-
Notifications
You must be signed in to change notification settings - Fork 8
게시글 API 구현 #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
leesewon00
merged 25 commits into
solid-connection:main
from
leesewon00:feat/49-create-post-api
Aug 10, 2024
Merged
게시글 API 구현 #50
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
3744573
refactor: 엔티티 클래스에서 빌더패턴 대신 생성자 사용
leesewon00 2e34feb
feat: 연관관계 편의 메소드 작성
leesewon00 e211a17
feat: 커뮤니티 관련 DTO 정의
leesewon00 bd4f0bc
feat: 커뮤니티 레포지토리 정의
leesewon00 112efca
feat: 커뮤니티 서비스 로직 추가
leesewon00 bd7a7b9
feat: 재귀 쿼리를 위한 Transient 필드 추가 및 댓글 서비스 로직 추가
leesewon00 2839697
feat: 커뮤니티 컨트롤러 로직 추가
leesewon00 ae198ed
feat: 커뮤니티 예외 추가
leesewon00 213320f
feat: 게시글 조회수 동시성 처리 로직 추가
leesewon00 2f94da2
feat: 게시판 데이터 추가
leesewon00 4eee103
feat: Mockito 의존성 추가
leesewon00 027d0b3
test: 커뮤니티 레포지토리 테스트 추가
leesewon00 ebd7735
test: 커뮤니티 서비스 테스트 추가
leesewon00 311d870
test: 게시글 조회수 동시성 처리 테스트 추가
leesewon00 494f153
feat: BaseEntity 동작을 위해 @EnableScheduling 어노테이션 추가
leesewon00 f47170e
feat: 로컬 환경에서 도커 컨테이너 빌드 자동화하는 쉘 스크립트 작성
leesewon00 cc073a4
refactor: BoardCode 불일치 문제 해결
leesewon00 4178bcc
refactor: 함수명 컨벤션에 따라 수정
leesewon00 43962ac
refactor: 불필요한 Getter 삭제
leesewon00 0f4fcbd
feat: 스케줄링 작업 비동기로 전환
leesewon00 7f69f5b
feat: 조회수 갱신 작업 비동기로 전환
leesewon00 e295a58
feat: 조회수 조작 막는 코드 추가
leesewon00 495dc58
test: 조회수 조작 막는 테스트코드 추가
leesewon00 a3de0d8
refactor: 재사용성을 고려하여 RedisService 함수 리팩토링
leesewon00 fd0e2a6
refactor: 중복코드 RedisUtils 함수화
leesewon00 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e | ||
|
|
||
| echo "Starting all docker containers..." | ||
| docker-compose -f docker-compose.local.yml down | ||
|
|
||
| echo "Pruning unused Docker images..." | ||
| docker image prune -f | ||
|
|
||
| echo "Containers are up and running." | ||
| docker-compose ps -a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #!/bin/bash | ||
|
|
||
| # 명령이 0이 아닌 종료값을 가질때 즉시 종료 | ||
| set -e | ||
|
|
||
| if [ ! -d "mysql_data_local" ]; then | ||
| echo "mysql_data_local 디렉토리가 없습니다. 디렉토리를 생성합니다." | ||
| mkdir -p mysql_data_local | ||
| fi | ||
|
|
||
| if [ ! -d "redis_data_local" ]; then | ||
| echo "redis_data_local 디렉토리가 없습니다. 디렉토리를 생성합니다." | ||
| mkdir -p redis_data_local | ||
| fi | ||
|
|
||
| echo "Starting all docker containers..." | ||
| docker-compose -f docker-compose.local.yml up -d | ||
|
|
||
| echo "Pruning unused Docker images..." | ||
| docker image prune -f | ||
|
|
||
| echo "Containers are up and running." | ||
| docker-compose ps -a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
src/main/java/com/example/solidconnection/board/controller/BoardController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package com.example.solidconnection.board.controller; | ||
|
|
||
| import com.example.solidconnection.board.service.BoardService; | ||
| import com.example.solidconnection.post.dto.BoardFindPostResponse; | ||
| import com.example.solidconnection.type.BoardCode; | ||
| import io.swagger.v3.oas.annotations.security.SecurityRequirement; | ||
| import io.swagger.v3.oas.annotations.security.SecurityRequirements; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| import static com.example.solidconnection.config.swagger.SwaggerConfig.ACCESS_TOKEN; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/communities") | ||
| @SecurityRequirements | ||
| @SecurityRequirement(name = ACCESS_TOKEN) | ||
| public class BoardController { | ||
|
|
||
| private final BoardService boardService; | ||
|
|
||
| // todo: 회원별로 접근 가능한 게시판 목록 조회 기능 개발 | ||
| @GetMapping() | ||
| public ResponseEntity<?> findAccessibleCodes() { | ||
| List<String> accessibleCodeList = new ArrayList<>(); | ||
| for (BoardCode boardCode : BoardCode.values()) { | ||
| accessibleCodeList.add(String.valueOf(boardCode)); | ||
| } | ||
| return ResponseEntity.ok().body(accessibleCodeList); | ||
| } | ||
|
|
||
| @GetMapping("/{code}") | ||
| public ResponseEntity<?> findPostsByCodeAndCategory( | ||
| @PathVariable(value = "code") String code, | ||
| @RequestParam(value = "category", defaultValue = "전체") String category) { | ||
|
|
||
| List<BoardFindPostResponse> postsByCodeAndPostCategory = boardService | ||
| .findPostsByCodeAndPostCategory(code, category); | ||
| return ResponseEntity.ok().body(postsByCodeAndPostCategory); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
src/main/java/com/example/solidconnection/board/dto/PostFindBoardResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.example.solidconnection.board.dto; | ||
|
|
||
| import com.example.solidconnection.board.domain.Board; | ||
|
|
||
| public record PostFindBoardResponse( | ||
| String code, | ||
| String koreanName | ||
| ) { | ||
| public static PostFindBoardResponse from(Board board) { | ||
| return new PostFindBoardResponse( | ||
| board.getCode(), | ||
| board.getKoreanName() | ||
| ); | ||
| } | ||
| } |
30 changes: 30 additions & 0 deletions
30
src/main/java/com/example/solidconnection/board/repository/BoardRepository.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.example.solidconnection.board.repository; | ||
|
|
||
| import com.example.solidconnection.board.domain.Board; | ||
| import com.example.solidconnection.custom.exception.CustomException; | ||
| import com.example.solidconnection.custom.exception.ErrorCode; | ||
| import org.springframework.data.jpa.repository.EntityGraph; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.data.repository.query.Param; | ||
| import org.springframework.stereotype.Repository; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_BOARD_CODE; | ||
|
|
||
| @Repository | ||
| public interface BoardRepository extends JpaRepository<Board, String> { | ||
|
|
||
| @EntityGraph(attributePaths = {"postList"}) | ||
| Optional<Board> findBoardByCode(@Param("code") String code); | ||
|
|
||
| default Board getByCodeUsingEntityGraph(String code) { | ||
| return findBoardByCode(code) | ||
| .orElseThrow(() -> new CustomException(ErrorCode.INVALID_BOARD_CODE)); | ||
| } | ||
|
|
||
| default Board getByCode(String code) { | ||
| return findById(code) | ||
| .orElseThrow(() -> new CustomException(INVALID_BOARD_CODE)); | ||
| } | ||
| } |
59 changes: 59 additions & 0 deletions
59
src/main/java/com/example/solidconnection/board/service/BoardService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| package com.example.solidconnection.board.service; | ||
|
|
||
| import com.example.solidconnection.board.domain.Board; | ||
| import com.example.solidconnection.board.repository.BoardRepository; | ||
| import com.example.solidconnection.custom.exception.CustomException; | ||
| import com.example.solidconnection.custom.exception.ErrorCode; | ||
| import com.example.solidconnection.post.domain.Post; | ||
| import com.example.solidconnection.post.dto.BoardFindPostResponse; | ||
| import com.example.solidconnection.type.BoardCode; | ||
| import com.example.solidconnection.type.PostCategory; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class BoardService { | ||
| private final BoardRepository boardRepository; | ||
|
|
||
| private String validateCode(String code) { | ||
| try { | ||
| return String.valueOf(BoardCode.valueOf(code)); | ||
| } catch (IllegalArgumentException ex) { | ||
| throw new CustomException(ErrorCode.INVALID_BOARD_CODE); | ||
| } | ||
| } | ||
|
|
||
| private PostCategory validatePostCategory(String postCategory) { | ||
| try { | ||
| return PostCategory.valueOf(postCategory); | ||
| } catch (IllegalArgumentException ex) { | ||
| throw new CustomException(ErrorCode.INVALID_POST_CATEGORY); | ||
| } | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public List<BoardFindPostResponse> findPostsByCodeAndPostCategory(String code, String category) { | ||
|
|
||
| String boardCode = validateCode(code); | ||
| PostCategory postCategory = validatePostCategory(category); | ||
|
|
||
| Board board = boardRepository.getByCodeUsingEntityGraph(boardCode); | ||
| List<Post> postList = getPostListByPostCategory(board.getPostList(), postCategory); | ||
|
|
||
| return BoardFindPostResponse.from(postList); | ||
| } | ||
|
|
||
| private List<Post> getPostListByPostCategory(List<Post> postList, PostCategory postCategory) { | ||
| if (postCategory.equals(PostCategory.전체)) { | ||
| return postList; | ||
| } | ||
| return postList.stream() | ||
| .filter(post -> post.getCategory().equals(postCategory)) | ||
| .collect(Collectors.toList()); | ||
| } | ||
| } |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/example/solidconnection/comment/dto/PostFindCommentResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package com.example.solidconnection.comment.dto; | ||
|
|
||
| import com.example.solidconnection.entity.Comment; | ||
| import com.example.solidconnection.siteuser.dto.PostFindSiteUserResponse; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public record PostFindCommentResponse( | ||
| Long id, | ||
| Long parentId, | ||
| String content, | ||
| Boolean isOwner, | ||
| LocalDateTime createdAt, | ||
| LocalDateTime updatedAt, | ||
| PostFindSiteUserResponse postFindSiteUserResponse | ||
|
|
||
| ) { | ||
| public static PostFindCommentResponse from(Boolean isOwner, Comment comment) { | ||
| return new PostFindCommentResponse( | ||
| comment.getId(), | ||
| getParentCommentId(comment), | ||
| comment.getContent(), | ||
| isOwner, | ||
| comment.getCreatedAt(), | ||
| comment.getUpdatedAt(), | ||
| PostFindSiteUserResponse.from(comment.getSiteUser()) | ||
| ); | ||
| } | ||
|
|
||
| private static Long getParentCommentId(Comment comment) { | ||
| if (comment.getParentComment() != null) { | ||
| return comment.getParentComment().getId(); | ||
| } | ||
| return null; | ||
| } | ||
| } |
33 changes: 33 additions & 0 deletions
33
src/main/java/com/example/solidconnection/comment/repository/CommentRepository.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.example.solidconnection.comment.repository; | ||
|
|
||
| import com.example.solidconnection.entity.Comment; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.data.jpa.repository.Query; | ||
| import org.springframework.data.repository.query.Param; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public interface CommentRepository extends JpaRepository<Comment, Long> { | ||
|
|
||
| @Query(value = """ | ||
| WITH RECURSIVE CommentTree AS ( | ||
| SELECT | ||
| id, parent_id, post_id, site_user_id, content, | ||
| created_at, updated_at, | ||
| 0 AS level, CAST(id AS CHAR(255)) AS path | ||
| FROM comment | ||
| WHERE post_id = :postId AND parent_id IS NULL | ||
| UNION ALL | ||
| SELECT | ||
| c.id, c.parent_id, c.post_id, c.site_user_id, c.content, | ||
| c.created_at, c.updated_at, | ||
| ct.level + 1, CONCAT(ct.path, '->', c.id) | ||
| FROM comment c | ||
| INNER JOIN CommentTree ct ON c.parent_id = ct.id | ||
| ) | ||
| SELECT * FROM CommentTree | ||
| ORDER BY path | ||
| """, nativeQuery = true) | ||
| List<Comment> findCommentTreeByPostId(@Param("postId") Long postId); | ||
|
Comment on lines
+12
to
+31
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JPQL 공부 열심히 하셨네요👍🔥 |
||
|
|
||
| } | ||
29 changes: 29 additions & 0 deletions
29
src/main/java/com/example/solidconnection/comment/service/CommentService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package com.example.solidconnection.comment.service; | ||
|
|
||
| import com.example.solidconnection.comment.repository.CommentRepository; | ||
| import com.example.solidconnection.comment.dto.PostFindCommentResponse; | ||
| import com.example.solidconnection.entity.Comment; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class CommentService { | ||
|
|
||
| private final CommentRepository commentRepository; | ||
|
|
||
| private Boolean isOwner(Comment comment, String email) { | ||
| return comment.getSiteUser().getEmail().equals(email); | ||
| } | ||
|
|
||
|
|
||
| public List<PostFindCommentResponse> findCommentsByPostId(String email, Long postId) { | ||
| return commentRepository.findCommentTreeByPostId(postId) | ||
| .stream() | ||
| .map(comment -> PostFindCommentResponse.from(isOwner(comment, email), comment)) | ||
| .collect(Collectors.toList()); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💭 이것은 단순 궁금증 ㅎㅎ
함수 안에서 개행은 어떤 규칙으로 하시는지 궁금합니다~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
별도의 규칙을 따르면서 작성하지는 않았습니다.
컨트롤러에서 받는 파라미터가 많아짐에 따라서 개행하였고,
가독성을 위해서 컨트롤러의 다른 함수들도 모두 파라미터별로 개행하였습니다.