Skip to content

[feat] 도메인 별 기본 클래스 구현 완료#10

Merged
KiSeungMin merged 21 commits into
developfrom
feature/seungmin
Jul 5, 2025
Merged

[feat] 도메인 별 기본 클래스 구현 완료#10
KiSeungMin merged 21 commits into
developfrom
feature/seungmin

Conversation

@KiSeungMin

@KiSeungMin KiSeungMin commented Jul 5, 2025

Copy link
Copy Markdown
Member

✔️ 연관 이슈

📝 작업 내용

  • 도메인 별 controller, service, repository, entity, exception, dto 정의 완료
  • BaseEntity 정의 완료
  • soft delete 구현 완료

기타 참고 사항

  • JPA 의존성을 추가했기 때문에 mysql을 연결해야 서버 실행이 가능합니다. Notion의 설정 정보/application.yml 파일을 참고해서 설정해주세요!

  • 저는 기초 틀만 작성한거기 때문에 클래스명, 필드명이나 디렉터리 구조 등은 모두 자유롭게 수정하셔도 돼요!

  • 엔티티에 TODO 라고 적어놓은 부분은 일부러 구현을 안 했습니다. 구현 방식이 다 다르실 것 같아서...!

  • direction이 길찾기 관련 디렉터리이고, search는 지도에서 검색 담당하는 디렉터리입니다.

스크린샷 (선택)

Summary by CodeRabbit

새로운 기능

  • 사용자, 리뷰, 검색, 웨이블존 관련 REST API 컨트롤러 및 서비스 추가
  • 사용자, 리뷰, 웨이블존 등 주요 엔티티 및 관련 이미지, 주소, 타입 등 엔티티/열거형 대거 도입
  • JPA 및 MySQL 연동, 자동 감사를 위한 설정 활성화
  • 표준화된 예외 처리 및 에러 케이스 정의

버그 수정

  • 해당 없음

기타

  • DTO, 레포지토리 등 기본 구조 및 소프트 딜리트(논리 삭제) 기능 구현

@KiSeungMin KiSeungMin self-assigned this Jul 5, 2025
@KiSeungMin KiSeungMin added the 💡 feature 기능 구현 및 개발 label Jul 5, 2025
@coderabbitai

coderabbitai Bot commented Jul 5, 2025

Copy link
Copy Markdown

