-
Notifications
You must be signed in to change notification settings - Fork 0
Test #1
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
base: develop
Are you sure you want to change the base?
Test #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,9 @@ | ||||||||||||
| package aibe.hosik.apply; | ||||||||||||
| package aibe.hosik.apply.repository; | ||||||||||||
|
|
||||||||||||
| import aibe.hosik.apply.entity.Apply; | ||||||||||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||||||||||
|
|
||||||||||||
| public interface ApplyRepository extends JpaRepository<Apply, Long> { | ||||||||||||
| // post id로 지원서 조회 | ||||||||||||
|
|
||||||||||||
|
Comment on lines
+7
to
+8
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. 🛠️ Refactor suggestion 코멘트만 있고 실제 메서드 구현이 없습니다 "post id로 지원서 조회"라는 코멘트가 있지만 실제 메서드가 구현되어 있지 않습니다. 모집글과 지원서 간의 연관관계를 처리하기 위해서는 이 기능이 필요할 것으로 보입니다. 아래와 같이 메서드를 구현하는 것이 좋을 것 같습니다: public interface ApplyRepository extends JpaRepository<Apply, Long> {
// post id로 지원서 조회
+ List<Apply> findByPostId(Long postId);
}📝 Committable suggestion
Suggested change
|
||||||||||||
| } | ||||||||||||
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,68 @@ | ||||||||||||||||||||||||||||||||||||||
| package aibe.hosik.post.controller; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.dto.PostDetailDTO; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.dto.PostRequestDTO; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.dto.PostResponseDTO; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.Post; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.service.PostService; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.skill.repository.PostSkillRepository; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.user.User; | ||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.user.UserRepository; | ||||||||||||||||||||||||||||||||||||||
| import io.swagger.v3.oas.annotations.Operation; | ||||||||||||||||||||||||||||||||||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||
| import org.apache.coyote.Response; | ||||||||||||||||||||||||||||||||||||||
| import org.springframework.http.ResponseEntity; | ||||||||||||||||||||||||||||||||||||||
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||||||||||||||||||||||||||||||||||||||
| import org.springframework.web.bind.annotation.*; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // 테스트 | ||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||
| @RestController | ||||||||||||||||||||||||||||||||||||||
| @RequestMapping("/api/posts") | ||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||
| @Tag(name = "Post", description = "모집글 API") // Swagger Tag | ||||||||||||||||||||||||||||||||||||||
| public class PostController { | ||||||||||||||||||||||||||||||||||||||
| private final PostService postService; | ||||||||||||||||||||||||||||||||||||||
| private final UserRepository userRepository; | ||||||||||||||||||||||||||||||||||||||
| private final PostSkillRepository postSkillRepository; | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+31
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. 🛠️ Refactor suggestion 컨트롤러에서 직접 Repository 접근은 지양하세요. 컨트롤러 레이어에서 직접 리포지토리 접근 로직을 서비스 계층으로 이동하는 것을 권장합니다: public class PostController {
private final PostService postService;
- private final UserRepository userRepository;
- private final PostSkillRepository postSkillRepository;
@PostMapping
public ResponseEntity<?> createPost(@RequestBody PostRequestDTO dto, @AuthenticationPrincipal User user){
Post createPost = postService.createPost(dto, user);
- // 스킬 조회
- List<String> skills = postSkillRepository.findSkillByPostId(createPost.getId());
// dto 반환
// TODO : currentCount 로직 구현 후 변환
- PostResponseDTO responseDTO = PostResponseDTO.from(createPost, skills, 0);
+ PostResponseDTO responseDTO = postService.getPostResponse(createPost);
return ResponseEntity.ok(responseDTO);
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Operation(summary="모집글 등록", description="모집글을 등록합니다.") | ||||||||||||||||||||||||||||||||||||||
| @PostMapping | ||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<?> createPost(@RequestBody PostRequestDTO dto, @AuthenticationPrincipal User user){ | ||||||||||||||||||||||||||||||||||||||
| Post createPost = postService.createPost(dto, user); | ||||||||||||||||||||||||||||||||||||||
| // 스킬 조회 | ||||||||||||||||||||||||||||||||||||||
| List<String> skills = postSkillRepository.findSkillByPostId(createPost.getId()); | ||||||||||||||||||||||||||||||||||||||
| // dto 반환 | ||||||||||||||||||||||||||||||||||||||
| // TODO : currentCount 로직 구현 후 변환 | ||||||||||||||||||||||||||||||||||||||
| PostResponseDTO responseDTO = PostResponseDTO.from(createPost, skills, 0); | ||||||||||||||||||||||||||||||||||||||
| return ResponseEntity.ok(responseDTO); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| // 테스트용 | ||||||||||||||||||||||||||||||||||||||
| @Operation(summary="모집글 등록 테스트", description="[TEST] 모집글을 등록합니다.") | ||||||||||||||||||||||||||||||||||||||
| @PostMapping("/mock") | ||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<?> createPostForSwagger(@RequestBody PostRequestDTO dto){ | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // 테스트용 userId | ||||||||||||||||||||||||||||||||||||||
| User mockUser = userRepository.findById(1L).orElseThrow(); | ||||||||||||||||||||||||||||||||||||||
| Post createPost = postService.createPost(dto, mockUser); | ||||||||||||||||||||||||||||||||||||||
| List<String> skills = postSkillRepository.findSkillByPostId(createPost.getId()); | ||||||||||||||||||||||||||||||||||||||
| PostResponseDTO responseDTO = PostResponseDTO.from(createPost, skills, 0); | ||||||||||||||||||||||||||||||||||||||
| return ResponseEntity.ok(responseDTO); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+45
to
+55
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. 🛠️ Refactor suggestion 테스트용 엔드포인트에 대한 보안 및 설계 개선이 필요합니다. 테스트용 엔드포인트는 다음과 같은 문제점이 있습니다:
다음과 같은 방법으로 개선할 수 있습니다:
+ @Profile({"dev", "test"}) // 개발 및 테스트 환경에서만 활성화
@Operation(summary="모집글 등록 테스트", description="[TEST] 모집글을 등록합니다.")
@PostMapping("/mock")
public ResponseEntity<?> createPostForSwagger(@RequestBody PostRequestDTO dto){
// 테스트용 userId
- User mockUser = userRepository.findById(1L).orElseThrow();
+ User mockUser = userRepository.findById(1L)
+ .orElseThrow(() -> new IllegalStateException("테스트용 사용자(ID: 1)가 존재하지 않습니다."));
// createPost 메서드를 재사용하여 중복 코드 제거
- Post createPost = postService.createPost(dto, mockUser);
- List<String> skills = postSkillRepository.findSkillByPostId(createPost.getId());
- PostResponseDTO responseDTO = PostResponseDTO.from(createPost, skills, 0);
- return ResponseEntity.ok(responseDTO);
+ return createPost(dto, mockUser);
}
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Operation(summary="모집글 조회", description = "모집글 목록을 조회합니다.") | ||||||||||||||||||||||||||||||||||||||
| @GetMapping | ||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<List<PostResponseDTO>> getAllPosts(){ | ||||||||||||||||||||||||||||||||||||||
| return ResponseEntity.ok(postService.getAllPosts()); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+58
to
+61
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. 🛠️ Refactor suggestion 페이지네이션 구현이 필요합니다.
다음과 같이 페이지네이션을 구현할 수 있습니다: @Operation(summary="모집글 조회", description = "모집글 목록을 조회합니다.")
@GetMapping
- public ResponseEntity<List<PostResponseDTO>> getAllPosts(){
- return ResponseEntity.ok(postService.getAllPosts());
+ public ResponseEntity<Page<PostResponseDTO>> getAllPosts(
+ @RequestParam(defaultValue = "0") int page,
+ @RequestParam(defaultValue = "10") int size,
+ @RequestParam(defaultValue = "id") String sortBy) {
+ Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy).descending());
+ return ResponseEntity.ok(postService.getAllPosts(pageable));
}
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @Operation(summary="모집글 상세 조회", description="모집글 게시글을 상세 조회합니다") | ||||||||||||||||||||||||||||||||||||||
| @GetMapping("/{postId}") | ||||||||||||||||||||||||||||||||||||||
| public ResponseEntity<PostDetailDTO> getPostDetail(@PathVariable Long postId){ | ||||||||||||||||||||||||||||||||||||||
| return ResponseEntity.ok(postService.getPostDetail(postId)); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+63
to
+67
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. 🛠️ Refactor suggestion 예외 처리가 필요합니다.
다음과 같이 예외 처리를 추가할 수 있습니다: @Operation(summary="모집글 상세 조회", description="모집글 게시글을 상세 조회합니다")
@GetMapping("/{postId}")
public ResponseEntity<PostDetailDTO> getPostDetail(@PathVariable Long postId){
+ try {
return ResponseEntity.ok(postService.getPostDetail(postId));
+ } catch (NoSuchElementException e) {
+ log.error("게시글을 찾을 수 없습니다. ID: {}", postId, e);
+ return ResponseEntity.notFound().build();
+ } catch (Exception e) {
+ log.error("게시글 조회 중 오류 발생. ID: {}", postId, e);
+ return ResponseEntity.internalServerError().build();
+ }
}또는 전역 예외 처리기(Global Exception Handler)를 구현하여 모든 컨트롤러에서 발생하는 예외를 중앙에서 처리하는 것을 고려해 보세요. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package aibe.hosik.post.dto; | ||
|
|
||
| import aibe.hosik.post.entity.Post; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record MatchedUserDTO( | ||
| Long userId, | ||
| String username, | ||
| String nickname, | ||
| String image, | ||
| String introduction | ||
| ) { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,41 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package aibe.hosik.post.dto; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.Post; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.PostCategory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.PostType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.LocalDate; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public record PostDetailDTO( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Long id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String content, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Integer headCount, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String image, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String requirementPersonality, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LocalDate endedAt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String category, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<String> skills, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 현재 선택된 목록 보여주기 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<MatchedUserDTO> matchedUsers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static PostDetailDTO from(Post post, List<String> skills, List<MatchedUserDTO> matchedUsers) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new PostDetailDTO( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getId(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getTitle(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getContent(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getHeadCount(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getImage(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getRequirementPersonality(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getEndedAt(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getCategory().toString(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post.getType().toString(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| skills, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| matchedUsers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+27
to
+41
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. 🛠️ Refactor suggestion 열거형(Enum) 타입 안전성 향상 필요 현재 또한 코드의 마지막 부분에서 닫는 괄호 public static PostDetailDTO from(Post post, List<String> skills, List<MatchedUserDTO> matchedUsers) {
return new PostDetailDTO(
post.getId(),
post.getTitle(),
post.getContent(),
post.getHeadCount(),
post.getImage(),
post.getRequirementPersonality(),
post.getEndedAt(),
- post.getCategory().toString(),
- post.getType().toString(),
+ post.getCategory().name(), // toString() 대신 name() 사용
+ post.getType().name(), // toString() 대신 name() 사용
skills,
matchedUsers
);
-}}
+ }
+}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,37 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package aibe.hosik.post.dto; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.Post; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.PostCategory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.PostType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.user.User; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.LocalDate; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public record PostRequestDTO( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String content, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Integer headCount, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String image, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String requirementPersonality, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LocalDate endedAt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PostCategory category, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PostType type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<String> skills | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+23
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. 🛠️ Refactor suggestion 필드 유효성 검증 추가 필요 현재 아래와 같이 수정하는 것을 권장합니다: public record PostRequestDTO(
+ @NotBlank(message = "제목은 필수 입력값입니다")
+ @Size(max = 100, message = "제목은 100자 이내로 입력해주세요")
String title,
+ @NotBlank(message = "내용은 필수 입력값입니다")
String content,
+ @Min(value = 1, message = "인원 수는 최소 1명 이상이어야 합니다")
Integer headCount,
String image,
String requirementPersonality,
+ @NotNull(message = "모집 종료일은 필수 입력값입니다")
+ @Future(message = "모집 종료일은 현재 이후의 날짜여야 합니다")
LocalDate endedAt,
+ @NotNull(message = "카테고리는 필수 입력값입니다")
PostCategory category,
+ @NotNull(message = "타입은 필수 입력값입니다")
PostType type,
+ @NotEmpty(message = "최소 하나 이상의 스킬이 필요합니다")
List<String> skills
) {Bean Validation을 위해 아래 의존성 추가가 필요합니다: import jakarta.validation.constraints.*; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Post toEntity(User user) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Post.builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .title(title()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .content(content()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .headCount(headCount()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .image(image()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .requirementPersonality(requirementPersonality()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .endedAt(endedAt()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .category(category()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .type(type()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .user(user) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+36
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. 🛠️ Refactor suggestion toEntity 메서드에 Null 체크 추가 필요
다음과 같이 빌더 패턴에서 null 체크 로직을 추가하는 것이 좋습니다: public Post toEntity(User user) {
+ if (user == null) {
+ throw new IllegalArgumentException("사용자 정보는 필수입니다");
+ }
return Post.builder()
.title(title())
.content(content())
.headCount(headCount())
.image(image())
.requirementPersonality(requirementPersonality())
.endedAt(endedAt())
.category(category())
.type(type())
.user(user)
.build();
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,29 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| package aibe.hosik.post.dto; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.Post; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| public record PostResponseDTO( | ||||||||||||||||||||||||||||||||||||||||||||||
| Long id, | ||||||||||||||||||||||||||||||||||||||||||||||
| String image, | ||||||||||||||||||||||||||||||||||||||||||||||
| String title, | ||||||||||||||||||||||||||||||||||||||||||||||
| String content, | ||||||||||||||||||||||||||||||||||||||||||||||
| String category, | ||||||||||||||||||||||||||||||||||||||||||||||
| List<String> skills, | ||||||||||||||||||||||||||||||||||||||||||||||
| Integer headCount, | ||||||||||||||||||||||||||||||||||||||||||||||
| Integer currentCount | ||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| public static PostResponseDTO from(Post post,List<String> skills, Integer currentCount) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return new PostResponseDTO(post.getId(), | ||||||||||||||||||||||||||||||||||||||||||||||
| post.getImage(), | ||||||||||||||||||||||||||||||||||||||||||||||
| post.getTitle(), | ||||||||||||||||||||||||||||||||||||||||||||||
| post.getContent(), | ||||||||||||||||||||||||||||||||||||||||||||||
| post.getCategory().toString(), | ||||||||||||||||||||||||||||||||||||||||||||||
| skills, | ||||||||||||||||||||||||||||||||||||||||||||||
| post.getHeadCount(), | ||||||||||||||||||||||||||||||||||||||||||||||
| currentCount | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+18
to
+28
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. 🛠️ Refactor suggestion 문법 및 Enum 처리 개선 필요
다음과 같이 수정하는 것을 권장합니다: - public static PostResponseDTO from(Post post,List<String> skills, Integer currentCount) {
+ public static PostResponseDTO from(Post post, List<String> skills, Integer currentCount) {
return new PostResponseDTO(post.getId(),
post.getImage(),
post.getTitle(),
post.getContent(),
- post.getCategory().toString(),
+ post.getCategory().name(),
skills,
post.getHeadCount(),
currentCount
);
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,14 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| package aibe.hosik.post.entity; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.common.TimeEntity; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.skill.entity.PostSkill; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.user.User; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import jakarta.persistence.*; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.*; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.LocalDate; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.ArrayList; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| @Entity | ||||||||||||||||||||||||||||||||||||||||||||||||
| @NoArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -34,6 +37,9 @@ public class Post extends TimeEntity { | |||||||||||||||||||||||||||||||||||||||||||||||
| @Column | ||||||||||||||||||||||||||||||||||||||||||||||||
| private String image; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| @Column | ||||||||||||||||||||||||||||||||||||||||||||||||
| private String requirementPersonality; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+42
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. 🛠️ Refactor suggestion requirementPersonality 필드에 유효성 제약조건 추가 필요
- @Column
+ @Column(length = 500)
+ @Size(max = 500)
private String requirementPersonality;📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
| @Column(nullable = false) | ||||||||||||||||||||||||||||||||||||||||||||||||
| private LocalDate endedAt; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -47,4 +53,9 @@ public class Post extends TimeEntity { | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| @ManyToOne(fetch = FetchType.LAZY) | ||||||||||||||||||||||||||||||||||||||||||||||||
| private User user; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // 양방향 매핑 | ||||||||||||||||||||||||||||||||||||||||||||||||
| @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) | ||||||||||||||||||||||||||||||||||||||||||||||||
| @Builder.Default | ||||||||||||||||||||||||||||||||||||||||||||||||
| private List<PostSkill> postSkills = new ArrayList<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+57
to
+60
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. 🛠️ Refactor suggestion 양방향 매핑에 대한 헬퍼 메서드 추가 필요 양방향 매핑을 사용할 때는 양쪽에서 관계를 설정하는 헬퍼 메서드를 추가하는 것이 좋습니다. 현재는 관계 설정 책임이 서비스 계층에 있어서 일관성 문제가 발생할 수 있습니다. 포스트와 스킬 간의 양방향 관계를 관리하는 헬퍼 메서드를 추가합니다: @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<PostSkill> postSkills = new ArrayList<>();
+
+ // 양방향 관계 유지를 위한 헬퍼 메서드
+ public void addPostSkill(PostSkill postSkill) {
+ this.postSkills.add(postSkill);
+ if (postSkill.getPost() != this) {
+ postSkill.setPost(this);
+ }
+ }
+
+ public void removePostSkill(PostSkill postSkill) {
+ this.postSkills.remove(postSkill);
+ if (postSkill.getPost() == this) {
+ postSkill.setPost(null);
+ }
+ }📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| package aibe.hosik.post.repository; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import aibe.hosik.post.entity.Post; | ||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.jpa.repository.EntityGraph; | ||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.jpa.repository.Query; | ||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.data.repository.query.Param; | ||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Repository; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Optional; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| public interface PostRepository extends JpaRepository<Post, Long> { | ||||||||||||||||||||||||||||||||||||||||||||||
| // Post 조회 시 postSkills, skill 엔티티 즉시 로딩 지정 | ||||||||||||||||||||||||||||||||||||||||||||||
| //@EntityGraph(attributePaths = {"postSkills", "postSkills.skill"}) | ||||||||||||||||||||||||||||||||||||||||||||||
| @Query("SELECT DISTINCT p FROM Post p LEFT JOIN FETCH p.postSkills ps LEFT JOIN FETCH ps.skill") | ||||||||||||||||||||||||||||||||||||||||||||||
| List<Post> findAllWithSkills(); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // PostDetail 조회 시 즉시 로딩 지정 | ||||||||||||||||||||||||||||||||||||||||||||||
| //@EntityGraph(attributePaths = {"postSkills", "postSkills.skill"}) | ||||||||||||||||||||||||||||||||||||||||||||||
| @Query("SELECT DISTINCT p FROM Post p LEFT JOIN FETCH p.postSkills ps LEFT JOIN FETCH ps.skill WHERE p.id = :id") | ||||||||||||||||||||||||||||||||||||||||||||||
| Optional<Post> findByIdWithSkills(@Param("id") Long id); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+22
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. 🛠️ Refactor suggestion 페이징 처리 및 주석 개선 필요 게시글 조회 시 페이징 처리가 구현되어 있지 않습니다. 데이터가 많아질 경우 성능 이슈가 발생할 수 있습니다. 또한 메서드 주석을 추가하여 메서드의 목적과 사용법을 명확히 설명하는 것이 좋습니다. - // PostDetail 조회 시 즉시 로딩 지정
+ /**
+ * 특정 ID의 게시글을 연관된 스킬과 함께 조회합니다.
+ * JPQL의 LEFT JOIN FETCH를 사용하여 N+1 문제를 방지합니다.
+ * @param id 조회할 게시글 ID
+ * @return 스킬 정보가 포함된 게시글 (Optional)
+ */
//@EntityGraph(attributePaths = {"postSkills", "postSkills.skill"})
@Query("SELECT DISTINCT p FROM Post p LEFT JOIN FETCH p.postSkills ps LEFT JOIN FETCH ps.skill WHERE p.id = :id")
Optional<Post> findByIdWithSkills(@Param("id") Long id);
+
+ /**
+ * 모든 게시글을 페이징하여 조회합니다.
+ * @param pageable 페이징 정보
+ * @return 페이징된 게시글 목록
+ */
+ @Query(value = "SELECT DISTINCT p FROM Post p",
+ countQuery = "SELECT COUNT(p) FROM Post p")
+ Page<Post> findAllWithPaging(Pageable pageable);📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package aibe.hosik.post.service; | ||
|
|
||
| import aibe.hosik.post.dto.PostDetailDTO; | ||
| import aibe.hosik.post.dto.PostRequestDTO; | ||
| import aibe.hosik.post.dto.PostResponseDTO; | ||
| import aibe.hosik.post.entity.Post; | ||
| import aibe.hosik.user.User; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public interface PostService { | ||
| List<PostResponseDTO> getAllPosts(); | ||
| Post createPost(PostRequestDTO dto, User user); | ||
| PostDetailDTO getPostDetail(Long postId); | ||
| } |
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.
💡 Verification agent
❓ Verification inconclusive
Spring Security 의존성이 활성화되었습니다
Spring Security 의존성을 활성화하셨네요. 이는 인증 및 권한 부여 기능을 프로젝트에 추가합니다. 다만, Spring Security를 활성화하면 기본적으로 모든 엔드포인트가 인증을 필요로 하게 됩니다. 이를 위한 적절한 보안 구성이 프로젝트에 추가되었는지 확인해주세요.
프로젝트에 SecurityConfig 또는 WebSecurityConfigurerAdapter 구현체가 있는지 확인해보세요:
🏁 Script executed:
Length of output: 89
보안 설정 클래스 미확인
Spring Security 의존성을 추가하셨으나,
src/main/java경로에서*Security*.java또는*WebSecurity*.java파일이 검색되지 않습니다. 이 상태라면 기본 설정으로 모든 엔드포인트가 인증을 필요로 하며, 기본 로그인 페이지와 기본 계정이 생성될 수 있습니다. 다음 사항을 검토 및 조치해주세요:@Configuration과@EnableWebSecurity애노테이션을 사용해WebSecurityConfigurerAdapter또는SecurityFilterChain구현체 생성antMatchers등), CSRF·CORS 설정 여부 확인예시:
위와 같이 보안 설정을 추가하여 프로젝트에 필요한 인증·인가 로직을 구현해주세요.