Skip to content

Commit c381e0e

Browse files
committed
Merge branch 'develop' into feature/login
2 parents cda57b4 + 11b4cd6 commit c381e0e

File tree

28 files changed

+1193
-91
lines changed

28 files changed

+1193
-91
lines changed

.github/workflows/ci.cd.prod.yml

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,17 @@ jobs:
3434
java-version: 21
3535
distribution: 'temurin'
3636

37-
# application.yml 생성
37+
# application.yml 운영 환경 용 생성
3838
- name: Make application.yml
3939
run: |
4040
mkdir -p ./src/main/resources
4141
cd ./src/main/resources
4242
touch ./application.yml
4343
touch ./application-secret.yml
4444
45-
echo "${{ secrets.APPLICATION }}" | base64 --decode > ./application.yml
46-
echo "${{ secrets.SECRET }}" | base64 --decode > ./application-secret.yml
45+
echo "${{ secrets.production_COMMON }}" | base64 --decode > ./application.yml
46+
echo "${{ secrets.production_PROD }}" | base64 --decode > ./application-prod.yml
47+
echo "${{ secrets.production_SECRET }}" | base64 --decode > ./application-prod-secret.yml
4748
4849
# Gradle cache 설정
4950
- name: Cache Gradle packages
@@ -53,11 +54,34 @@ jobs:
5354
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
5455
restore-keys: ${{ runner.os }}-gradle
5556

56-
# Gradle build (우선 Test 제외)
57-
- name: Build with Gradle
58-
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
59-
with:
60-
arguments: clean build -x test
57+
- name: MySQL 컨테이너 실행
58+
run: |
59+
docker run --name log4u-mysql \
60+
-e MYSQL_ROOT_PASSWORD=root \
61+
-e MYSQL_DATABASE=log4u \
62+
-e MYSQL_USER=dev \
63+
-e MYSQL_PASSWORD=devcos4-team08 \
64+
-d \
65+
-p 3307:3306 \
66+
mysql:8.0.33
67+
68+
- name: Build and analyze
69+
env:
70+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
71+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
72+
DB_URL: jdbc:mysql://localhost:3307/log4u
73+
DB_USERNAME: dev
74+
DB_PASSWORD: devcos4-team08
75+
76+
# 테스트용으로 dev 프로필 사용(시크릿 제외하고 prod 와 동일)
77+
run: |
78+
chmod +x ./gradlew
79+
./gradlew build jacocoTestReport -Pprofile=dev
80+
81+
- name: Docker MySQL 종료 및 제거
82+
run: |
83+
docker stop log4u-mysql
84+
docker rm log4u-mysql
6185
6286
deploy:
6387
runs-on: ubuntu-latest

pull_request_template.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## 📌 PR 제목
2+
<!-- 간결하고 명확한 PR 제목 작성 -->
3+
4+
## ✨ 변경 사항
5+
<!-- 이번 PR에서 변경된 내용을 요약하여 설명 -->
6+
- 변경 사항 1
7+
- 변경 사항 2
8+
- 변경 사항 3
9+
10+
## 🔍 변경 이유
11+
<!-- 이번 PR이 필요한 이유 또는 해결하는 문제 -->
12+
13+
## ✅ 체크리스트
14+
<!-- PR을 제출하기 전에 확인해야 할 사항 -->
15+
- [ ] 코드가 정상적으로 동작하는지 확인
16+
- [ ] 관련 테스트 코드 작성 및 통과 여부 확인
17+
- [ ] 문서화(README 등) 필요 여부 확인 및 반영
18+
- [ ] 리뷰어가 알아야 할 사항 추가 설명
19+
20+
## 📸 스크린샷 (선택)
21+
<!-- UI 변경이 포함된 경우 관련 스크린샷 첨부 -->
22+
23+
## 📌 참고 사항
24+
<!-- 기타 리뷰어가 참고해야 할 사항 -->

src/main/java/com/example/log4u/domain/comment/controller/CommentController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
import org.springframework.http.ResponseEntity;
44
import org.springframework.web.bind.annotation.DeleteMapping;
5+
import org.springframework.web.bind.annotation.GetMapping;
56
import org.springframework.web.bind.annotation.PathVariable;
67
import org.springframework.web.bind.annotation.PostMapping;
78
import org.springframework.web.bind.annotation.RequestBody;
89
import org.springframework.web.bind.annotation.RequestMapping;
10+
import org.springframework.web.bind.annotation.RequestParam;
911
import org.springframework.web.bind.annotation.RestController;
1012