"""

Walkthrough

이번 변경사항은 사용자, 리뷰, 검색, 웨이블존, 길찾기 도메인별로 controller, service, repository, entity, dto, exception 클래스의 기본 구조를 생성하였으며, JPA 및 MySQL 연동을 위한 설정과 공통 엔티티(감사 필드, 주소 등)도 도입하였습니다. 각 도메인별 예외 처리와 소프트 딜리트 기능도 포함되어 있습니다.

Changes

파일/경로 요약 변경 요약
build.gradle, ServerApplication.java JPA 및 MySQL 드라이버 의존성 추가, JPA Auditing 활성화
.../common/entity/Address.java, BaseEntity.java 공통 주소 및 감사 엔티티 클래스 추가
.../direction/, .../review/, .../search/, .../user/, .../wayblezone/** 각 도메인별 controller, service, repository, entity, dto, exception, enum 클래스 기본 구조 생성
.../entity/*Image.java, .../entity/Review.java, .../entity/WaybleZone.java, .../entity/User.java 리뷰, 웨이블존, 유저 엔티티에 소프트 딜리트 및 연관관계 매핑, 기본 필드 및 어노테이션 설정
.../dto/*.java 각 도메인별 기본 Dto(record) 클래스 추가 (필드 없음, 구조만 생성)
.../exception/*.java 각 도메인별 에러케이스 enum 클래스 추가
.../entity/*.java (enum) 각 도메인별 enum 타입(성별, 로그인타입, 유저타입, 웨이블존타입 등) 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Repository
    participant DB

    Client->>Controller: GET /{domain}/hello
    Controller->>Service: (Optional) 서비스 메서드 호출
    Service-->>Controller: 결과 반환
    Controller-->>Client: CommonResponse("hello")

    Client->>Controller: GET /{domain}/ex
    Controller->>Service: makeException()
    Service->>Controller: 예외 발생 (ApplicationException)
    Controller-->>Client: CommonResponse("예외 발생!")
Loading

Assessment against linked issues

Objective Addressed Explanation
도메인별 controller, service, repository, entity, dto, exception 클래스 구현 (#9)

Poem

( )
(•ㅅ•)
( づ♡

엔티티 틀을 쏙쏙쏙
도메인별로 콕콕콕
예외 처리도 빵빵!
JPA와 MySQL도 척척!
토끼는 오늘도 깡총깡총,
새 구조 위에 춤을 춥니다~

🐰✨
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c61723c and 6d7d78e.

📒 Files selected for processing (3)
  • src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/direction/service/DirectionService.java (1 hunks)
  • src/main/java/com/wayble/server/user/entity/User.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/wayble/server/user/entity/User.java
🔇 Additional comments (2)
src/main/java/com/wayble/server/direction/service/DirectionService.java (1)

12-14: 이전 리뷰 이슈가 성공적으로 해결되었습니다.

과거 리뷰에서 지적된 도메인 간 결합도 문제가 해결되었습니다. 이제 DirectionService에서 자체 도메인의 DirectionErrorCase.PATH_NOT_FOUND를 사용하고 있어 도메인 분리와 일관성이 잘 유지되고 있습니다.

src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java (1)

11-11: 이전 리뷰 이슈가 성공적으로 해결되었습니다.

과거 리뷰에서 지적된 명명 불일치 문제가 해결되었습니다. 이제 PATH_NOT_FOUND라는 길찾기 도메인에 적절한 이름을 사용하고 있으며, 에러 메시지도 도메인 컨텍스트에 잘 맞습니다.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

♻️ Duplicate comments (3)
src/main/java/com/wayble/server/wayblezone/controller/WaybleZoneController.java (1)

23-28: ReviewController와 동일한 예외 처리 문제가 있습니다.

이전에 지적한 것과 동일한 문제입니다. makeException() 호출 후 성공 응답을 반환하는 로직이 올바르지 않습니다.

src/main/java/com/wayble/server/user/controller/UserController.java (1)

23-28: 모든 컨트롤러에서 동일한 예외 처리 문제가 반복되고 있습니다.

다른 컨트롤러들과 동일한 문제입니다. 이런 패턴이 모든 도메인 컨트롤러에서 반복되고 있어, 잘못된 예외 처리 방식이 프로젝트 전체에 전파될 위험이 있습니다.

모든 컨트롤러에서 일관된 방식으로 수정하거나, 공통 기능이라면 추상 클래스나 유틸리티 메서드로 추출하는 것을 고려해보세요.

src/main/java/com/wayble/server/direction/controller/DirectionController.java (1)

23-28: 전체 컨트롤러에서 공통 패턴 추출을 고려해보세요.

동일한 예외 처리 문제가 모든 컨트롤러에서 반복되고 있습니다.

4개의 컨트롤러가 모두 동일한 구조를 가지고 있으므로, 다음과 같은 방식을 고려해보세요:

@RestController
public abstract class BaseController {
    
    @GetMapping("/hello")
    public CommonResponse<String> hello() {
        return CommonResponse.success("hello");
    }
    
    @GetMapping("/ex")
    public CommonResponse<String> exception() {
        // 올바른 예외 처리 로직 구현
        makeException();
        return CommonResponse.success("예외 테스트 완료");
    }
    
    protected abstract void makeException();
}

각 도메인 컨트롤러에서 이를 상속받아 사용하면 코드 중복을 줄이고 일관성을 유지할 수 있습니다.

🧹 Nitpick comments (21)
src/main/java/com/wayble/server/user/exception/UserErrorCase.java (1)

7-16: 에러 케이스 구현 적절함

ErrorCase 인터페이스를 구현하여 일관된 에러 처리 패턴을 따르고 있습니다. Lombok 애노테이션 사용으로 보일러플레이트 코드가 적절히 제거되었습니다.

도메인별 에러 코드 일관성을 위해 에러 코드 범위 정의를 고려해보세요:

// 예시: 사용자 도메인은 1000-1999 범위
USER_NOT_FOUND(400, 1001, "사용자를 찾을 수 없습니다.");
src/main/java/com/wayble/server/user/dto/UserResponseDto.java (1)

3-4: 빈 DTO 레코드라면 사용 의도·필드 계획을 주석으로 명시해주세요

현재 UserResponseDto 레코드가 비어 있어 실제 응답 필드가 무엇인지 파악하기 어렵습니다.
• 추후 필드를 채울 계획이라면 // TODO 형태의 주석으로 명시해 주세요.
• 그렇지 않다면 임시 클래스라는 설명을 JavaDoc 으로 남겨 두면 다른 개발자가 혼란을 겪지 않습니다.

src/main/java/com/wayble/server/user/dto/UserRegisterDto.java (1)

3-4: 빈 DTO 레코드의 목적을 명확히 해주세요

UserRegisterDto 역시 필드가 전혀 없습니다. 등록용 DTO 라면 최소한 넘어올 데이터 스펙(예: email, password 등)을 정의하거나, 향후 추가 예정임을 주석으로 표시하는 편이 좋습니다.

src/main/java/com/wayble/server/review/dto/ReviewRegisterDto.java (1)

3-4: DTO 스켈레톤만 존재 — 개발 가이드 주석 추가 권장

ReviewRegisterDto 가 비어 있어 실제 리뷰 등록 시 필요한 필드(예: content, rating 등) 정의가 없습니다. 다른 팀원이 참고할 수 있도록 간단한 JavaDoc 또는 TODO 주석을 추가해 주세요.

src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneResponseDto.java (1)

3-4: 응답 DTO 비어 있음 — 필드 설계 방향 문서화 필요

WaybleZoneResponseDto 가 비어있어 API 응답 구조를 예측하기 어렵습니다.
• 예정된 필드 목록을 주석으로 남기거나
• 임시 클래스임을 명확히 기술해주시면 좋겠습니다.

src/main/java/com/wayble/server/review/dto/ReviewResponseDto.java (1)

3-4: Review 응답 DTO가 비어 있습니다

향후 프론트엔드와의 계약을 위해 어떤 필드를 포함할지 간단히라도 TODO 를 남겨 주시면 의사소통에 도움이 됩니다.

src/main/java/com/wayble/server/user/entity/Gender.java (1)

3-5: UNKNOWN → 더 포괄적인 값 또는 주석 추가 고려
UNKNOWN 값은 실제 사용 시 “성별 미선택/기타” 의미로 쓰일 가능성이 높습니다. 다만 다국어 번역 시 부정적으로 보일 수 있으니 OTHER·UNSPECIFIED 등 중립적 용어로 교체하거나, Enum 자체에 간단한 Javadoc 으로 의미를 명시해 두시면 향후 프론트엔드·국제화 작업 시 혼선이 줄어듭니다.

src/main/java/com/wayble/server/user/entity/LoginType.java (1)

3-5: 향후 공급자 확장성 대비 문자열 코드 매핑 메서드 추가 제안
외부 소셜 로그인이 늘어날 수 있으므로 Enum 내부에 from(String code) / getCode() 같은 변환 메서드를 미리 두면, 컨트롤러·DTO 계층에서 문자열 ↔ Enum 변환 로직 중복을 방지할 수 있습니다.

src/main/java/com/wayble/server/user/repository/UserRepository.java (1)

6-7: 소프트 딜리트 엔티티 필터링 확인 필요
BaseEntity 에 소프트 딜리트 구현이 있다면, @Where(clause = "deleted = false") 같은 전역 필터가 엔티티에 적용됐는지 확인해주세요. 적용되지 않았다면 Repository 단에서 직접 exclude 하거나 Hibernate 필터를 설정해야 실제 조회 시 삭제된 데이터가 노출되지 않습니다.

src/main/java/com/wayble/server/ServerApplication.java (1)

5-9: @EnableJpaAuditing 사용 시 AuditorAware 빈 필요 여부 검토
현재 BaseEntity 가 createdDate, lastModifiedDate 만 사용한다면 문제없지만, 추후 createdBy, modifiedBy 필드를 추가할 계획이라면 AuditorAware<?> 빈을 등록해 두어야 합니다. 지금 단계에서 미리 템플릿 형태로 추가해 두면 나중에 감사 기능 확장 시 수고를 덜 수 있습니다.

src/main/java/com/wayble/server/review/repository/ReviewRepository.java (1)

6-7: 소프트 딜리트 및 페이징 최적화 고려
리뷰는 목록 조회 빈도가 높을 수 있습니다. 사용자에게 삭제된 리뷰가 보이지 않도록 @Where 필터 적용 여부 및 기본 정렬(최신순 등)을 JpaRepository 의 @EntityGraph 또는 쿼리 메서드로 정의해 두시면 성능과 유지보수성 모두 개선됩니다.

src/main/java/com/wayble/server/user/service/UserService.java (1)

9-18: 서비스 클래스 구조는 좋지만 예외 처리 메서드를 개선해주세요.

Spring의 표준 패턴을 잘 따르고 있습니다. 하지만 makeException() 메서드에 대해 몇 가지 개선사항을 제안합니다:

  1. 메서드명이 너무 일반적입니다. 목적을 더 명확히 하는 이름을 고려해보세요.
  2. 주입받은 UserRepository를 사용하지 않는 것 같습니다.
  3. 데모/테스트 목적이라면 메서드명에 이를 명시하는 것이 좋습니다.

다음과 같은 개선을 제안합니다:

-    public void makeException() {
+    public void throwUserNotFoundForDemo() {
         throw new ApplicationException(UserErrorCase.USER_NOT_FOUND);
     }

또는 실제 비즈니스 로직으로 대체:

-    public void makeException() {
-        throw new ApplicationException(UserErrorCase.USER_NOT_FOUND);
-    }
+    public User findUserById(Long userId) {
+        return userRepository.findById(userId)
+                .orElseThrow(() -> new ApplicationException(UserErrorCase.USER_NOT_FOUND));
+    }
src/main/java/com/wayble/server/search/service/SearchService.java (1)

12-14: 데모용 메서드의 명명 개선 필요

현재 makeException() 메서드는 데모/테스트 목적으로 보이지만, 메서드명이 그 의도를 명확히 표현하지 못합니다. 실제 검색 서비스 기능을 구현하기 전까지는 throwExceptionForDemo() 같은 더 명확한 이름을 사용하는 것이 좋겠습니다.

-    public void makeException() {
+    public void throwExceptionForDemo() {
         throw new ApplicationException(SearchErrorCase.SEARCH_EXCEPTION);
     }
src/main/java/com/wayble/server/common/entity/BaseEntity.java (1)

24-25: 소프트 삭제 편의 메서드 추가 제안

소프트 삭제 기능을 더 쉽게 사용할 수 있도록 편의 메서드를 추가하는 것을 고려해보세요.

     @Column(name = "deleted_at")
     private LocalDateTime deletedAt;
+    
+    public void softDelete() {
+        this.deletedAt = LocalDateTime.now();
+    }
+    
+    public boolean isDeleted() {
+        return this.deletedAt != null;
+    }
src/main/java/com/wayble/server/wayblezone/entity/WaybleZoneImage.java (2)

15-15: 데이터베이스 종속성을 고려해보세요.

현재 now() 함수를 직접 사용하고 있는데, 이는 MySQL 특정 함수입니다. 다른 데이터베이스로 전환할 가능성이 있다면 더 범용적인 방식을 고려해보세요.

-@SQLDelete(sql = "UPDATE wayble_zone_image SET deleted_at = now() WHERE id = ?")
+@SQLDelete(sql = "UPDATE wayble_zone_image SET deleted_at = CURRENT_TIMESTAMP WHERE id = ?")

또는 JPA의 @PreRemove와 함께 BaseEntity의 deletedAt 필드를 활용하는 방법도 있습니다.


11-11: 빌더 패턴 접근성 개선을 고려해보세요.

현재 빌더가 private로 설정되어 있어 외부에서 사용할 수 없습니다. 엔티티 생성을 위한 정적 팩토리 메서드를 추가하거나 빌더 접근성을 조정하는 것을 고려해보세요.

-@Builder(access = AccessLevel.PRIVATE)
+@Builder(access = AccessLevel.PACKAGE)

또는 정적 팩토리 메서드 추가:

public static WaybleZoneImage create(WaybleZone waybleZone, String imageUrl) {
    return WaybleZoneImage.builder()
        .waybleZone(waybleZone)
        .imageUrl(imageUrl)
        .build();
}
src/main/java/com/wayble/server/review/entity/Review.java (2)

33-36: 필드 초기화 방식을 개선하는 것을 고려해보세요.

엔티티에서 직접 기본값을 설정하는 것보다는 데이터베이스 레벨에서 기본값을 설정하거나 생성자/빌더 패턴을 통해 초기화하는 것이 더 명확할 수 있습니다.

-    @Column(nullable = false)
-    private double rating = 0.0;
-
-    @Column(nullable = false)
-    private Integer likeCount = 0;
+    @Column(nullable = false, columnDefinition = "DOUBLE DEFAULT 0.0")
+    private double rating;
+
+    @Column(nullable = false, columnDefinition = "INTEGER DEFAULT 0")
+    private Integer likeCount;

49-52: TODO 코멘트 처리를 추적하세요.

접근성 정보 관련 구현이 필요하다고 표시되어 있습니다. 이를 별도 이슈로 관리하거나 구현 계획을 수립하는 것이 좋겠습니다.

접근성 정보를 위한 별도 엔티티나 임베디드 클래스 설계에 대한 도움이 필요하시면 알려주세요.

src/main/java/com/wayble/server/user/entity/User.java (1)

59-64: TODO 코멘트들을 체계적으로 관리하세요.

여러 중요한 기능들이 TODO로 표시되어 있습니다. 이들을 별도 이슈로 만들어 추적하는 것을 권장합니다.

각 TODO 항목에 대한 구체적인 구현 계획이나 이슈 생성을 도와드릴 수 있습니다.

src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (2)

53-55: 불필요한 TODO 코멘트입니다.

Review 엔티티가 이미 구현되어 있고 관계 매핑도 완료되어 있습니다. 이 TODO 코멘트는 제거해도 될 것 같습니다.

-    /**
-     * TODO: Review 관련 엔티티 구현 필요
-     */

45-60: TODO 코멘트들을 체계적으로 관리하세요.

영업 시간, 장애 시설 정보, 내가 저장한 장소 등 중요한 기능들이 TODO로 표시되어 있습니다. 이들을 별도 이슈로 만들어 우선순위를 정하고 관리하는 것을 권장합니다.

각 TODO 항목에 대한 구체적인 구현 방안이나 데이터 모델 설계를 도와드릴 수 있습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe179ef and c61723c.

📒 Files selected for processing (39)
  • build.gradle (1 hunks)
  • src/main/java/com/wayble/server/ServerApplication.java (1 hunks)
  • src/main/java/com/wayble/server/common/entity/Address.java (1 hunks)
  • src/main/java/com/wayble/server/common/entity/BaseEntity.java (1 hunks)
  • src/main/java/com/wayble/server/direction/controller/DirectionController.java (1 hunks)
  • src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/direction/service/DirectionService.java (1 hunks)
  • src/main/java/com/wayble/server/review/controller/ReviewController.java (1 hunks)
  • src/main/java/com/wayble/server/review/dto/ReviewRegisterDto.java (1 hunks)
  • src/main/java/com/wayble/server/review/dto/ReviewResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/review/entity/Review.java (1 hunks)
  • src/main/java/com/wayble/server/review/entity/ReviewImage.java (1 hunks)
  • src/main/java/com/wayble/server/review/exception/ReviewErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/review/repository/ReviewImageRepository.java (1 hunks)
  • src/main/java/com/wayble/server/review/repository/ReviewRepository.java (1 hunks)
  • src/main/java/com/wayble/server/review/service/ReviewService.java (1 hunks)
  • src/main/java/com/wayble/server/search/controller/SearchController.java (1 hunks)
  • src/main/java/com/wayble/server/search/exception/SearchErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/search/service/SearchService.java (1 hunks)
  • src/main/java/com/wayble/server/user/controller/UserController.java (1 hunks)
  • src/main/java/com/wayble/server/user/dto/UserRegisterDto.java (1 hunks)
  • src/main/java/com/wayble/server/user/dto/UserResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/user/entity/Gender.java (1 hunks)
  • src/main/java/com/wayble/server/user/entity/LoginType.java (1 hunks)
  • src/main/java/com/wayble/server/user/entity/User.java (1 hunks)
  • src/main/java/com/wayble/server/user/entity/UserType.java (1 hunks)
  • src/main/java/com/wayble/server/user/exception/UserErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/user/repository/UserRepository.java (1 hunks)
  • src/main/java/com/wayble/server/user/service/UserService.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/controller/WaybleZoneController.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneRegisterDto.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneResponseDto.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/entity/WaybleZoneImage.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/entity/WaybleZoneType.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/exception/WaybleZoneErrorCase.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/repository/WaybleZoneImageRepository.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/repository/WaybleZoneRepository.java (1 hunks)
  • src/main/java/com/wayble/server/wayblezone/service/WaybleZoneService.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/main/java/com/wayble/server/common/entity/Address.java (1)
src/main/java/com/wayble/server/user/entity/User.java (1)
  • Getter (17-64)
src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (1)
src/main/java/com/wayble/server/wayblezone/entity/WaybleZoneImage.java (1)
  • Entity (9-29)
🔇 Additional comments (19)
build.gradle (2)

27-27: JPA 의존성 추가 승인

JPA 지원을 위한 spring-boot-starter-data-jpa 의존성 추가가 적절합니다. 도메인별 엔티티 구현에 필요한 기본 설정입니다.


31-31: MySQL 드라이버 의존성 적절히 구성됨

MySQL 커넥터가 runtimeOnly로 올바르게 구성되었습니다. 이는 컴파일 시점에는 필요하지 않고 런타임에만 필요한 드라이버의 특성에 맞는 설정입니다.

src/main/java/com/wayble/server/user/entity/UserType.java (1)

3-12: 사용자 타입 열거형 구현이 적절함

사용자 유형을 명확히 구분하는 열거형이 잘 정의되었습니다. 각 타입에 대한 한국어 주석이 코드 이해에 도움이 됩니다.

src/main/java/com/wayble/server/common/entity/Address.java (2)

7-9: @embeddable 애노테이션 적절히 사용됨

JPA 임베딩을 위한 @embeddable 애노테이션이 올바르게 사용되었습니다. 주소 정보를 재사용 가능한 컴포넌트로 설계한 것이 좋습니다.


31-36: 위경도 정밀도 설정 적절함

위도와 경도를 DECIMAL(10,7)로 설정하여 GPS 좌표의 정밀도를 적절히 보장했습니다. 이는 약 1m 정도의 정확도를 제공합니다.

src/main/java/com/wayble/server/wayblezone/entity/WaybleZoneType.java (1)

3-12: 깔끔한 열거형 구현입니다.

구현이 간단하고 명확하며, 각 상수에 대한 한국어 주석이 도움이 됩니다. 코드가 이해하기 쉽고 유지보수가 용이합니다.

src/main/java/com/wayble/server/review/repository/ReviewImageRepository.java (1)

6-7: 표준 JPA 저장소 인터페이스 구현입니다.

Spring Data JPA의 표준 패턴을 따르며, 적절한 제네릭 타입을 사용하고 있습니다. 기본 CRUD 작업에 충분한 구현입니다.

src/main/java/com/wayble/server/wayblezone/repository/WaybleZoneRepository.java (1)

6-7: 표준 JPA 저장소 인터페이스 구현입니다.

Spring Data JPA의 표준 패턴을 따르며, WaybleZone 엔티티에 대한 기본 CRUD 작업을 제공합니다.

src/main/java/com/wayble/server/wayblezone/repository/WaybleZoneImageRepository.java (1)

6-7: 표준 JPA 저장소 인터페이스 구현입니다.

다른 저장소 인터페이스와 일관된 패턴을 따르며, WaybleZoneImage 엔티티에 대한 기본 CRUD 작업을 제공합니다.

src/main/java/com/wayble/server/review/service/ReviewService.java (1)

9-17: 기본 구조 구현 완료

ReviewService의 기본 구조가 올바르게 구현되었습니다. 현재는 플레이스홀더 구현이지만 향후 비즈니스 로직 추가를 위한 기반이 잘 마련되어 있습니다.

src/main/java/com/wayble/server/wayblezone/exception/WaybleZoneErrorCase.java (1)

7-16: 에러 케이스 enum 구조 잘 설계됨

WaybleZoneErrorCase가 ErrorCase 인터페이스를 올바르게 구현하고 있으며, 도메인별 에러 코드(2001)와 적절한 한국어 메시지를 포함하고 있습니다.

src/main/java/com/wayble/server/review/exception/ReviewErrorCase.java (1)

7-16: 에러 케이스 enum 구조 올바르게 구현됨

ReviewErrorCase가 ErrorCase 인터페이스를 올바르게 구현하고 있으며, 도메인별 에러 코드(3001)와 적절한 한국어 메시지를 포함하고 있습니다.

src/main/java/com/wayble/server/wayblezone/service/WaybleZoneService.java (1)

10-21: 기본 구조 및 에러 케이스 사용 올바름

WaybleZoneService의 기본 구조가 올바르게 구현되었으며, 도메인별 에러 케이스(WaybleZoneErrorCase)를 적절히 사용하고 있습니다. 현재는 플레이스홀더 구현이지만 향후 비즈니스 로직 추가를 위한 기반이 잘 마련되어 있습니다.

src/main/java/com/wayble/server/search/exception/SearchErrorCase.java (1)

7-16: 잘 구현된 에러 케이스 정의

도메인과 일치하는 명명 규칙을 사용하고 있으며, 에러 코드 체계도 일관성 있게 구성되어 있습니다. 한국어 에러 메시지도 명확하게 작성되었습니다.

src/main/java/com/wayble/server/common/entity/BaseEntity.java (1)

13-26: 잘 설계된 베이스 엔티티

JPA 감사 기능과 소프트 삭제 패턴이 올바르게 구현되어 있습니다. @MappedSuperclass 사용으로 공통 필드를 효율적으로 관리할 수 있습니다.

src/main/java/com/wayble/server/wayblezone/entity/WaybleZoneImage.java (2)

9-17: 엔티티 구조가 잘 설계되었습니다.

BaseEntity 상속, 소프트 삭제 구현, 적절한 Lombok 어노테이션 사용 등이 모두 올바르게 구현되었습니다.


23-25: 지연 로딩 설정이 적절합니다.

FetchType.LAZY를 사용하여 성능 최적화를 고려한 좋은 구현입니다.

src/main/java/com/wayble/server/review/entity/ReviewImage.java (1)

1-30: 엔티티 구조가 잘 설계되었습니다.

ReviewImage 엔티티의 구현이 깔끔하고 일관성 있게 작성되었습니다. 소프트 삭제 기능과 관계 매핑이 적절하게 구현되어 있습니다.

src/main/java/com/wayble/server/wayblezone/entity/WaybleZone.java (1)

36-44: 관계 매핑이 적절하게 구성되었습니다.

Address 임베디드 클래스 사용과 일대다 관계 매핑이 깔끔하게 구현되어 있습니다. 연관된 WaybleZoneImage 엔티티와의 관계도 올바르게 설정되어 있습니다.

Comment on lines +7 to +37
@Getter
@Embeddable
public class Address {
/** 시·도 */
@Column(name = "state", length = 100, nullable = false)
private String state;

/** 시·군·구 */
@Column(name = "city", length = 100, nullable = false)
private String city;

/** 동·읍·면 */
@Column(name = "district", length = 100)
private String district;

/** 도로명 주소 */
@Column(name = "street_address", length = 200)
private String streetAddress;

/** 상세 주소 */
@Column(name = "detail_address", length = 200)
private String detailAddress;

/** 위도 */
@Column(name = "latitude", columnDefinition = "DECIMAL(10,7)", nullable = false)
private Double latitude;

/** 경도 */
@Column(name = "longitude", columnDefinition = "DECIMAL(10,7)", nullable = false)
private Double longitude;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

생성자와 유효성 검증 추가 고려

Address 클래스에 생성자와 유효성 검증을 추가하는 것을 고려해보세요.

@Getter
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PUBLIC)
public class Address {
    // ... 기존 필드들 ...
    
    // 필수 필드 생성자
    public Address(String state, String city, Double latitude, Double longitude) {
        this.state = validateNotBlank(state, "시·도는 필수입니다");
        this.city = validateNotBlank(city, "시·군·구는 필수입니다");
        this.latitude = validateLatitude(latitude);
        this.longitude = validateLongitude(longitude);
    }
    
    private String validateNotBlank(String value, String message) {
        if (value == null || value.trim().isEmpty()) {
            throw new IllegalArgumentException(message);
        }
        return value;
    }
    
    private Double validateLatitude(Double latitude) {
        if (latitude == null || latitude < -90 || latitude > 90) {
            throw new IllegalArgumentException("위도는 -90~90 범위여야 합니다");
        }
        return latitude;
    }
    
    private Double validateLongitude(Double longitude) {
        if (longitude == null || longitude < -180 || longitude > 180) {
            throw new IllegalArgumentException("경도는 -180~180 범위여야 합니다");
        }
        return longitude;
    }
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/common/entity/Address.java lines 7 to 37, add
constructors and validation methods to ensure required fields are set and valid.
Implement a protected no-args constructor and a public all-args constructor
using Lombok annotations. Add a custom constructor for mandatory fields (state,
city, latitude, longitude) that validates non-blank strings for state and city,
and checks latitude is between -90 and 90 and longitude between -180 and 180,
throwing IllegalArgumentException if validations fail.

Comment on lines +3 to +4
public record WaybleZoneRegisterDto() {
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

빈 DTO 레코드 구현 필요

WaybleZoneRegisterDto가 빈 레코드로 정의되어 있어 실제 등록 기능에서 사용할 수 없습니다. 등록에 필요한 필드들을 정의해야 합니다.

다음과 같은 필드들을 추가하는 것을 고려해보세요:

public record WaybleZoneRegisterDto(
    String name,
    String description,
    WaybleZoneType type,
    Address address,
    // 기타 필요한 필드들
) {
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneRegisterDto.java at
lines 3 to 4, the WaybleZoneRegisterDto is currently an empty record with no
fields, making it unusable for registration purposes. To fix this, define the
record with the necessary fields such as name, description, type
(WaybleZoneType), and address (Address), along with any other required fields to
properly represent the data needed for zone registration.

@RequiredArgsConstructor
public enum ReviewErrorCase implements ErrorCase {

REVIEW_NOT_FOUND(400, 3001, "리뷰를 찾을 수 없습니다.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

도메인 간 에러 케이스 사용 검증 필요

DirectionService에서 이 ReviewErrorCase를 잘못 사용하고 있는 것이 확인되었습니다. 각 도메인은 자신만의 에러 케이스를 사용해야 합니다.

다음 스크립트를 실행하여 ReviewErrorCase가 다른 도메인에서 잘못 사용되고 있는지 확인해주세요:


🏁 Script executed:

#!/bin/bash
# ReviewErrorCase가 review 도메인 외부에서 사용되는지 확인
rg -A 3 "ReviewErrorCase" --type java | grep -v "review/"

Length of output: 799


DirectionService에서 ReviewErrorCase 사용 금지 및 도메인 전용 에러 케이스 도입

DirectionService에서 리뷰 도메인 전용 에러 케이스(ReviewErrorCase)를 참조하고 있습니다. 각 도메인은 고유한 에러 케이스를 사용해야 하므로, direction 도메인용 에러 케이스를 새로 정의하고 해당 부분을 교체해주세요.

  • 수정 대상
    • src/main/java/com/wayble/server/direction/service/DirectionService.java

  • 조치 사항

    1. direction 도메인용 에러 케이스(enum) 생성
      • 예: src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java
    2. import 및 예외 발생부 변경
      - import com.wayble.server.review.exception.ReviewErrorCase;
      + import com.wayble.server.direction.exception.DirectionErrorCase;
      
      - throw new ApplicationException(ReviewErrorCase.REVIEW_NOT_FOUND);
      + throw new ApplicationException(DirectionErrorCase.REVIEW_NOT_FOUND);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/review/exception/ReviewErrorCase.java at line
11, the ReviewErrorCase enum is being used in the DirectionService, which
violates domain separation. To fix this, create a new enum DirectionErrorCase in
src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java with
appropriate error codes for the direction domain. Then, update
src/main/java/com/wayble/server/direction/service/DirectionService.java to
import and use DirectionErrorCase instead of ReviewErrorCase for error handling.

Comment thread src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java Outdated
Comment on lines +24 to +28
@GetMapping("/ex")
public CommonResponse<String> exception() {
searchService.makeException();
return CommonResponse.success("예외 발생!");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

예외 처리 로직 오류

/ex 엔드포인트에서 searchService.makeException()을 호출하면 예외가 발생하여 다음 줄의 return 문은 실행되지 않습니다. 이는 도달할 수 없는 코드(unreachable code)입니다.

예외 처리 데모가 목적이라면 try-catch 블록을 사용하거나, 아니면 success 응답 반환 부분을 제거해야 합니다:

     @GetMapping("/ex")
     public CommonResponse<String> exception() {
-        searchService.makeException();
-        return CommonResponse.success("예외 발생!");
+        try {
+            searchService.makeException();
+            return CommonResponse.success("예외 발생하지 않음");
+        } catch (ApplicationException e) {
+            throw e; // 글로벌 예외 핸들러에서 처리
+        }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@GetMapping("/ex")
public CommonResponse<String> exception() {
searchService.makeException();
return CommonResponse.success("예외 발생!");
}
@GetMapping("/ex")
public CommonResponse<String> exception() {
try {
searchService.makeException();
return CommonResponse.success("예외 발생하지 않음");
} catch (ApplicationException e) {
throw e; // 글로벌 예외 핸들러에서 처리
}
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/search/controller/SearchController.java
around lines 24 to 28, the method calls searchService.makeException() which
throws an exception, making the subsequent return statement unreachable. To fix
this, wrap the call to makeException() in a try-catch block to handle the
exception and then return the success response, or remove the return statement
if the exception is meant to propagate without a success response.

Comment on lines +23 to +28
// 예외 사용 참고용 컨트롤러(지우셔도 돼요)
@GetMapping("/ex")
public CommonResponse<String> exception() {
reviewService.makeException();
return CommonResponse.success("예외 발생!");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

예외 처리 로직이 잘못되었습니다.

makeException() 메서드를 호출한 후 성공 응답을 반환하는 것은 논리적으로 맞지 않습니다. 예외가 발생했다면 해당 지점에서 예외가 던져져야 하고, 이후 코드는 실행되지 않아야 합니다.

현재 구현에서는 예외가 실제로 발생하지 않거나, 발생해도 적절히 처리되지 않는 상황을 암시합니다.

다음과 같이 수정하는 것을 고려해보세요:

// 예외 사용 참고용 컨트롤러(지우셔도 돼요)
@GetMapping("/ex")
public CommonResponse<String> exception() {
-    reviewService.makeException();
-    return CommonResponse.success("예외 발생!");
+    // 이 메서드는 예외를 발생시키므로 성공 응답은 반환되지 않습니다
+    reviewService.makeException();
+    // 이 줄은 실행되지 않습니다
+    return CommonResponse.success("이 메시지는 보이지 않습니다");
}

또는 예외 처리를 명시적으로 보여주려면:

@GetMapping("/ex")
public CommonResponse<String> exception() {
+    try {
+        reviewService.makeException();
+        return CommonResponse.success("예외가 발생하지 않았습니다");
+    } catch (Exception e) {
+        // 실제로는 GlobalExceptionHandler에서 처리됩니다
+        throw e;
+    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 예외 사용 참고용 컨트롤러(지우셔도 돼요)
@GetMapping("/ex")
public CommonResponse<String> exception() {
reviewService.makeException();
return CommonResponse.success("예외 발생!");
}
// 예외 사용 참고용 컨트롤러(지우셔도 돼요)
@GetMapping("/ex")
public CommonResponse<String> exception() {
// 이 메서드는 예외를 발생시키므로 성공 응답은 반환되지 않습니다
reviewService.makeException();
// 이 줄은 실행되지 않습니다
return CommonResponse.success("이 메시지는 보이지 않습니다");
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/review/controller/ReviewController.java
around lines 23 to 28, the method calls reviewService.makeException() but then
returns a success response, which is logically incorrect if an exception is
expected. To fix this, remove the success return statement after calling
makeException() so that if an exception occurs, it propagates properly and the
method does not continue execution. Alternatively, explicitly catch the
exception within the method and handle it appropriately to demonstrate exception
handling.

Comment on lines +38 to +39
// TODO: 비밀번호 암호화 필요
private String password;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

패스워드 보안 처리가 시급합니다.

패스워드가 평문으로 저장될 수 있는 상황입니다. 이는 중요한 보안 이슈이므로 가능한 한 빨리 해결해야 합니다.

Spring Security의 PasswordEncoder를 사용하여 패스워드를 암호화하는 것을 권장합니다:

@PrePersist
@PreUpdate
private void encryptPassword() {
    if (password != null && !password.startsWith("$2a$")) {
        // BCrypt로 암호화 (예시)
        this.password = passwordEncoder.encode(password);
    }
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/user/entity/User.java at lines 38-39, the
password field is stored in plain text, which is a critical security issue. To
fix this, implement password encryption using Spring Security's PasswordEncoder
by adding a method annotated with @PrePersist and @PreUpdate that checks if the
password is already encrypted and, if not, encrypts it before saving. Ensure to
inject or access a PasswordEncoder instance to perform the encryption.

Comment thread src/main/java/com/wayble/server/user/entity/User.java

@seung-in-Yoo seung-in-Yoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기본틀 설계가 너무 좋네요 수고하셨습니다!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 feature 기능 구현 및 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants