-
Notifications
You must be signed in to change notification settings - Fork 0
[FEAT] 회원탈퇴 #48
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
[FEAT] 회원탈퇴 #48
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Walkthrough이 변경 사항은 FixLog 서버의 주요 도메인, DTO, 서비스, 컨트롤러, 리포지토리, 예외 처리, 보안(JWT 인증 및 Spring Security), 그리고 테스트 데이터 초기화 기능을 대규모로 도입합니다. 회원가입, 로그인, 팔로우, 북마크, 포스트 등 핵심 기능의 전체 백엔드 구조가 구현되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant AuthController
participant AuthService
participant MemberRepository
participant PasswordEncoder
participant JwtUtil
Client->>AuthController: POST /auth/login (email, password)
AuthController->>AuthService: login(requestDto)
AuthService->>MemberRepository: findByEmail(email)
MemberRepository-->>AuthService: Member or Exception
AuthService->>PasswordEncoder: matches(raw, encoded)
AuthService->>JwtUtil: createToken(userId, email)
JwtUtil-->>AuthService: accessToken
AuthService-->>AuthController: LoginResponseDto
AuthController-->>Client: Response<LoginResponseDto>
sequenceDiagram
participant Client
participant SecurityConfig
participant JwtAuthenticationFilter
participant JwtUtil
participant MemberRepository
participant SecurityContextHolder
Client->>SecurityConfig: 요청
SecurityConfig->>JwtAuthenticationFilter: 요청 필터링
JwtAuthenticationFilter->>JwtUtil: isTokenValid(token)
JwtUtil-->>JwtAuthenticationFilter: true/false
JwtAuthenticationFilter->>JwtUtil: getEmailFromToken(token)
JwtAuthenticationFilter->>MemberRepository: findByEmail(email)
MemberRepository-->>JwtAuthenticationFilter: Member
JwtAuthenticationFilter->>SecurityContextHolder: setAuthentication
JwtAuthenticationFilter-->>SecurityConfig: 필터 체인 계속
Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
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.
Actionable comments posted: 63
🧹 Nitpick comments (44)
.coderabbit.yaml (1)
15-15: 파일 끝 개행 추가 필요
YAMLlint 오류(no new line character at the end of file)를 해결하기 위해 파일 끝에 새 줄(개행)을 추가해주세요..coderabbit.yaml +<빈 줄 추가>🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 15-15: no new line character at the end of file
(new-line-at-end-of-file)
src/main/java/com/example/FixLog/dto/follow/request/UnfollowRequestDto.java (1)
9-12: 중복 코드 제거를 위한 공통 DTO 클래스 고려해보세요.현재 구현은 올바르지만,
FollowRequestDto와 동일한 구조를 가지고 있습니다. 공통 기본 클래스나 제네릭을 활용하여 코드 중복을 줄일 수 있습니다.공통 기본 클래스를 만들어 중복을 제거할 수 있습니다:
+@Getter +@NoArgsConstructor +public abstract class BaseTargetRequestDto { + @JsonProperty("target_member_id") + protected Long targetMemberId; +} -@Getter -@NoArgsConstructor -public class UnfollowRequestDto { - @JsonProperty("target_member_id") - private Long targetMemberId; -} +public class UnfollowRequestDto extends BaseTargetRequestDto { +}src/main/java/com/example/FixLog/dto/UserIdDto.java (1)
5-8: DTO의 불변성과 일관성을 개선하세요.다른 DTO들과의 일관성을 위해
@NoArgsConstructor어노테이션을 추가하고, 불변성을 위해 생성자나 빌더 패턴을 고려해보세요. 또한userId필드에 대한 유효성 검증을 추가하는 것을 권장합니다.+import lombok.NoArgsConstructor; +import javax.validation.constraints.NotNull; @Getter +@NoArgsConstructor public class UserIdDto { + @NotNull private Long userId; }src/main/java/com/example/FixLog/dto/bookmark/response/BookmarkFolderCreateResponse.java (1)
3-3: Java record 사용이 응답 DTO에 적합합니다.Java record를 사용하여 불변성을 보장하는 것은 좋은 선택입니다. 다만
folder_id필드명이 snake_case를 사용하고 있는데, Java 컨벤션상 camelCase(folderId)를 사용하는 것이 일반적입니다. API 응답 형식 요구사항에 따른 것이라면@JsonProperty어노테이션 사용을 고려해보세요.만약 API 응답에서 snake_case가 필요하다면:
+import com.fasterxml.jackson.annotation.JsonProperty; -public record BookmarkFolderCreateResponse(Long folder_id, String name) {} +public record BookmarkFolderCreateResponse( + @JsonProperty("folder_id") Long folderId, + String name +) {}src/main/java/com/example/FixLog/dto/member/SignupRequestDto.java (2)
9-12: DTO 필드에 유효성 검증 어노테이션 추가 제안
password,nickname필드에@NotBlank,@Size등 Bean Validation 어노테이션을 추가하여 서버단 입력 유효성 검사를 강화하는 것을 권장합니다.
3-7: Lombok 어노테이션 일관성 점검
LoginRequestDto에는@Getter만 사용하고,SignupRequestDto에는@Getter/@Setter를 사용하고 있습니다. DTO의 불변성과 사용 방식을 고려해 어노테이션 정책을 통일하면 유지보수가 용이합니다.src/main/java/com/example/FixLog/dto/member/LoginResponseDto.java (1)
11-14: 응답 필드 네이밍 컨벤션 확인
JSON 필드 네이밍(userId,profileImageUrl)이 camelCase로 노출됩니다. API 전체에서 snake_case(예:user_id)로 통일할지 팀 컨벤션을 검토하세요.build.gradle (2)
28-28: 들여쓰기 일관성 확인
28번째 줄(implementation 'org.springframework.boot:spring-boot-starter-security')이 공백으로 들여쓰기되어 있습니다. 전체 파일에서 탭 혹은 공백 중 일관된 방식을 사용하세요.
30-32: JJWT 의존성 버전 관리 개선 제안
jjwt-api,jjwt-impl,jjwt-jackson버전을 BOM으로 관리하면 하드코딩된 버전을 통일 관리할 수 있습니다. 예:dependencies { - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' - runtimeOnly('io.jsonwebtoken:jjwt-jackson:0.11.5') + implementation platform('io.jsonwebtoken:jjwt-bom:0.11.5') + implementation 'io.jsonwebtoken:jjwt-api' + runtimeOnly 'io.jsonwebtoken:jjwt-impl' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson' }src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkMoveRequest.java (1)
5-7: 필드 유효성 검증 어노테이션 추가 제안
folderId필드에@NotNull또는@Positive를 추가하여 필수 값임을 명시하고 음수 ID가 전달되는 것을 방지하세요.src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkFolderUpdateRequest.java (1)
5-7: 필드 유효성 검증 어노테이션 추가 제안
folderName에@NotBlank,@Size(max = 50)등을 추가해 빈 문자열이나 과도한 길이 전달을 방지하세요.src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkFolderCreateRequest.java (1)
5-7: 입력 값 검증을 위한 validation 어노테이션 추가를 고려하세요.현재 구현은 깔끔하지만, 폴더명에 대한 유효성 검증이 없습니다.
다음과 같이 validation 어노테이션을 추가하는 것을 권장합니다:
+import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; public record BookmarkFolderCreateRequest( - @JsonProperty("name") String folderName + @JsonProperty("name") + @NotBlank(message = "폴더명은 필수입니다") + @Size(max = 50, message = "폴더명은 50자를 초과할 수 없습니다") + String folderName ) {}src/main/java/com/example/FixLog/mock/TagTestDataInitializer.java (1)
27-27: 로깅 시스템 사용을 고려하세요.
System.out.println대신 로거를 사용하는 것이 더 적절합니다.다음과 같이 개선할 수 있습니다:
+ import lombok.extern.slf4j.Slf4j; + @Slf4j @Component @RequiredArgsConstructor public class TagTestDataInitializer implements CommandLineRunner { // ... - System.out.println("임시 태그 4개 삽입 완료"); + log.info("임시 태그 4개 삽입 완료");src/main/java/com/example/FixLog/domain/tag/TagCategory.java (1)
5-19: 중복된 getter 메서드를 제거하여 일관성을 개선하세요.
@Getter어노테이션이 클래스 레벨에 적용되어 있어getDisplayName()메서드가 자동으로 생성되므로, 수동으로 작성된 getter 메서드(17-19행)는 불필요합니다.다음 diff를 적용하여 중복을 제거하세요:
- public String getDisplayName() { - return displayName; - }src/main/java/com/example/FixLog/domain/tag/Tag.java (2)
21-22: tagName 필드에 유효성 검증을 추가하는 것을 고려하세요.데이터베이스 레벨 제약조건 외에 애플리케이션 레벨 검증도 추가하면 더 안전합니다.
다음과 같은 검증 어노테이션을 추가해보세요:
+import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +@NotBlank(message = "태그명은 필수입니다") +@Size(max = 20, message = "태그명은 20자를 초과할 수 없습니다") @Column(length = 20, nullable = false) private String tagName;
24-29: 정적 팩토리 메서드 패턴을 잘 활용했습니다.
of메서드를 통한 객체 생성 방식이 깔끔하고 의도가 명확합니다. 다만 equals/hashCode 메서드 추가를 고려해보세요.엔티티 동등성 비교를 위해 다음을 추가하는 것을 고려하세요:
+import lombok.EqualsAndHashCode; +@EqualsAndHashCode(of = {"tagCategory", "tagName"}) @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Tag {src/main/java/com/example/FixLog/dto/follow/request/FollowRequestDto.java (1)
7-12: 코드가 잘 구현되었습니다.DTO 설계가 적절합니다:
- JsonProperty 어노테이션으로 API 계약 일관성 확보
- Lombok 어노테이션 적절한 사용
- UnfollowRequestDto와 일관된 패턴
선택적 개선사항으로 입력 검증을 위한 Bean Validation 어노테이션을 고려할 수 있습니다:
+import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; public class FollowRequestDto { + @NotNull(message = "대상 회원 ID는 필수입니다") + @Positive(message = "회원 ID는 양수여야 합니다") @JsonProperty("target_member_id") private Long targetMemberId; // 팔로우 대상 ID }src/main/java/com/example/FixLog/mock/MemberTestDataInitializer.java (1)
37-37: 적절한 로깅 프레임워크를 사용하세요.System.out.println 대신 SLF4J 로거를 사용하는 것이 좋습니다.
+import lombok.extern.slf4j.Slf4j; +@Slf4j @Component @Profile({"dev", "test", "local"}) @Order(1) @RequiredArgsConstructor public class MemberTestDataInitializer implements CommandLineRunner { - System.out.println("테스트용 멤버 2명 삽입 완료"); + log.info("테스트용 멤버 2명 삽입 완료");src/main/java/com/example/FixLog/util/JwtUtil.java (2)
21-21: 만료 시간을 설정 가능하도록 개선하세요.만료 시간이 하드코딩되어 있습니다. 이를
application.properties에서 설정할 수 있도록 변경하는 것이 좋습니다.+ @Value("${jwt.expiration}") - private final long expiration = 1000 * 60 * 60 * 24; // 24시간 + private long expiration;그리고
application.properties에 다음을 추가하세요:jwt.expiration=86400000
46-53: 예외 처리를 더 구체적으로 개선하세요.현재 모든 예외를 동일하게 처리하고 있습니다. JWT 관련 특정 예외들을 구별하여 처리하면 디버깅과 로깅에 도움이 됩니다.
public boolean isTokenValid(String token) { try { getClaims(token); return true; - } catch (Exception e) { + } catch (io.jsonwebtoken.ExpiredJwtException e) { + // 토큰 만료 + return false; + } catch (io.jsonwebtoken.MalformedJwtException e) { + // 잘못된 토큰 형식 + return false; + } catch (io.jsonwebtoken.UnsupportedJwtException e) { + // 지원하지 않는 토큰 + return false; + } catch (io.jsonwebtoken.security.SecurityException e) { + // 서명 검증 실패 + return false; + } catch (Exception e) { + // 기타 예외 return false; } }src/main/java/com/example/FixLog/exception/GlobalExceptionHandler.java (2)
10-16: 메서드명이 부정확합니다.메서드명이
handleDuplicateException인데 실제로는 모든CustomException을 처리합니다. 더 일반적인 이름으로 변경하는 것이 좋습니다.- protected ResponseEntity<Response<?>> handleDuplicateException(CustomException ex) { + protected ResponseEntity<Response<?>> handleCustomException(CustomException ex) {
8-17: 추가 예외 처리를 고려해보세요.현재는
CustomException만 처리하고 있습니다. 일반적인 예외들(IllegalArgumentException,NullPointerException등)에 대한 처리도 추가하면 더 안전한 애플리케이션이 됩니다.다음과 같은 핸들러들을 추가하는 것을 고려해보세요:
@ExceptionHandler(IllegalArgumentException.class) protected ResponseEntity<Response<?>> handleIllegalArgumentException(IllegalArgumentException ex) { logger.error("IllegalArgumentException occurred", ex); return new ResponseEntity<>(Response.fail("잘못된 요청입니다."), HttpStatus.BAD_REQUEST); } @ExceptionHandler(Exception.class) protected ResponseEntity<Response<?>> handleGeneralException(Exception ex) { logger.error("Unexpected error occurred", ex); return new ResponseEntity<>(Response.fail("서버 오류가 발생했습니다."), HttpStatus.INTERNAL_SERVER_ERROR); }src/main/java/com/example/FixLog/dto/Response.java (1)
19-25: 추가 편의 메서드를 고려해보세요.현재 구현도 충분하지만, 데이터 없이 성공 응답을 반환하는 경우를 위한 오버로드 메서드가 있으면 더 편리할 것입니다.
public static <T> Response<T> success(String message, T data) { return new Response<>(true, message, data); } + + public static <T> Response<T> success(String message) { + return new Response<>(true, message, null); + }src/main/java/com/example/FixLog/mock/BookmarkFolderTestDataInitializer.java (1)
22-33: 테스트 데이터 초기화 로직이 잘 구현되어 있습니다.
@Order(2)어노테이션으로 멤버 초기화 후 실행되도록 순서를 관리하고,ifPresentOrElse를 사용한 에러 처리도 적절합니다. 다만 현재 조건문은 전체 북마크 폴더가 비어있는지만 확인하는데, 특정 사용자의 폴더 존재 여부를 확인하는 것이 더 정확할 것 같습니다.더 정확한 조건 검사를 위해 다음과 같이 수정하는 것을 고려해보세요:
@Override public void run(String... args) { - if (bookmarkFolderRepository.count() == 0) { memberRepository.findByEmail("[email protected]").ifPresentOrElse(member -> { + if (bookmarkFolderRepository.findByUserId(member).isEmpty()) { BookmarkFolder defaultFolder = new BookmarkFolder(member, "default folder"); BookmarkFolder etcFolder = new BookmarkFolder(member, "그외 폴더"); bookmarkFolderRepository.saveAll(List.of(defaultFolder, etcFolder)); System.out.println("테스트용 북마크 폴더 2개 생성 완료"); + } }, () -> { System.out.println("[email protected] 사용자가 존재하지 않아 폴더 생성 생략됨"); }); - }이렇게 하면 해당 사용자의 폴더만 체크하여 중복 생성을 방지할 수 있습니다.
src/main/java/com/example/FixLog/dto/post/PostDto.java (1)
8-22: PostDto 클래스 설계 개선 제안현재 구현은 기능적으로 문제없으나 다음 개선사항을 고려해보세요:
- 빌더 패턴 적용: 22개의 필드를 가진 생성자는 가독성이 떨어집니다.
- 필드 검증: 필수 필드(예: postTitle)에 대한 null 체크나 빈 문자열 검증 고려
- 불변성 강화: 현재 List tags는 외부에서 수정 가능합니다.
다음과 같이 개선할 수 있습니다:
+import lombok.Builder; +import java.util.Collections; @Getter -@AllArgsConstructor +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class PostDto { private String postTitle; // ... other fields - private List<String> tags; + private List<String> tags; + + public List<String> getTags() { + return tags != null ? Collections.unmodifiableList(tags) : Collections.emptyList(); + } }src/main/java/com/example/FixLog/domain/bookmark/BookmarkFolder.java (1)
25-27: 필드명과 실제 타입의 일관성을 개선해주세요.
userId필드명이 실제로는Member객체를 참조하고 있어 혼란을 줄 수 있습니다. 의도를 더 명확히 하기 위해 필드명을 변경하는 것을 고려해보세요.-@OneToOne(fetch = FetchType.LAZY) -@JoinColumn(name = "user_id", nullable = false) -private Member userId; +@OneToOne(fetch = FetchType.LAZY) +@JoinColumn(name = "user_id", nullable = false) +private Member member;또는
-@OneToOne(fetch = FetchType.LAZY) -@JoinColumn(name = "user_id", nullable = false) -private Member userId; +@OneToOne(fetch = FetchType.LAZY) +@JoinColumn(name = "user_id", nullable = false) +private Member owner;src/main/java/com/example/FixLog/service/MemberService.java (1)
46-48: 비즈니스 로직 분리를 고려하세요.회원가입 시 기본 북마크 폴더 생성 로직이 MemberService에 포함되어 있어 단일 책임 원칙(SRP)에 위배됩니다.
이 로직을 별도 서비스나 이벤트 기반으로 분리하는 것을 고려해보세요:
// 예시: ApplicationEventPublisher 사용 @EventListener public void handleMemberRegistered(MemberRegisteredEvent event) { BookmarkFolder newFolder = new BookmarkFolder(event.getMember()); bookmarkFolderRepository.save(newFolder); }src/main/java/com/example/FixLog/service/AuthService.java (1)
22-44: 예외 처리와 로깅 개선인증 실패 시 보안을 위해 더 일반적인 에러 메시지를 사용하고, 로깅을 추가하는 것을 고려하세요.
@Slf4j // 클래스 레벨에 추가 public class AuthService { public LoginResponseDto login(LoginRequestDto requestDto) { try { Member member = memberRepository.findByEmail(requestDto.getEmail()) .orElseThrow(() -> new CustomException(ErrorCode.INVALID_CREDENTIALS)); if (!passwordEncoder.matches(requestDto.getPassword(), member.getPassword())) { log.warn("Failed login attempt for email: {}", requestDto.getEmail()); throw new CustomException(ErrorCode.INVALID_CREDENTIALS); } log.info("Successful login for user: {}", member.getEmail()); // ... 나머지 로직 } catch (Exception e) { log.error("Login error for email: {}", requestDto.getEmail(), e); throw e; } } }src/main/java/com/example/FixLog/service/MainPageService.java (2)
54-59: 매직 넘버 사용 및 에러 처리 개선 필요sort 파라미터 검증에서 매직 넘버(0, 1)를 사용하고 있습니다. enum을 사용하여 가독성과 유지보수성을 향상시키는 것을 권장합니다.
다음과 같이 개선할 수 있습니다:
+public enum SortType { + LATEST(0), POPULAR(1); + + private final int value; + SortType(int value) { this.value = value; } + public int getValue() { return value; } + + public static SortType fromValue(int value) { + return Arrays.stream(values()) + .filter(type -> type.value == value) + .findFirst() + .orElseThrow(() -> new CustomException(ErrorCode.SORT_NOT_EXIST)); + } +} - if (sort == 0) { // 최신순 정렬 - posts = postRepository.findTop12ByOrderByCreatedAtDesc(); - } else if (sort == 1) { // 인기순 정렬 - posts = postRepository.findTop12ByOrderByPostLikesDesc(); - } else - throw new CustomException(ErrorCode.SORT_NOT_EXIST); + SortType sortType = SortType.fromValue(sort); + posts = switch (sortType) { + case LATEST -> postRepository.findTop12ByOrderByCreatedAtDesc(); + case POPULAR -> postRepository.findTop12ByOrderByPostLikesDesc(); + };
85-94: 매직 넘버 하드코딩 문제페이지 크기(12)와 sort 검증 로직이 하드코딩되어 있습니다. 상수로 정의하거나 설정 파일로 분리하는 것을 권장합니다.
+ private static final int DEFAULT_PAGE_SIZE = 12; - Pageable pageable = PageRequest.of(page - 1, 12); + Pageable pageable = PageRequest.of(page - 1, DEFAULT_PAGE_SIZE);src/main/java/com/example/FixLog/config/JwtAuthenticationFilter.java (1)
49-55: 토큰 추출 로직 보안 강화 권장Bearer 토큰 추출 로직이 적절하게 구현되어 있습니다. 추가적인 보안 강화를 위해 토큰 길이 검증을 고려해볼 수 있습니다.
private String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { - return bearerToken.substring(7); + String token = bearerToken.substring(7); + return token.length() > 0 ? token : null; } return null; }src/main/java/com/example/FixLog/service/BookmarkFolderService.java (3)
43-43: 페이지 크기 하드코딩 문제페이지 크기가 10으로 하드코딩되어 있습니다. 상수로 정의하거나 설정 파일로 분리하는 것을 권장합니다.
+ private static final int DEFAULT_FOLDER_PAGE_SIZE = 10; - Pageable pageable = PageRequest.of(page - 1, 10); // 기본 size = 10 + Pageable pageable = PageRequest.of(page - 1, DEFAULT_FOLDER_PAGE_SIZE);
93-96: 불필요한 빈 줄 제거 필요파일 끝에 불필요한 빈 줄들이 있습니다. 코드 포맷팅을 정리해주세요.
bookmarkFolderRepository.delete(folder); } - } +}
69-71: 소유권 검증 로직 중복폴더 수정과 삭제에서 동일한 소유권 검증 로직이 반복됩니다. 공통 메서드로 추출하는 것을 권장합니다.
+ private void validateFolderOwnership(BookmarkFolder folder, Member member) { + if (!folder.getUserId().equals(member)) { + throw new CustomException(ErrorCode.ACCESS_DENIED); + } + } public void updateFolderName(Long folderId, String email, String newName) { Member member = getMemberByEmailOrThrow(email); BookmarkFolder folder = bookmarkFolderRepository.findById(folderId) .orElseThrow(() -> new CustomException(ErrorCode.FOLDER_NOT_FOUND)); - // 본인만 수정 가능 - if (!folder.getUserId().equals(member)) { - throw new CustomException(ErrorCode.ACCESS_DENIED); - } + validateFolderOwnership(folder, member);Also applies to: 86-88
src/main/java/com/example/FixLog/dto/main/MainPageResponseDto.java (1)
18-19: JsonInclude 어노테이션 사용법 검증
totalPages필드에@JsonInclude(JsonInclude.Include.NON_DEFAULT)를 사용했는데,int타입의 기본값은 0이므로 의도한 대로 동작할 것입니다. 하지만 명시적으로@JsonInclude(JsonInclude.Include.NON_ZERO)를 사용하는 것이 더 명확할 수 있습니다.- @JsonInclude(JsonInclude.Include.NON_DEFAULT) // totalPage = 0 인 경우에는 출력되지 않도록 + @JsonInclude(JsonInclude.Include.NON_ZERO) // totalPages = 0 인 경우에는 출력되지 않도록 private int totalPages;src/main/java/com/example/FixLog/dto/post/PostRequestDto.java (1)
23-24: 주석 처리된 코드 정리 권장주석 처리된 필드들이 향후 확장 계획을 나타내지만, 코드 가독성을 위해 TODO 주석으로 대체하거나 별도 문서로 관리하는 것을 권장합니다.
-// private List<String> postImageUrl; -// private List<String> tags; +// TODO: 향후 구현 예정 기능 +// - 다중 이미지 업로드 (postImageUrl) +// - 문자열 기반 태그 지원 (tags)src/main/java/com/example/FixLog/domain/post/Post.java (1)
35-62: @lob 어노테이션 사용 검토모든 텍스트 필드에
@Lob어노테이션을 사용했는데, 이는 성능에 영향을 줄 수 있습니다. 실제 데이터 크기에 따라 적절한 길이 제한을 고려해보세요.-@Lob -@Column(nullable = false) +@Column(length = 1000, nullable = false) private String problem; -@Lob -@Column(nullable = false) +@Column(length = 500, nullable = false) private String errorMessage;정말 큰 텍스트가 예상되는 필드에만
@Lob을 사용하고, 나머지는 적절한 길이 제한을 설정하는 것을 권장합니다.src/main/java/com/example/FixLog/controller/MainPageController.java (2)
14-16: 의존성 주입 어노테이션 누락AuthController에서는
@RequiredArgsConstructor를 사용했지만, 여기서는 수동으로 생성자를 작성했습니다. 일관성을 위해 Lombok 어노테이션 사용을 권장합니다.+import lombok.RequiredArgsConstructor; + @RestController @RequestMapping("/main") +@RequiredArgsConstructor public class MainPageController { private final MainPageService mainPageService; - - public MainPageController(MainPageService mainPageService){ - this.mainPageService = mainPageService; - }
19-19: 변수명 오타 수정
userIddto변수명에 오타가 있습니다. 일관된 네이밍 컨벤션을 적용하세요.-public Response<Object> mainPageView(@RequestParam("sort") int sort, @RequestBody UserIdDto userIddto){ +public Response<Object> mainPageView(@RequestParam("sort") int sort, @RequestBody UserIdDto userIdDto){26행의 동일한 오타도 함께 수정해주세요.
src/main/java/com/example/FixLog/domain/member/Member.java (2)
73-75: 중복된 주석 제거 필요같은 내용의 주석이 반복되고 있습니다.
- // Member 객체를 정적 팩토리 방식으로 회원가입 시에 생성하는 메서드 - // Member 객체를 정적 팩토리 방식으로 생성하는 메서드 // Creates a Member object using a static factory method
83-83: 하드코딩된 프로필 이미지 URL 개선 필요기본 프로필 이미지 URL이 하드코딩되어 있습니다. 설정 파일이나 상수로 관리하는 것이 좋습니다.
설정 파일로 관리하는 방식으로 리팩토링하시겠습니까? 구현을 도와드릴 수 있습니다.
src/main/java/com/example/FixLog/controller/PostController.java (1)
11-17: Lombok을 사용하여 코드 일관성 유지다른 서비스 클래스들과 일관성을 위해 Lombok의
@RequiredArgsConstructor를 사용하는 것이 좋습니다.+import lombok.RequiredArgsConstructor; @RestController @RequestMapping("/posts") +@RequiredArgsConstructor public class PostController { private final PostService postService; - - public PostController(PostService postService){ - this.postService = postService; - }src/main/java/com/example/FixLog/controller/FollowController.java (1)
26-26: 임시 인증 방식 사용 확인JWT 구현 전까지
requesterEmail파라미터를 사용하는 것으로 이해했습니다. 추후@AuthenticationPrincipal로 변경 시 모든 엔드포인트를 일괄 업데이트해야 합니다.JWT 인증 구현 관련 이슈를 생성하여 추적하시겠습니까?
Also applies to: 36-36, 45-45, 54-54
src/main/java/com/example/FixLog/controller/BookmarkFolderController.java (1)
75-77: 불필요한 빈 줄을 제거하세요.파일 끝에 불필요한 빈 줄들이 있습니다.
} - -
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (67)
.coderabbit.yaml(1 hunks)build.gradle(1 hunks)src/main/java/com/example/FixLog/config/JwtAuthenticationFilter.java(1 hunks)src/main/java/com/example/FixLog/config/SecurityConfig.java(1 hunks)src/main/java/com/example/FixLog/controller/AuthController.java(1 hunks)src/main/java/com/example/FixLog/controller/BookmarkFolderController.java(1 hunks)src/main/java/com/example/FixLog/controller/FollowController.java(1 hunks)src/main/java/com/example/FixLog/controller/MainPageController.java(1 hunks)src/main/java/com/example/FixLog/controller/MemberController.java(1 hunks)src/main/java/com/example/FixLog/controller/PostController.java(1 hunks)src/main/java/com/example/FixLog/domain/bookmark/Bookmark.java(1 hunks)src/main/java/com/example/FixLog/domain/bookmark/BookmarkFolder.java(1 hunks)src/main/java/com/example/FixLog/domain/follow/Follow.java(1 hunks)src/main/java/com/example/FixLog/domain/fork/Fork.java(1 hunks)src/main/java/com/example/FixLog/domain/like/PostLike.java(1 hunks)src/main/java/com/example/FixLog/domain/member/Member.java(1 hunks)src/main/java/com/example/FixLog/domain/member/SocialType.java(1 hunks)src/main/java/com/example/FixLog/domain/post/Post.java(1 hunks)src/main/java/com/example/FixLog/domain/post/PostTag.java(1 hunks)src/main/java/com/example/FixLog/domain/tag/Tag.java(1 hunks)src/main/java/com/example/FixLog/domain/tag/TagCategory.java(1 hunks)src/main/java/com/example/FixLog/dto/Response.java(1 hunks)src/main/java/com/example/FixLog/dto/UserIdDto.java(1 hunks)src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkFolderCreateRequest.java(1 hunks)src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkFolderUpdateRequest.java(1 hunks)src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkMoveRequest.java(1 hunks)src/main/java/com/example/FixLog/dto/bookmark/response/BookmarkFolderCreateResponse.java(1 hunks)src/main/java/com/example/FixLog/dto/bookmark/response/BookmarkFolderPageResponse.java(1 hunks)src/main/java/com/example/FixLog/dto/bookmark/response/BookmarkFolderReadResponse.java(1 hunks)src/main/java/com/example/FixLog/dto/follow/request/FollowRequestDto.java(1 hunks)src/main/java/com/example/FixLog/dto/follow/request/UnfollowRequestDto.java(1 hunks)src/main/java/com/example/FixLog/dto/follow/response/FollowResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/follow/response/FollowerListResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/follow/response/FollowingListResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/main/MainPagePostResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/main/MainPageResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/member/DuplicateCheckResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/member/LoginRequestDto.java(1 hunks)src/main/java/com/example/FixLog/dto/member/LoginResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/member/MemberInfoResponseDto.java(1 hunks)src/main/java/com/example/FixLog/dto/member/SignupRequestDto.java(1 hunks)src/main/java/com/example/FixLog/dto/post/PostDto.java(1 hunks)src/main/java/com/example/FixLog/dto/post/PostRequestDto.java(1 hunks)src/main/java/com/example/FixLog/dto/post/PostResponseDto.java(1 hunks)src/main/java/com/example/FixLog/exception/CustomException.java(1 hunks)src/main/java/com/example/FixLog/exception/ErrorCode.java(1 hunks)src/main/java/com/example/FixLog/exception/GlobalExceptionHandler.java(1 hunks)src/main/java/com/example/FixLog/mock/BookmarkFolderTestDataInitializer.java(1 hunks)src/main/java/com/example/FixLog/mock/MemberTestDataInitializer.java(1 hunks)src/main/java/com/example/FixLog/mock/TagTestDataInitializer.java(1 hunks)src/main/java/com/example/FixLog/repository/MemberRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/bookmark/BookmarkFolderRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/bookmark/BookmarkRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/follow/FollowRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/like/PostLikeRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/post/PostRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/post/PostTagRepository.java(1 hunks)src/main/java/com/example/FixLog/repository/tag/TagRepository.java(1 hunks)src/main/java/com/example/FixLog/service/AuthService.java(1 hunks)src/main/java/com/example/FixLog/service/BookmarkFolderService.java(1 hunks)src/main/java/com/example/FixLog/service/BookmarkService.java(1 hunks)src/main/java/com/example/FixLog/service/FollowService.java(1 hunks)src/main/java/com/example/FixLog/service/MainPageService.java(1 hunks)src/main/java/com/example/FixLog/service/MemberService.java(1 hunks)src/main/java/com/example/FixLog/service/PostService.java(1 hunks)src/main/java/com/example/FixLog/util/JwtUtil.java(1 hunks)src/main/resources/application.properties(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (15)
src/main/java/com/example/FixLog/dto/follow/request/UnfollowRequestDto.java (1)
src/main/java/com/example/FixLog/dto/follow/request/FollowRequestDto.java (1)
Getter(7-12)
src/main/java/com/example/FixLog/dto/member/LoginResponseDto.java (2)
src/main/java/com/example/FixLog/dto/Response.java (1)
JsonInclude(6-26)src/main/java/com/example/FixLog/dto/member/LoginRequestDto.java (1)
Getter(5-9)
src/main/java/com/example/FixLog/dto/member/SignupRequestDto.java (1)
src/main/java/com/example/FixLog/dto/member/LoginRequestDto.java (1)
Getter(5-9)
src/main/java/com/example/FixLog/mock/BookmarkFolderTestDataInitializer.java (2)
src/main/java/com/example/FixLog/mock/MemberTestDataInitializer.java (1)
Component(16-40)src/main/java/com/example/FixLog/mock/TagTestDataInitializer.java (1)
Component(13-30)
src/main/java/com/example/FixLog/dto/follow/response/FollowResponseDto.java (2)
src/main/java/com/example/FixLog/dto/follow/response/FollowerListResponseDto.java (1)
Getter(7-17)src/main/java/com/example/FixLog/dto/follow/response/FollowingListResponseDto.java (1)
Getter(7-17)
src/main/java/com/example/FixLog/domain/post/PostTag.java (2)
src/main/java/com/example/FixLog/domain/post/Post.java (1)
Entity(15-100)src/main/java/com/example/FixLog/domain/tag/Tag.java (1)
Entity(8-30)
src/main/java/com/example/FixLog/domain/bookmark/BookmarkFolder.java (2)
src/main/java/com/example/FixLog/domain/bookmark/Bookmark.java (1)
Entity(11-44)src/main/java/com/example/FixLog/domain/member/Member.java (1)
Entity(21-120)
src/main/java/com/example/FixLog/controller/MainPageController.java (1)
src/main/java/com/example/FixLog/controller/PostController.java (1)
RestController(10-45)
src/main/java/com/example/FixLog/dto/UserIdDto.java (5)
src/main/java/com/example/FixLog/dto/follow/request/FollowRequestDto.java (1)
Getter(7-12)src/main/java/com/example/FixLog/dto/follow/request/UnfollowRequestDto.java (1)
Getter(7-12)src/main/java/com/example/FixLog/dto/member/LoginRequestDto.java (1)
Getter(5-9)src/main/java/com/example/FixLog/dto/member/SignupRequestDto.java (1)
Getter(6-13)src/main/java/com/example/FixLog/dto/post/PostRequestDto.java (1)
Getter(7-25)
src/main/java/com/example/FixLog/dto/post/PostDto.java (1)
src/main/java/com/example/FixLog/dto/post/PostResponseDto.java (1)
Getter(8-17)
src/main/java/com/example/FixLog/dto/main/MainPagePostResponseDto.java (1)
src/main/java/com/example/FixLog/dto/main/MainPageResponseDto.java (1)
Getter(10-25)
src/main/java/com/example/FixLog/dto/follow/request/FollowRequestDto.java (1)
src/main/java/com/example/FixLog/dto/follow/request/UnfollowRequestDto.java (1)
Getter(7-12)
src/main/java/com/example/FixLog/service/MainPageService.java (1)
src/main/java/com/example/FixLog/service/PostService.java (1)
Service(31-187)
src/main/java/com/example/FixLog/dto/follow/response/FollowerListResponseDto.java (2)
src/main/java/com/example/FixLog/dto/follow/response/FollowResponseDto.java (1)
Getter(7-17)src/main/java/com/example/FixLog/dto/follow/response/FollowingListResponseDto.java (1)
Getter(7-17)
src/main/java/com/example/FixLog/dto/main/MainPageResponseDto.java (1)
src/main/java/com/example/FixLog/dto/main/MainPagePostResponseDto.java (1)
Getter(9-19)
🪛 YAMLlint (1.37.1)
.coderabbit.yaml
[error] 15-15: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (40)
.coderabbit.yaml (7)
2-2: 언어 설정 확인
ISO 639-1 확장 코드"ko-KR"이 스키마에 부합하며, PR 요구사항인 한국어 리뷰와 일치합니다.
3-3: early_access 설정 확인
early_access: false로 조기 접근 기능이 비활성화되어 있어 의도된 기본 설정과 일치합니다.
5-5: 리뷰 프로필 설정 확인
profile: "chill"설정으로 과도한 피드백을 피하는 모드가 활성화되어 있습니다. 의도에 부합합니다.
6-6: 자동 승인 워크플로우 확인 필요
request_changes_workflow: true로 설정하면 코드래빗 리뷰 완료 후 자동으로 PR이 승인됩니다. 이 동작이 팀의 리뷰 프로세스와 일치하는지 검토 부탁드립니다.
7-10: 리뷰 출력 옵션 확인
high_level_summary,poem,review_status,collapse_walkthrough등 리뷰 출력 관련 옵션이 의도대로 설정되어 있어 보입니다.
11-13: 자동 리뷰 세부 설정 확인
auto_review.enabled: true및drafts: false로 PR 자동 리뷰가 활성화되며, 드래프트는 제외됩니다. 의도된 동작인지 확인하세요.
14-15: 채팅 자동 응답 설정 확인
chat.auto_reply: true로 설정되어 있으며, 자동 응답 기능이 활성화됩니다. 의도에 부합합니다.🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 15-15: no new line character at the end of file
(new-line-at-end-of-file)
src/main/java/com/example/FixLog/repository/MemberRepository.java (1)
8-11: 표준적인 JPA 리포지토리 구현이 올바릅니다.Spring Data JPA의 메서드 네이밍 규칙을 잘 따르고 있으며, Optional 반환 타입을 사용하여 null 안전성을 확보했습니다. 이메일과 닉네임으로 회원을 조회하는 기본적인 기능이 잘 구현되어 있습니다.
src/main/java/com/example/FixLog/domain/member/SocialType.java (1)
3-6: 소셜 로그인 타입 열거형이 잘 구현되었습니다.간단하고 명확한 enum 구현입니다. 향후 다른 소셜 로그인 제공자(예: GOOGLE, KAKAO 등)를 추가하기 용이한 구조입니다.
src/main/java/com/example/FixLog/repository/tag/TagRepository.java (1)
1-7: 표준 JPA 리포지토리 구현이 잘 되어 있습니다.Spring Data JPA의 표준 패턴을 올바르게 따르고 있으며, 기본적인 CRUD 및 페이지네이션 기능을 제공합니다.
src/main/java/com/example/FixLog/repository/post/PostTagRepository.java (1)
1-7: Post와 Tag 간의 다대다 관계를 위한 리포지토리가 올바르게 구현되었습니다.PostTag 엔티티를 위한 표준 JPA 리포지토리 패턴을 잘 따르고 있습니다.
src/main/java/com/example/FixLog/dto/member/LoginResponseDto.java (1)
7-10: 응답 DTO 구현 양호
@JsonInclude(JsonInclude.Include.NON_NULL)와@AllArgsConstructor를 통해 null 필드 제외 및 생성자 주입이 잘 구성되었습니다.build.gradle (1)
37-39:Details
✅ Verification successful
spring-security-test 제거 영향 검증 요청
보안 관련 테스트에서@WithMockUser등 스프링 시큐리티 테스트 지원을 사용 중이라면 컴파일/실행 오류가 발생할 수 있습니다. 관련 의존성 제거 전후 테스트 통과 여부를 확인하세요.다음 스크립트를 실행하여 보안 테스트 의존성을 참조하는 코드를 찾아보세요:
🏁 Script executed:
#!/bin/bash # Verify no Spring Security test annotations are used without dependency rg -n "@WithMockUser" --glob="src/test/java/**/*.java"Length of output: 54
추가 검증을 위해 다음 스크립트를 실행해 보세요.
테스트 코드 전체에서 Spring Security 테스트 어노테이션 및 관련 임포트를 검색합니다.
🏁 Script executed:
#!/bin/bash # 1. @WithMockUser, @WithUserDetails, @WithAnonymousUser 어노테이션 검색 rg -n "@WithMockUser" rg -n "@WithUserDetails" rg -n "@WithAnonymousUser" # 2. Spring Security 테스트 의존성 임포트 검색 rg -n "import.*org.springframework.security.test"Length of output: 125
spring-security-test 의존성 제거 검증 완료
@WithMockUser,@WithUserDetails,@WithAnonymousUser및org.springframework.security.test임포트를 전체 테스트 코드에서 검색한 결과, 해당 어노테이션이나 관련 임포트가 전혀 발견되지 않았습니다.
따라서spring-security-test의존성 제거로 인한 컴파일/실행 오류는 발생하지 않습니다.src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkMoveRequest.java (2)
5-7: BookmarkMoveRequest DTO 구현 양호
Java 레코드를 활용해 간결하게 작성되었습니다.
1-4: Java 레코드 역직렬화 지원 확인 요청
Jackson이 Java 레코드 파라미터 역직렬화를 지원하도록jackson-module-parameter-names모듈이 등록되어 있는지 검증해주세요.src/main/java/com/example/FixLog/dto/bookmark/request/BookmarkFolderUpdateRequest.java (2)
5-7: DTO 구현 적절
Java 레코드를 활용하여 폴더 이름 업데이트 요청을 깔끔하게 표현했습니다.
6-6: JSON 프로퍼티 네이밍 검증 요청
@JsonProperty("name")으로 매핑된folderName필드가 API 문서 및 프론트엔드 요청 규격과 일치하는지 확인해주세요.src/main/java/com/example/FixLog/exception/CustomException.java (1)
8-10: 잘 구현된 커스텀 예외 클래스입니다.표준적인 예외 처리 패턴을 잘 따르고 있습니다:
- RuntimeException 확장으로 unchecked exception 구현
- Lombok을 활용한 깔끔한 코드
- ErrorCode enum을 통한 구조화된 에러 관리
src/main/java/com/example/FixLog/dto/member/DuplicateCheckResponseDto.java (1)
8-10: 코드가 잘 구현되었습니다.간단하고 명확한 DTO 구조로 중복 검사 응답을 위한 목적에 적합합니다.
src/main/java/com/example/FixLog/dto/bookmark/response/BookmarkFolderReadResponse.java (1)
5-8: Modern Java record 사용이 훌륭합니다.record 클래스와
@JsonProperty어노테이션을 사용하여 깔끔하고 불변의 DTO를 구현했습니다. API 응답의 일관성을 위한 JSON 필드명 지정도 적절합니다.src/main/java/com/example/FixLog/dto/post/PostResponseDto.java (1)
10-17: 포스트 응답 DTO가 잘 설계되었습니다.포스트 정보와 사용자별 상태(좋아요, 북마크)를 포함한 포괄적인 응답 구조입니다. 필드명이 명확하고 타입 선택도 적절합니다.
src/main/java/com/example/FixLog/domain/tag/TagCategory.java (1)
6-9: 깔끔한 enum 구조와 한글 표시명 적용을 잘 구현했습니다.태그 카테고리의 계층 구조(대분류, 중분류, 소분류)가 명확하게 정의되어 있고, 한글 표시명이 적절히 캡슐화되어 있습니다.
src/main/java/com/example/FixLog/dto/member/MemberInfoResponseDto.java (1)
9-15: 🛠️ Refactor suggestionDTO 구조는 양호하나 유효성 검증과 보안 고려사항을 추가하세요.
현재 구조는 깔끔하지만 다음 개선사항을 고려해보세요:
- 유효성 검증: 이메일 형식, URL 형식 등에 대한 검증 어노테이션 추가
- 민감정보 처리: 이메일과 같은 민감한 정보의 노출 범위 검토
- null 안전성: 필드에 대한 null 처리 정책 명시
다음과 같은 개선을 고려해보세요:
+import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Size; +import com.fasterxml.jackson.annotation.JsonInclude; +@JsonInclude(JsonInclude.Include.NON_NULL) public class MemberInfoResponseDto { + @Email(message = "올바른 이메일 형식이 아닙니다") private String email; + + @Size(max = 20, message = "닉네임은 20자를 초과할 수 없습니다") private String nickname; + private String profileImageUrl; private String bio; private SocialType socialType;Likely an incorrect or invalid review comment.
src/main/java/com/example/FixLog/domain/tag/Tag.java (1)
8-22: JPA 엔티티 구조가 모범 사례를 잘 따르고 있습니다.다음과 같은 좋은 설계 패턴이 적용되어 있습니다:
- 적절한 JPA 어노테이션 사용
EnumType.STRING사용으로 가독성 확보- 보호된 기본 생성자로 JPA 요구사항 충족
- 컬럼 제약조건 명시
src/main/java/com/example/FixLog/util/JwtUtil.java (1)
28-36: JWT 토큰 생성 로직이 잘 구현되었습니다.토큰에 필요한 정보(userId, email)를 적절히 포함하고, 만료 시간과 서명을 올바르게 설정했습니다. HMAC-SHA256 알고리즘 사용도 적절합니다.
src/main/java/com/example/FixLog/dto/Response.java (2)
19-25: 응답 래퍼 클래스가 잘 설계되었습니다.제네릭을 활용한 타입 안전성, 정적 팩토리 메서드를 통한 명확한 생성 방식, Jackson 어노테이션을 통한 적절한 JSON 직렬화 설정이 모두 잘 구현되어 있습니다.
6-6: JSON 직렬화 설정이 적절합니다.
@JsonInclude(JsonInclude.Include.NON_NULL)어노테이션을 통해 null 값을 응답에서 제외하는 것이 API 응답 크기를 줄이고 클라이언트 측 처리를 단순화하는 좋은 설계입니다.src/main/java/com/example/FixLog/dto/bookmark/response/BookmarkFolderPageResponse.java (1)
7-13: 페이지네이션 응답 DTO 구현이 잘 되어 있습니다.표준적인 페이지네이션 응답 패턴을 잘 따르고 있으며, Jackson 어노테이션을 통한 JSON 필드 매핑도 적절합니다. Record 클래스를 사용한 것도 불변 객체로서 DTO에 적합한 선택입니다.
src/main/java/com/example/FixLog/dto/main/MainPagePostResponseDto.java (1)
9-19: DTO 구조가 잘 설계되어 있습니다.메인 페이지에 필요한 포스트 정보를 효율적으로 담고 있으며,
LocalDate사용에 대한 주석도 의도를 명확히 설명하고 있어 좋습니다. Lombok 어노테이션 사용으로 보일러플레이트 코드도 적절히 줄였습니다.src/main/java/com/example/FixLog/repository/follow/FollowRepository.java (1)
10-15: 팔로우 기능에 필요한 메서드들이 잘 정의되어 있습니다.중복 팔로우 방지, 팔로우 관계 조회, 팔로워/팔로잉 목록 조회 등 핵심 기능에 필요한 메서드들이 Spring Data JPA 네이밍 규칙을 따라 명확하게 정의되어 있습니다. 각 메서드의 목적을 설명하는 한국어 주석도 도움이 됩니다.
src/main/java/com/example/FixLog/domain/bookmark/BookmarkFolder.java (1)
37-45: 생성자 오버로딩이 잘 구현되어 있습니다.사용자 지정 폴더명과 기본 폴더명("default folder")을 위한 두 가지 생성자가 적절히 제공되어 있어, 다양한 사용 시나리오를 지원할 수 있습니다.
src/main/java/com/example/FixLog/domain/bookmark/Bookmark.java (1)
35-39: 🛠️ Refactor suggestion생성자 매개변수명을 필드명과 일치시키세요.
위에서 제안한 필드명 변경에 따라 생성자도 함께 수정이 필요합니다.
필드명 변경 후 생성자도 다음과 같이 수정하세요:
- public Bookmark(BookmarkFolder folderId, Post postId){ - this.folderId = folderId; - this.postId = postId; + public Bookmark(BookmarkFolder folder, Post post){ + this.folder = folder; + this.post = post; this.isMarked = true; // 객체 생성 시 true }Likely an incorrect or invalid review comment.
src/main/java/com/example/FixLog/config/SecurityConfig.java (1)
30-34: PR 목표와 일치하지 않는 API 경로 설정PR 요약에서는 "/api" 접두사를 제거한다고 했으나, SecurityConfig에서는 여전히 "/api" 경로를 사용하고 있습니다.
다음 스크립트로 전체 코드베이스에서 API 경로 사용 현황을 확인해보세요:
#!/bin/bash # Description: API 경로 패턴 확인 # Expected: "/api" 접두사 사용 현황 파악 echo "=== Controller에서 /api 경로 사용 현황 ===" rg -A 3 -B 1 "RequestMapping.*api|PostMapping.*api|GetMapping.*api|PutMapping.*api|DeleteMapping.*api" echo "=== SecurityConfig에서 /api 경로 사용 현황 ===" rg -A 2 -B 2 "requestMatchers.*api"Likely an incorrect or invalid review comment.
src/main/java/com/example/FixLog/config/JwtAuthenticationFilter.java (1)
37-44: JWT 토큰 검증 및 인증 로직 검토JWT 토큰 검증과 인증 설정이 적절히 구현되어 있습니다.
MEMBER_NOT_FOUND에러 코드 사용은 PR 목표인 에러 메시지 통합과 일치합니다.src/main/java/com/example/FixLog/dto/main/MainPageResponseDto.java (1)
10-25: 잘 구현된 DTO 클래스DTO 구조가 깔끔하게 설계되었습니다.
@JsonInclude어노테이션을 사용하여 조건부 직렬화를 구현한 것과, 두 가지 생성자를 제공하여 유연성을 확보한 것이 좋습니다.src/main/java/com/example/FixLog/service/FollowService.java (2)
25-47: 팔로우 기능이 잘 구현되었습니다!자기 자신 팔로우 방지와 중복 팔로우 체크가 적절히 구현되어 있습니다.
69-84: 읽기 전용 트랜잭션 설정이 적절합니다!조회 메서드에
@Transactional(readOnly = true)를 사용하여 성능 최적화를 고려한 점이 좋습니다.src/main/java/com/example/FixLog/controller/BookmarkFolderController.java (3)
1-13: 임포트 구문이 적절합니다.필요한 의존성들이 올바르게 임포트되어 있고, 사용되지 않는 임포트는 없습니다.
15-20: 컨트롤러 클래스 선언이 적절합니다.
@RestController,@RequiredArgsConstructor,@RequestMapping어노테이션이 올바르게 사용되었고, 의존성 주입도 적절합니다.
66-74: 폴더 삭제 로직이 적절합니다.삭제 기능이 올바르게 구현되어 있습니다. 다만 다른 메서드들과 마찬가지로 인증 방식 개선을 고려해보세요.
src/main/java/com/example/FixLog/repository/bookmark/BookmarkRepository.java
Show resolved
Hide resolved
src/main/java/com/example/FixLog/config/JwtAuthenticationFilter.java
Outdated
Show resolved
Hide resolved
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.
Review continued from previous batch...
src/main/java/com/example/FixLog/controller/BookmarkFolderController.java
Show resolved
Hide resolved
src/main/java/com/example/FixLog/controller/BookmarkFolderController.java
Show resolved
Hide resolved
src/main/java/com/example/FixLog/controller/BookmarkFolderController.java
Show resolved
Hide resolved
…SER_NICKNAME_NOT_FOUND로 변경 후 로그인시 회원정보 없을 때 USER_NICKNAME_NOT_FOUND로 변경
이슈 번호
작업 내용
Summary by CodeRabbit
신규 기능
버그 수정
환경/설정
예외 처리 및 응답 포맷