13+
import com.example.log4u.common.dto.PageResponse;
1114
import com.example.log4u.domain.comment.dto.request.CommentCreateRequestDto;
1215
import com.example.log4u.domain.comment.dto.response.CommentCreateResponseDto;
16+
import com.example.log4u.domain.comment.dto.response.CommentResponseDto;
1317
import com.example.log4u.domain.comment.service.CommentService;
1418

1519
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -39,4 +43,14 @@ public ResponseEntity<Void> deleteComment(@PathVariable Long commentId) {
3943
commentService.deleteComment(userId, commentId);
4044
return ResponseEntity.noContent().build();
4145
}
46+
47+
@GetMapping("/{diaryId}")
48+
public ResponseEntity<PageResponse<CommentResponseDto>> getCommentListByDiary(
49+
@PathVariable Long diaryId,
50+
@RequestParam(required = false) Long cursorCommentId,
51+
@RequestParam(defaultValue = "5") int size
52+
) {
53+
PageResponse<CommentResponseDto> response = commentService.getCommentListByDiary(diaryId, cursorCommentId, size);
54+
return ResponseEntity.ok(response);
55+
}
4256
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.example.log4u.domain.comment.dto.response;
2+
3+
import com.example.log4u.domain.comment.entity.Comment;
4+
5+
public record CommentResponseDto(
6+
Long commentId,
7+
String content
8+
) {
9+
public static CommentResponseDto of(Comment comment) {
10+
return new CommentResponseDto(
11+
comment.getCommentId(),
12+
comment.getContent()
13+
);
14+
}
15+
}

src/main/java/com/example/log4u/domain/comment/entity/Comment.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ public class Comment extends BaseEntity {
3030
@Column(nullable = false)
3131
private Long diaryId;
3232

33+
@Column(nullable = false)
3334
private String content;
3435
}
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.example.log4u.domain.comment.repository;
22

3+
import java.time.LocalDateTime;
4+
import java.util.List;
5+
6+
import org.springframework.data.domain.Pageable;
37
import org.springframework.data.jpa.repository.JpaRepository;
8+
import org.springframework.data.jpa.repository.Query;
9+
import org.springframework.data.repository.query.Param;
410

511
import com.example.log4u.domain.comment.entity.Comment;
612

