Skip to content

Commit b28b182

Browse files
authored
Merge pull request #168 from lass9436/feature7
[이영민] step-8 페이징 구현하기
2 parents dc9a73e + 31ff3ca commit b28b182

File tree

13 files changed

+345
-13
lines changed

13 files changed

+345
-13
lines changed

.github/workflows/aws.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Build and Deploy Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- lass9436
7+
8+
jobs:
9+
build_and_deploy:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v2
15+
16+
- name: Set up Docker Buildx
17+
uses: docker/setup-buildx-action@v2
18+
19+
- name: Build Docker image
20+
run: docker build -t jsp-cafe:latest .
21+
22+
- name: Save Docker image to file
23+
run: docker save jsp-cafe:latest | gzip > jsp-cafe.tar.gz
24+
25+
- name: Upload Docker image file
26+
uses: actions/upload-artifact@v3
27+
with:
28+
name: docker-image
29+
path: jsp-cafe.tar.gz
30+
31+
- name: Deploy to EC2
32+
env:
33+
SSH_PRIVATE_KEY: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
34+
EC2_USER: ${{ secrets.EC2_USER }}
35+
EC2_HOST: ${{ secrets.EC2_HOST }}
36+
run: |
37+
# Save the SSH private key to a file
38+
echo "$SSH_PRIVATE_KEY" > private_key.pem
39+
chmod 600 private_key.pem
40+
41+
# Transfer the Docker image file to EC2 server
42+
scp -i private_key.pem jsp-cafe.tar.gz $EC2_USER@$EC2_HOST:/tmp/
43+
44+
# Connect to EC2 server and run Docker commands
45+
ssh -i private_key.pem $EC2_USER@$EC2_HOST << 'EOF'
46+
docker load < /tmp/jsp-cafe.tar.gz
47+
docker stop jsp-cafe || true
48+
docker rm jsp-cafe || true
49+
docker run -d --name jsp-cafe -p 8080:8080 jsp-cafe:latest
50+
EOF

Dockerfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# 빌드 스테이지: Gradle과 JDK 17을 사용하여 WAR 파일 빌드
2+
FROM gradle:7.6.1-jdk17 AS build
3+
WORKDIR /app
4+
COPY . .
5+
RUN ./gradlew clean build
6+
7+
# 실행 스테이지: Tomcat 10.1.26과 JDK 17을 사용하여 WAR 실행
8+
FROM tomcat:10.1.26-jdk17
9+
WORKDIR /usr/local/tomcat/webapps/
10+
COPY --from=build /app/build/libs/*.war ./ROOT.war
11+
12+
# 8080 포트 노출 (Tomcat 기본 포트)
13+
EXPOSE 8080
14+
15+
# Tomcat 실행
16+
CMD ["catalina.sh", "run"]

src/main/java/lass9436/comment/model/CommentRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ public interface CommentRepository {
1212
void deleteByCommentSeq(long commentSeq);
1313

1414
List<Comment> findByQuestionSeq(long questionSeq);
15+
16+
List<Comment> findRangeByQuestionSeq(long questionSeq, long startCommentSeq, int count);
17+
18+
long countByQuestionSeq(long questionSeq);
1519
}

src/main/java/lass9436/comment/model/CommentRepositoryDBImpl.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,52 @@ public List<Comment> findByQuestionSeq(long questionSeq) {
122122
return comments;
123123
}
124124

125+
@Override
126+
public List<Comment> findRangeByQuestionSeq(long questionSeq, long startCommentSeq, int count) {
127+
String sql = "SELECT * FROM comments WHERE questionSeq = ? AND commentSeq < ? AND useYn = 'Y' ORDER BY commentSeq DESC LIMIT ?";
128+
List<Comment> comments = new ArrayList<>();
129+
130+
try (Connection conn = Database.getConnection();
131+
PreparedStatement ps = conn.prepareStatement(sql)) {
132+
133+
ps.setLong(1, questionSeq);
134+
ps.setLong(2, startCommentSeq);
135+
ps.setInt(3, count);
136+
137+
try (ResultSet rs = ps.executeQuery()) {
138+
while (rs.next()) {
139+
comments.add(mapRow(rs));
140+
}
141+
}
142+
} catch (SQLException e) {
143+
e.printStackTrace();
144+
}
145+
146+
return comments;
147+
}
148+
149+
@Override
150+
public long countByQuestionSeq(long questionSeq) {
151+
String query = "SELECT COUNT(*) FROM comments WHERE questionSeq = ? and useYn = 'Y'";
152+
long count = 0;
153+
154+
try (Connection connection = Database.getConnection();
155+
PreparedStatement ps = connection.prepareStatement(query);) {
156+
157+
ps.setLong(1, questionSeq);
158+
ResultSet resultSet = ps.executeQuery();
159+
160+
if (resultSet.next()) {
161+
count = resultSet.getLong(1);
162+
}
163+
164+
} catch (SQLException e) {
165+
e.printStackTrace();
166+
}
167+
168+
return count;
169+
}
170+
125171
private Comment mapRow(ResultSet rs) throws SQLException {
126172
Comment comment = new Comment();
127173
comment.setCommentSeq(rs.getLong("commentSeq"));

src/main/java/lass9436/comment/model/CommentRepositoryImpl.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public void deleteByCommentSeq(long commentSeq) {
3333
commentStore.remove(commentSeq);
3434
}
3535

36+
@Override
37+
public long countByQuestionSeq(long questionSeq) {
38+
return 0;
39+
}
40+
3641
@Override
3742
public List<Comment> findByQuestionSeq(long questionSeq) {
3843
List<Comment> comments = new ArrayList<>();
@@ -43,5 +48,26 @@ public List<Comment> findByQuestionSeq(long questionSeq) {
4348
}
4449
return comments;
4550
}
51+
52+
@Override
53+
public List<Comment> findRangeByQuestionSeq(long questionSeq, long startCommentSeq, int count) {
54+
List<Comment> result = new ArrayList<>();
55+
56+
// 모든 댓글을 순회하며 조건에 맞는 댓글을 찾습니다.
57+
for (Comment comment : commentStore.values()) {
58+
// 해당 질문의 댓글이고, startCommentSeq보다 작은 commentSeq를 가진 경우
59+
if (comment.getQuestionSeq() == questionSeq && comment.getCommentSeq() < startCommentSeq) {
60+
result.add(comment);
61+
}
62+
}
63+
64+
// commentSeq를 기준으로 내림차순 정렬 (최신 댓글이 먼저 오도록)
65+
result.sort((c1, c2) -> Long.compare(c2.getCommentSeq(), c1.getCommentSeq()));
66+
67+
// count 개수만큼만 반환
68+
return result.stream()
69+
.limit(count)
70+
.toList();
71+
}
4672
}
4773

src/main/java/lass9436/comment/servlet/CommentServlet.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package lass9436.comment.servlet;
22

33
import java.io.IOException;
4+
import java.util.List;
45

56
import com.fasterxml.jackson.databind.ObjectMapper;
67
import jakarta.servlet.ServletConfig;
@@ -23,6 +24,23 @@ public void init(ServletConfig config) throws ServletException {
2324
commentRepository = (CommentRepository)config.getServletContext().getAttribute("commentRepository");
2425
}
2526

27+
@Override
28+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
29+
long questionSeq = Long.parseLong(req.getParameter("questionSeq"));
30+
long startCommentSeq = Long.parseLong(req.getParameter("startCommentSeq"));
31+
int count = 5; // 또는 req.getParameter("count")로 받아올 수 있습니다.
32+
33+
List<Comment> comments = commentRepository.findRangeByQuestionSeq(questionSeq, startCommentSeq, count);
34+
35+
ObjectMapper objectMapper = new ObjectMapper();
36+
String jsonResponse = objectMapper.writeValueAsString(comments);
37+
38+
resp.setContentType("application/json");
39+
resp.setCharacterEncoding("UTF-8");
40+
resp.getWriter().write(jsonResponse);
41+
resp.setStatus(HttpServletResponse.SC_OK);
42+
}
43+
2644
@Override
2745
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
2846
String contents = req.getParameter("contents");

src/main/java/lass9436/config/Database.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
public class Database {
1313

14-
private static final String url = "jdbc:mysql://localhost:3306/jsp_cafe";
14+
private static final String url = "jdbc:mysql://host.docker.internal:3306/jsp_cafe";
1515
private static final String user = "user";
1616
private static final String password = "1234";
1717
private static final MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();

src/main/java/lass9436/question/model/QuestionRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ public interface QuestionRepository {
1212
void deleteByQuestionSeq(long questionSeq); // Delete by questionSeq
1313

1414
Question findByTitle(String title); // Read by title
15+
16+
List<Question> findAllPageable(long page, long pageSize);
17+
18+
long count();
1519
}

src/main/java/lass9436/question/model/QuestionRepositoryDBImpl.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,49 @@ public Question findByTitle(String title) {
127127
return question;
128128
}
129129

130+
@Override
131+
public List<Question> findAllPageable(long page, long pageSize) {
132+
String query = "SELECT * FROM questions WHERE useYn = 'Y' ORDER BY questionSeq DESC LIMIT ? OFFSET ?";
133+
List<Question> questions = new ArrayList<>();
134+
135+
try (Connection connection = Database.getConnection();
136+
PreparedStatement statement = connection.prepareStatement(query)) {
137+
138+
statement.setLong(1, pageSize);
139+
statement.setLong(2, (page - 1) * pageSize);
140+
ResultSet resultSet = statement.executeQuery();
141+
142+
while (resultSet.next()) {
143+
questions.add(mapRowToQuestion(resultSet));
144+
}
145+
146+
} catch (SQLException e) {
147+
e.printStackTrace();
148+
}
149+
150+
return questions;
151+
}
152+
153+
@Override
154+
public long count() {
155+
String query = "SELECT COUNT(*) FROM questions WHERE useYn = 'Y'";
156+
long count = 0;
157+
158+
try (Connection connection = Database.getConnection();
159+
PreparedStatement statement = connection.prepareStatement(query);
160+
ResultSet resultSet = statement.executeQuery()) {
161+
162+
if (resultSet.next()) {
163+
count = resultSet.getLong(1);
164+
}
165+
166+
} catch (SQLException e) {
167+
e.printStackTrace();
168+
}
169+
170+
return count;
171+
}
172+
130173
private Question mapRowToQuestion(ResultSet resultSet) throws SQLException {
131174
Question question = new Question();
132175
question.setQuestionSeq(resultSet.getLong("questionSeq"));

src/main/java/lass9436/question/model/QuestionRepositoryImpl.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,22 @@ public Question findByTitle(String title) {
5252
.findFirst()
5353
.orElse(null);
5454
}
55+
56+
@Override
57+
public List<Question> findAllPageable(long page, long pageSize) {
58+
long startIndex = (page - 1) * pageSize;
59+
return questions.stream()
60+
.filter(q -> "Y".equals(q.getUseYn())) // useYn이 'Y'인 질문만 선택
61+
.sorted((q1, q2) -> Long.compare(q2.getQuestionSeq(), q1.getQuestionSeq())) // questionSeq 내림차순 정렬
62+
.skip(startIndex)
63+
.limit(pageSize)
64+
.toList();
65+
}
66+
67+
@Override
68+
public long count() {
69+
return questions.stream()
70+
.filter(q -> "Y".equals(q.getUseYn())) // useYn이 'Y'인 질문만 카운트
71+
.count();
72+
}
5573
}

src/main/java/lass9436/question/servlet/QuestionPageServlet.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,35 @@ private String handleRegister(HttpServletRequest req, HttpServletResponse resp)
6262
}
6363

6464
private String handleList(HttpServletRequest req, HttpServletResponse resp) {
65-
req.setAttribute("questions", questionRepository.findAll());
65+
long page = getPageParameter(req.getParameter("page"));
66+
long pageSize = 15;
67+
req.setAttribute("questions", questionRepository.findAllPageable(page, pageSize));
68+
req.setAttribute("maxPage", (long) Math.ceil((double) questionRepository.count() / pageSize));
6669
return "/list.jsp";
6770
}
6871

72+
private long getPageParameter(String pageParam) {
73+
if (pageParam == null || pageParam.trim().isEmpty()) {
74+
return 1;
75+
}
76+
try {
77+
long page = Long.parseLong(pageParam);
78+
return page > 0 ? page : 1;
79+
} catch (NumberFormatException e) {
80+
return 1;
81+
}
82+
}
83+
6984
private String handleDetail(HttpServletRequest req, HttpServletResponse resp) {
7085
long seq = Long.parseLong(req.getParameter("seq"));
7186
Question question = questionRepository.findByQuestionSeq(seq);
72-
List<Comment> comments = commentRepository.findByQuestionSeq(seq);
87+
List<Comment> comments = commentRepository.findRangeByQuestionSeq(seq, Long.MAX_VALUE, 5);
88+
long lastCommentSeq = !comments.isEmpty() ? comments.get(comments.size() - 1).getCommentSeq() : 0;
89+
long count = commentRepository.countByQuestionSeq(seq);
7390
req.setAttribute("question", question);
7491
req.setAttribute("comments", comments);
92+
req.setAttribute("count", count);
93+
req.setAttribute("lastCommentSeq", lastCommentSeq);
7594
return "/detail.jsp";
7695
}
7796

0 commit comments

Comments
 (0)