7-
public interface CommentRepository extends JpaRepository<Comment, Long> {
8-
13+
public interface CommentRepository extends JpaRepository<Comment, Long>, CommentRepositoryCustom {
914
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.example.log4u.domain.comment.repository;
2+
3+
import org.springframework.data.domain.Pageable;
4+
import org.springframework.data.domain.Slice;
5+
6+
import com.example.log4u.domain.comment.entity.Comment;
7+
8+
public interface CommentRepositoryCustom {
9+
10+
Slice<Comment> findByDiaryIdWithCursor(Long diaryId, Long cursorCommentId, Pageable pageable);
11+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.example.log4u.domain.comment.repository;
2+
3+
import static com.example.log4u.domain.comment.entity.QComment.*;
4+
5+
import java.util.List;
6+
7+
import org.springframework.data.domain.Pageable;
8+
import org.springframework.data.domain.Slice;
9+
import org.springframework.data.domain.SliceImpl;
10+
import org.springframework.stereotype.Repository;
11+
12+
import com.example.log4u.domain.comment.entity.Comment;
13+
import com.querydsl.jpa.impl.JPAQueryFactory;
14+
15+
import lombok.RequiredArgsConstructor;
16+
17+
@Repository
18+
@RequiredArgsConstructor
19+
public class CommentRepositoryImpl implements CommentRepositoryCustom {
20+
21+
private final JPAQueryFactory queryFactory;
22+
23+
@Override
24+
public Slice<Comment> findByDiaryIdWithCursor(Long diaryId, Long cursorCommentId, Pageable pageable) {
25+
List<Comment> result = queryFactory
26+
.selectFrom(comment)
27+
.where(
28+
comment.diaryId.eq(diaryId),
29+
cursorCommentId != null ? comment.commentId.lt(cursorCommentId) : null
30+
)
31+
.orderBy(comment.commentId.desc())
32+
.limit(pageable.getPageSize() + 1) // 커서 기반 페이징
33+
.fetch();
34+
35+
boolean hasNext = result.size() > pageable.getPageSize();
36+
List<Comment> content = hasNext ? result.subList(0, pageable.getPageSize()) : result;
37+
38+
return new SliceImpl<>(content, pageable, hasNext);
39+
}
40+
}

src/main/java/com/example/log4u/domain/comment/service/CommentService.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
package com.example.log4u.domain.comment.service;
22

3+
import java.util.List;
4+
5+
import org.springframework.data.domain.PageRequest;
6+
import org.springframework.data.domain.Pageable;
7+
import org.springframework.data.domain.Slice;
8+
import org.springframework.data.domain.SliceImpl;
39
import org.springframework.stereotype.Service;
410
import org.springframework.transaction.annotation.Transactional;
511

12+
import com.example.log4u.common.dto.PageResponse;
613
import com.example.log4u.domain.comment.dto.request.CommentCreateRequestDto;
714
import com.example.log4u.domain.comment.dto.response.CommentCreateResponseDto;
15+
import com.example.log4u.domain.comment.dto.response.CommentResponseDto;
816
import com.example.log4u.domain.comment.entity.Comment;
917
import com.example.log4u.domain.comment.exception.NotFoundCommentException;
1018
import com.example.log4u.domain.comment.exception.UnauthorizedAccessException;
@@ -22,7 +30,7 @@ public class CommentService {
2230

2331
@Transactional
2432
public CommentCreateResponseDto addComment(Long userId, CommentCreateRequestDto requestDto) {
25-
checkDiaryExists(requestDto);
33+
checkDiaryExists(requestDto.diaryId());
2634
Comment comment = requestDto.toEntity(userId);
2735
commentRepository.save(comment);
2836
return CommentCreateResponseDto.of(comment);
@@ -35,8 +43,8 @@ public void deleteComment(Long userId, Long commentId) {
3543
commentRepository.delete(comment);
3644
}
3745

38-
private void checkDiaryExists(CommentCreateRequestDto requestDto) {
39-
diaryService.checkDiaryExists(requestDto.diaryId());
46+
private void checkDiaryExists(Long diaryId) {
47+
diaryService.checkDiaryExists(diaryId);
4048
}
4149

4250
private void validateCommentOwner(Long userId, Comment comment) {
@@ -49,4 +57,18 @@ private Comment getComment(Long commentId) {
4957
return commentRepository.findById(commentId)
5058
.orElseThrow(NotFoundCommentException::new);
5159
}
60+
61+
@Transactional(readOnly = true)
62+
public PageResponse<CommentResponseDto> getCommentListByDiary(Long diaryId, Long cursorCommentId, int size) {
63+
checkDiaryExists(diaryId);
64+
Pageable pageable = PageRequest.of(0, size);
65+
Slice<Comment> slice = commentRepository.findByDiaryIdWithCursor(diaryId, cursorCommentId, pageable);
66+
67+
List<CommentResponseDto> dtoList = slice.getContent().stream()
68+
.map(CommentResponseDto::of)
69+
.toList();
70+
71+
Long nextCursor = slice.hasNext() ? dtoList.getLast().commentId() : null;
72+
return PageResponse.of(new SliceImpl<>(dtoList, pageable, slice.hasNext()), nextCursor);
73+
}
5274
}

src/main/java/com/example/log4u/domain/diary/controller/DiaryController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ public ResponseEntity<Void> createDiary(
4545
public ResponseEntity<PageResponse<DiaryResponseDto>> searchDiaries(
4646
@RequestParam(required = false) String keyword,
4747
@RequestParam(defaultValue = "LATEST") SortType sort,
48-
@RequestParam(defaultValue = "0") int page
48+
@RequestParam(defaultValue = "0") int page,
49+
@RequestParam(defaultValue = "6") int size
4950
) {
5051
return ResponseEntity.ok(
51-
diaryService.searchDiaries(keyword, sort, page)
52+
diaryService.searchDiaries(keyword, sort, page, size)
5253
);
5354
}
5455

0 commit comments

Comments
 (0)