Skip to content

Conversation

@unifolio0
Copy link
Contributor

@unifolio0 unifolio0 commented Jul 29, 2025

🚩 Jira Ticket

SCRUM-64

🗣️ 리뷰 요구사항 (선택)

급한 마음에 여러가지 태스크를 한번에 작업했습니다. 다음 pr부터는 이런 일이 없도록 작은 단위로 올리겠습니다.

Summary by CodeRabbit

  • 신규 기능

    • 즐겨찾기 및 예약 관련 서비스, 컨트롤러, DTO가 추가되어 사용자가 즐겨찾는 식당 관리 및 예약이 가능해졌습니다.
    • 식당의 예약 가능 날짜 조회, 주변 식당 검색, 식당 상세 정보 제공 기능이 추가되었습니다.
    • 도메인 계층에 멤버, 오너, 식당, 예약, 리뷰 등 엔터티 및 서비스가 신설되었습니다.
  • 버그 수정

    • 없음
  • 리팩터

    • 패키지 구조 및 클래스명 변경, 기존 엔터티 및 레포지토리의 위치 이동이 이루어졌습니다.
    • 예외 처리 구조가 개선되어 도메인별로 세분화된 에러 코드와 예외가 도입되었습니다.
  • 테스트

    • 통합 및 단위 테스트 클래스가 추가되고, 테스트 환경 구성이 개선되었습니다.
  • 문서 및 설정

    • 멀티 모듈 Gradle 프로젝트로 구조화되었으며, 각 모듈별 빌드 스크립트가 추가되었습니다.
    • 설정 파일이 보완되고, Flyway 관련 불필요한 설정이 제거되었습니다.

@unifolio0 unifolio0 self-assigned this Jul 29, 2025
@unifolio0 unifolio0 added the feat label Jul 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 29, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

이 변경사항은 프로젝트를 멀티 모듈 구조로 대대적으로 리팩토링하며, 각 도메인별로 분리된 패키지와 서비스, 엔티티, 레포지토리, 예외처리, DTO, 컨트롤러, Gradle 빌드 설정 등을 새롭게 도입합니다. 또한, 기존 코드의 패키지명, 클래스명, import 경로, 엔티티 상속 구조, 컨트롤러 엔드포인트, 테스트 코드 등도 새로운 구조에 맞게 일괄적으로 변경 및 추가되었습니다.

Changes

Cohort / File(s) Change Summary
Gradle 멀티모듈 및 설정
build.gradle, settings.gradle, common/build.gradle, domain/build.gradle, api-owner/build.gradle, api-user/build.gradle
전체 프로젝트를 멀티모듈로 분리하고, 각 모듈별로 의존성 및 플러그인, 빌드 설정을 분리/정의.
애플리케이션 엔트리포인트 및 테스트
api-owner/src/main/java/com/wellmeet/ApiOwnerApplication.java, api-user/src/main/java/com/wellmeet/ApiUserApplication.java, api-user/src/test/java/com/wellmeet/ApiUserApplicationTests.java, domain/src/test/java/com/wellmeet/TestConfiguration.java
각 모듈별로 Spring Boot 애플리케이션 진입점 및 기본 context load 테스트 클래스 추가.
패키지/도메인별 엔티티, 서비스, 레포지토리 신규 도입 및 이동
domain/src/main/java/com/wellmeet/domain/..., domain/src/test/java/com/wellmeet/...
도메인별로 엔티티, 서비스, 레포지토리, 예외, 테스트 등 신규 생성 및 기존 코드 이동/리팩토링.
API 모듈 서비스/컨트롤러/DTO 추가 및 리팩토링
api-user/src/main/java/com/wellmeet/..., api-owner/src/main/java/com/wellmeet/...
사용자/사장님용 API 모듈별로 서비스, 컨트롤러, DTO 등 신규 생성 및 경로, 엔드포인트, 메서드명 등 리팩토링.
DTO/테스트 import 및 생성자, 필드명 일괄 변경
api-user/src/main/java/com/wellmeet/restaurant/dto/*, api-user/src/test/java/com/wellmeet/*
도메인 구조 변경에 따라 import 경로, 생성자, 필드명, 테스트 경로 등 일괄 수정.
예외 및 에러코드 체계 도입
api-user/src/main/java/com/wellmeet/exception/*, domain/src/main/java/com/wellmeet/domain/exception/*
API/도메인 계층별로 에러코드 Enum, 커스텀 예외 클래스, 글로벌 예외 핸들러 등 신규 도입 및 기존 코드 일괄 적용.
설정 파일 추가/수정
api-user/src/main/resources/application-dev.yml, api-user/src/main/resources/application-local.yml, domain/src/test/resources/application.yml
환경별 데이터베이스, JPA, SQL 초기화 등 설정 추가 및 일부 설정 제거.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant FavoriteController
  participant FavoriteService
  participant MemberDomainService
  participant RestaurantDomainService
  participant FavoriteRestaurantDomainService
  participant ReviewDomainService

  User->>FavoriteController: GET /user/favorite/restaurant?memberId=
  FavoriteController->>FavoriteService: getFavoriteRestaurants(memberId)
  FavoriteService->>FavoriteRestaurantDomainService: findAllByMemberId(memberId)
  FavoriteService->>ReviewDomainService: getAverageRating(restaurantId)
  FavoriteService-->>FavoriteController: List<FavoriteRestaurantResponse>
  FavoriteController-->>User: 응답 반환
Loading
sequenceDiagram
  participant User
  participant ReservationController
  participant ReservationService
  participant ReservationDomainService
  participant RestaurantDomainService

  User->>ReservationController: POST /user/reservation
  ReservationController->>ReservationService: reserve(memberId, request)
  ReservationService->>ReservationDomainService: save(Reservation)
  ReservationService->>RestaurantDomainService: getOptionByRestaurantAndOptionId(...)
  ReservationService-->>ReservationController: CreateReservationResponse
  ReservationController-->>User: 201 Created
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related PRs

Suggested labels

refactor

Suggested reviewers

  • ezcolin2

Poem

🐇
모듈이 나뉘고, 패키지 춤추네
서비스, 엔티티, 컨트롤러 새 둥지
예외도 새 옷, DTO도 반짝
토끼는 깡총깡총, 코드정원 탐험
리뷰어님, 당근 한 입 힘내세요!
🥕✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 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 06e8f51 and 0155a1f.

📒 Files selected for processing (17)
  • api-owner/src/main/java/com/wellmeet/owner/OwnerController.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/owner/OwnerService.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/reservation/ReservationService.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/FavoriteController.java (2 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/ReservationController.java (2 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java (3 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java (4 hunks)
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (4 hunks)
  • common/build.gradle (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/ReservationDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/BusinessHour.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/ReviewDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/repository/ReviewRepository.java (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 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 generate unit tests to generate unit tests for 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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🔭 Outside diff range comments (3)
api-user/src/main/java/com/wellmeet/restaurant/menu/domain/Menu.java (1)

35-37: 가격 필드에 int 사용은 금액 손실 위험

금액(원화 등)은 소수점 오차 없는 long(최소 단위) 또는 BigDecimal 사용이 권장됩니다. int 범위(약 21억) 초과 금액이나 할인 계산 시 부정확성이 발생할 수 있습니다.

-    private int price;
+    private long price;

Price 계산 로직/DTO도 함께 수정되어야 합니다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/ReviewTag.java (1)

24-33: 생성자 부재로 불변성 보장 어려움

reviewtag 필드가 @NotNull이지만 엔티티 내부에 이를 세팅할 수 있는 생성자/팩토리 메서드가 없습니다. JPA 프록시가 아닌 일반 코드에서 객체를 만들 때 필드가 비어있는 상태로 생성될 위험이 있습니다.

+@Builder
+public ReviewTag(Review review, Tag tag) {
+    this.review = review;
+    this.tag = tag;
+}

빌더나 정적 팩토리를 통해 필수 필드를 강제하면 무결성이 높아집니다.

api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1)

31-34: N+1 성능 이슈 가능성

즐겨찾기 레스토랑 목록 조회 시 reviewService.getAverageRating이 레스토랑마다 개별 쿼리를 날리면 N+1 문제가 발생합니다.
ReviewRepository에서 IN 절로 한 번에 평균 평점을 가져오거나, Restaurant에 평점 평균을 캐싱하는 옵션을 검토해 보세요.

🧹 Nitpick comments (10)
domain/build.gradle (1)

1-9: domain 모듈 의존성 중복

domain 모듈이 implementation project(':common')spring-boot-starter-data-jpa·validation을 이미 전이 의존성으로 받는다면, 4–5행의 동일 의존성 선언은 중복입니다.
또한 H2·MySQL 두 데이터베이스 드라이버를 동시에 runtimeOnly로 포함하면 의도치 않은 드라이버 선택 문제가 생길 수 있습니다. 운영용 DB가 MySQL이라면 H2는 테스트 스코프로 이동하는 것이 안전합니다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/Review.java (1)

52-57: 별점 검증 로직은 좋으나 Bean Validation 애너테이션 추가 고려

생성자 검증 외에 @Min(0)·@Max(5) 애너테이션을 rating 필드에 부여하면, 컨트롤러 레이어에서 DTO → Entity 매핑 시점에도 일관된 검증이 가능합니다.

-    private double rating;
+    @DecimalMin("0.0")
+    @DecimalMax("5.0")
+    private double rating;

프레젠테이션 계층과 도메인 계층 모두에서 제약조건을 보강하는 방향 검토 부탁드립니다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/ReviewTag.java (1)

15-33: equals‧hashCode 구현 누락

컬렉션(Set) 등에 담기는 경우가 많을 엔티티이므로 id 기준 equalshashCode를 재정의하는 것이 안전합니다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/Situation.java (1)

8-11: 이모지 하드코딩 시 국제화 고려

UI 측 다국어 지원을 위해 logo(이모지)와 name을 리소스 테이블로 분리하거나 MessageSource에 위임하는 방식을 검토해 볼 가치가 있습니다.

api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1)

11-17: 금액 타입은 int 대신 BigDecimal 고려

가격을 int(원 단위)로 저장하면 할인‧통화 변환 등 계산 시 overflow 및 정밀도 문제가 발생할 수 있습니다. JPA 컬럼을 DECIMAL(10,2)로 두고 DTO에도 BigDecimal을 사용하는 편이 안전합니다.

api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java (1)

15-20: 읽기 전용 트랜잭션 옵션 고려

조회 전용 메서드이므로 @Transactional(readOnly = true) 를 부여하면 성능 최적화와 의도 전달에 도움이 됩니다.

 @Service
 @RequiredArgsConstructor
 public class MenuService {

     private final MenuRepository menuRepository;

+    @Transactional(readOnly = true)
     public List<RepresentativeMenuResponse> findByRestaurantId(String restaurantId) {
api-user/src/main/java/com/wellmeet/restaurant/menu/repository/MenuRepository.java (1)

11-11: 대량 데이터 대응을 위한 페이징 고려

List<Menu> findByRestaurantId(String restaurantId) 는 전체 메뉴를 한 번에 반환하므로, 메뉴 수가 많은 레스토랑에서 메모리 사용이 급증할 수 있습니다. Page<Menu> 또는 Slice<Menu> 반환형으로의 확장을 고려해 보세요.

api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java (1)

15-17: 읽기 전용 트랜잭션 어노테이션을 추가하는 것을 권장합니다.

데이터베이스 읽기 성능 최적화를 위해 @Transactional(readOnly = true) 어노테이션을 추가해보세요.

+@Transactional(readOnly = true)
 public List<AvailableDate> findAvailableDates(String restaurantId) {
     return availableDateRepository.findAllByRestaurantId(restaurantId);
 }

필요한 import도 추가해야 합니다:

+import org.springframework.transaction.annotation.Transactional;
api-user/src/main/java/com/wellmeet/restaurant/availabledate/domain/AvailableDate.java (1)

22-22: 날짜-시간-레스토랑 조합의 유일성 제약조건을 고려해보세요.

동일한 레스토랑에서 같은 날짜와 시간에 중복된 예약 슬롯이 생성되는 것을 방지하기 위해 유니크 제약조건 추가를 검토해보세요.

+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;

+@Table(uniqueConstraints = {
+    @UniqueConstraint(columnNames = {"available_date", "available_time", "restaurant_id"})
+})
 @Getter
 @Entity
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
 public class AvailableDate {
api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1)

80-90: 가용일자 조회 메서드 구현이 올바르지만 성능 최적화 여지가 있습니다.

메서드 로직은 올바르게 구현되었지만, 레스토랑 존재 확인과 가용일자 조회를 위해 두 번의 데이터베이스 호출이 발생합니다.

성능을 최적화하려면 다음과 같이 리팩터링할 수 있습니다:

 @Transactional(readOnly = true)
 public List<AvailableDateResponse> getRestaurantAvailableDate(String id) {
-    if (!restaurantRepository.existsById(id)) {
-        throw new WellMeetException(ErrorCode.RESTAURANT_NOT_FOUND);
-    }
     List<AvailableDate> availableDates = availableDateService.findAvailableDates(id);
+    if (availableDates.isEmpty() && !restaurantRepository.existsById(id)) {
+        throw new WellMeetException(ErrorCode.RESTAURANT_NOT_FOUND);
+    }
     return availableDates
             .stream()
             .map(AvailableDateResponse::new)
             .toList();
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 450c496 and f93b93e.

📒 Files selected for processing (35)
  • api-owner/build.gradle (1 hunks)
  • api-owner/src/main/java/com/wellmeet/apiowner/ApiOwnerApplication.java (1 hunks)
  • api-user/build.gradle (1 hunks)
  • api-user/src/main/java/com/wellmeet/ApiUserApplication.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/ReservationController.java (2 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (2 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/repository/ReservationRepository.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java (2 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (4 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/availabledate/domain/AvailableDate.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/availabledate/repository/AvailableDateRepository.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/AvailableDateResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/menu/domain/Menu.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/menu/repository/MenuRepository.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/ReviewService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/domain/Review.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/domain/ReviewTag.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/domain/Situation.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/domain/Tag.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/repository/ReviewRepository.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/ApiUserApplicationTests.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/BaseControllerTest.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/BaseRepositoryTest.java (0 hunks)
  • api-user/src/test/java/com/wellmeet/WellMeetBackendApplicationTests.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/restaurant/review/domain/ReviewTest.java (1 hunks)
  • build.gradle (1 hunks)
  • common/build.gradle (1 hunks)
  • domain/build.gradle (1 hunks)
  • settings.gradle (1 hunks)
💤 Files with no reviewable changes (1)
  • api-user/src/test/java/com/wellmeet/BaseRepositoryTest.java
🧰 Additional context used
🧠 Learnings (25)
📓 Common learnings
Learnt from: unifolio0
PR: Team-soft-macaron/WellMeet-Backend#14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at `com.wellmeet.restaurant.domain.Restaurant` after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.
api-user/src/main/java/com/wellmeet/restaurant/review/domain/ReviewTag.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/Tag.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/Review.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/Situation.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/menu/domain/Menu.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/test/java/com/wellmeet/restaurant/review/domain/ReviewTest.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

api-user/src/main/java/com/wellmeet/restaurant/menu/repository/MenuRepository.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/test/java/com/wellmeet/BaseControllerTest.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/review/ReviewService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/reservation/repository/ReservationRepository.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/ApiUserApplication.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/availabledate/repository/AvailableDateRepository.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/availabledate/domain/AvailableDate.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/review/repository/ReviewRepository.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/reservation/ReservationController.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

🧬 Code Graph Analysis (15)
api-user/src/main/java/com/wellmeet/restaurant/review/domain/Review.java (1)
src/main/java/com/wellmeet/restaurant/model/review/domain/Review.java (1)
  • Review (23-65)
api-user/src/main/java/com/wellmeet/restaurant/review/domain/Situation.java (2)
src/main/java/com/wellmeet/restaurant/model/review/domain/Review.java (1)
  • Review (23-65)
src/main/java/com/wellmeet/restaurant/model/review/domain/Situation.java (2)
  • Situation (5-20)
  • Situation (16-19)
api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (2)
src/main/java/com/wellmeet/restaurant/model/review/domain/Review.java (1)
  • Review (23-65)
src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (2)
  • RepresentativeReviewResponse (7-20)
  • RepresentativeReviewResponse (15-19)
common/build.gradle (1)
src/main/java/com/wellmeet/config/JpaAuditingConfig.java (1)
  • JpaAuditingConfig (6-10)
api-user/src/main/java/com/wellmeet/restaurant/menu/repository/MenuRepository.java (3)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (2)
  • MenuRepository (8-12)
  • findByRestaurantId (11-11)
src/main/java/com/wellmeet/restaurant/model/menu/domain/Menu.java (2)
  • Menu (18-44)
  • Menu (38-43)
src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1)
  • RepresentativeMenuResponse (7-18)
api-user/src/main/java/com/wellmeet/ApiUserApplication.java (2)
src/main/java/com/wellmeet/WellMeetBackendApplication.java (2)
  • WellMeetBackendApplication (6-12)
  • main (9-11)
src/test/java/com/wellmeet/WellMeetBackendApplicationTests.java (2)
  • WellMeetBackendApplicationTests (6-12)
  • contextLoads (9-11)
api-user/src/main/java/com/wellmeet/restaurant/availabledate/repository/AvailableDateRepository.java (5)
src/main/java/com/wellmeet/restaurant/model/review/repository/ReviewRepository.java (1)
  • ReviewRepository (8-12)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (2)
  • MenuRepository (8-12)
  • findByRestaurantId (11-11)
src/main/java/com/wellmeet/member/repository/MemberRestaurantRepository.java (1)
  • MemberRestaurantRepository (11-19)
src/main/java/com/wellmeet/restaurant/repository/RestaurantRepository.java (1)
  • RestaurantRepository (11-21)
src/main/java/com/wellmeet/member/repository/MemberRepository.java (1)
  • MemberRepository (7-9)
api-user/src/test/java/com/wellmeet/ApiUserApplicationTests.java (3)
api-user/src/test/java/com/wellmeet/WellMeetBackendApplicationTests.java (1)
  • SpringBootTest (6-12)
src/test/java/com/wellmeet/WellMeetBackendApplicationTests.java (2)
  • WellMeetBackendApplicationTests (6-12)
  • contextLoads (9-11)
src/main/java/com/wellmeet/WellMeetBackendApplication.java (2)
  • WellMeetBackendApplication (6-12)
  • main (9-11)
api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (4)
src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (2)
  • RepresentativeMenuResponse (7-18)
  • RepresentativeMenuResponse (14-17)
src/main/java/com/wellmeet/restaurant/model/menu/domain/Menu.java (2)
  • Menu (18-44)
  • Menu (38-43)
src/main/java/com/wellmeet/restaurant/model/menu/service/MenuService.java (2)
  • MenuService (9-21)
  • findByRestaurantId (15-20)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (1)
  • MenuRepository (8-12)
api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (5)
src/main/java/com/wellmeet/restaurant/model/review/domain/Review.java (1)
  • Review (23-65)
src/main/java/com/wellmeet/restaurant/model/menu/service/MenuService.java (1)
  • MenuService (9-21)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (1)
  • MenuRepository (8-12)
src/main/java/com/wellmeet/restaurant/RestaurantService.java (1)
  • RestaurantService (22-70)
src/main/java/com/wellmeet/restaurant/model/review/repository/ReviewRepository.java (1)
  • ReviewRepository (8-12)
api-owner/src/main/java/com/wellmeet/apiowner/ApiOwnerApplication.java (2)
api-user/src/main/java/com/wellmeet/ApiUserApplication.java (1)
  • SpringBootApplication (6-12)
src/main/java/com/wellmeet/WellMeetBackendApplication.java (2)
  • WellMeetBackendApplication (6-12)
  • main (9-11)
api-user/src/main/java/com/wellmeet/restaurant/review/repository/ReviewRepository.java (1)
src/main/java/com/wellmeet/restaurant/model/review/repository/ReviewRepository.java (1)
  • ReviewRepository (8-12)
api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java (2)
api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1)
  • Service (26-91)
src/main/java/com/wellmeet/restaurant/RestaurantService.java (1)
  • RestaurantService (22-70)
api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (4)
src/main/java/com/wellmeet/reservation/ReservationService.java (5)
  • ReservationService (21-107)
  • updateReservation (64-86)
  • cancel (56-62)
  • reserve (29-47)
  • getReservation (96-106)
src/main/java/com/wellmeet/reservation/domain/Reservation.java (2)
  • Reservation (19-78)
  • cancel (59-61)
src/main/java/com/wellmeet/reservation/ReservationController.java (2)
  • ReservationController (22-70)
  • cancelReservation (62-69)
src/main/java/com/wellmeet/reservation/repository/ReservationRepository.java (1)
  • ReservationRepository (9-15)
api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (5)
api-user/src/main/java/com/wellmeet/member/service/MemberRestaurantService.java (1)
  • Service (13-39)
api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java (1)
  • Service (9-18)
api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java (1)
  • Service (9-21)
api-user/src/main/java/com/wellmeet/restaurant/review/ReviewService.java (1)
  • Service (10-30)
src/main/java/com/wellmeet/member/service/MemberRestaurantService.java (1)
  • MemberRestaurantService (13-39)
🔇 Additional comments (32)
api-user/src/main/java/com/wellmeet/restaurant/review/domain/Tag.java (1)

1-1: 패키지 리팩터링 확인 완료

패키지 명 변경이 일관성 있게 반영되었습니다. 기존 model 서브패키지를 제거한 결정이 다른 도메인 클래스들과도 정합성을 유지합니다. 추가적인 영향 범위(예: import 경로, JPA 엔티티 스캔 경로)도 함께 점검해 주세요.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/ReviewTag.java (1)

1-1: 패키지 이동 👍

model 하위 패키지 제거와 일관성 있는 네이밍으로 가독성이 좋아졌습니다.

api-user/src/main/java/com/wellmeet/restaurant/review/domain/Situation.java (1)

1-1: 패키지 경로 정리 확인

패키지 이동이 일관성 있게 반영되었습니다. 관련 import 수정 여부만 한 번 더 전역 검색으로 확인 부탁드립니다.

api-user/src/test/java/com/wellmeet/restaurant/review/domain/ReviewTest.java (1)

1-1: 패키지 경로 업데이트 확인

테스트 패키지 수정으로 컴파일 오류 위험이 제거되었습니다. 👍

api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1)

3-3: 패키지 변경 반영 완료

Menu import 경로가 새 구조와 일치합니다.

api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1)

10-10: 리뷰 서비스 패키지 경로 반영 확인

의존성 경로 수정이 잘 적용되었습니다.

api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (1)

3-3: 패키지 경로 변경 확인 완료

Review 도메인 클래스 이동에 따른 import 수정이 정확합니다. 추가 조치 필요 없어 보입니다.

settings.gradle (1)

3-6: 멀티모듈 include 추가 후 의존성 확인 필요

common, domain, api-owner, api-user 모듈을 include 하면서 빌드-순환(circular) 의존성이나 누락된 build.gradle 설정이 없는지 한번 더 점검해 주세요. CI 파이프라인에서 모듈 간 컴파일 및 테스트가 모두 통과되는지 확인 권장합니다.

api-user/src/test/java/com/wellmeet/WellMeetBackendApplicationTests.java (1)

9-11: 단순 들여쓰기 수정 – 문제 없음

기능 변화가 없으므로 그대로 승인합니다.

api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java (1)

1-4: 패키지 이동은 정상이나 Java 버전 호환성 확인 필요

stream().toList() 는 JDK 16 이상에서만 지원됩니다. 빌드 환경이 Java 17 이상임을 명확히 해두면 좋겠습니다.

api-user/src/main/java/com/wellmeet/restaurant/menu/repository/MenuRepository.java (1)

1-3: 패키지 변경 반영 OK

Repository 위치 이동이 잘 반영되었습니다. 추가 수정 사항 없습니다.

api-user/src/main/java/com/wellmeet/restaurant/review/repository/ReviewRepository.java (1)

1-3: 패키지 구조 개선이 적절합니다.

model 하위 패키지를 제거하여 더 간결한 패키지 구조로 변경되었습니다. 이는 코드베이스 전반의 일관성을 위한 좋은 리팩토링입니다.

api-user/src/main/java/com/wellmeet/reservation/repository/ReservationRepository.java (1)

16-16: 레스토랑별 예약 조회 기능 추가가 적절합니다.

새로운 findAllByRestaurantId 메서드는 특정 레스토랑의 모든 예약을 조회할 수 있게 해주며, SCRUM-64 요구사항인 레스토랑 예약 기능을 지원합니다. Spring Data JPA 네이밍 컨벤션을 올바르게 따르고 있습니다.

api-user/src/main/java/com/wellmeet/restaurant/review/ReviewService.java (1)

1-5: 패키지 구조 리팩토링이 일관성 있게 적용되었습니다.

ReviewService의 패키지 구조가 다른 클래스들과 일관성 있게 변경되어 더 명확한 패키지 계층을 제공합니다. 기능적 변경 없이 구조만 개선되었습니다.

api-user/src/test/java/com/wellmeet/BaseControllerTest.java (1)

5-7: 테스트 클래스의 import 구문이 올바르게 업데이트되었습니다.

새로운 패키지 구조에 맞게 MenuRepositoryReviewRepository의 import 구문이 정확히 변경되어 테스트가 정상적으로 작동할 수 있도록 보장합니다.

api-user/src/main/java/com/wellmeet/ApiUserApplication.java (1)

7-11: 멀티모듈 구조로의 전환이 적절하게 구현되었습니다.

WellMeetBackendApplication에서 ApiUserApplication으로 클래스명을 변경하고 SpringApplication.run() 호출을 업데이트한 것은 사용자 API를 별도 모듈로 분리하는 아키텍처 개선을 올바르게 반영합니다.

api-owner/build.gradle (1)

1-14: 멀티모듈 구조의 api-owner 빌드 설정이 적절합니다.

Spring Boot 플러그인과 필요한 의존성들이 올바르게 구성되어 있습니다. 내부 모듈(common, domain)에 대한 의존성과 웹, JPA, 검증을 위한 스타터 의존성이 적절히 포함되어 있습니다.

api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (1)

10-12: 패키지 리팩토링에 따른 import 경로 수정이 올바릅니다.

Menu, Review, Situation 클래스들의 import 경로가 새로운 패키지 구조(com.wellmeet.restaurant.menu.domain, com.wellmeet.restaurant.review.domain)에 맞게 정확히 업데이트되었습니다.

api-user/src/test/java/com/wellmeet/ApiUserApplicationTests.java (1)

1-12: api-user 모듈의 통합 테스트 설정이 적절합니다.

@SpringBootTest 어노테이션을 사용한 기본적인 컨텍스트 로딩 테스트가 올바르게 구성되어 있습니다. 새로운 모듈의 설정이 정상적으로 작동하는지 확인하는 필수적인 테스트입니다.

api-owner/src/main/java/com/wellmeet/apiowner/ApiOwnerApplication.java (1)

1-11: api-owner 모듈의 Spring Boot 애플리케이션 진입점이 올바르게 구성되었습니다.

@SpringBootApplication 어노테이션과 main 메서드가 표준 Spring Boot 패턴에 따라 정확히 구현되어 있습니다. 패키지 구조도 멀티모듈 설정에 적합합니다.

api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java (1)

3-3: 새로운 가용 날짜 조회 기능을 위한 DTO import가 추가되었습니다.

AvailableDateResponse import가 올바르게 추가되어 레스토랑 예약 가능한 날짜 조회 기능을 지원합니다.

api-user/src/main/java/com/wellmeet/restaurant/availabledate/repository/AvailableDateRepository.java (1)

8-12: 리포지토리 구현이 적절합니다.

Spring Data JPA 명명 규칙을 올바르게 따르고 있으며, 다른 리포지토리 인터페이스들과 일관된 패턴을 사용하고 있습니다.

api-user/build.gradle (1)

1-37: 빌드 설정이 적절하게 구성되었습니다.

멀티모듈 구조와 JaCoCo 테스트 커버리지 설정이 잘 되어 있습니다. 환경 변수를 통한 조건부 리포트 생성도 좋은 접근입니다.

api-user/src/main/java/com/wellmeet/restaurant/dto/AvailableDateResponse.java (1)

9-22: DTO 구현이 적절합니다.

도메인 객체를 API 응답으로 변환하는 로직이 명확하고 올바르게 구현되었습니다. 필요한 필드들만 노출하여 적절한 캡슐화를 유지하고 있습니다.

api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (2)

7-8: 새로운 가용일자 기능을 위한 의존성 추가가 적절합니다.

AvailableDateService와 관련 DTO 임포트, 그리고 멀티모듈 구조에 맞는 패키지 경로 업데이트가 올바르게 수행되었습니다.

Also applies to: 12-12, 17-17, 20-20, 24-24, 35-35


37-37: 읽기 전용 트랜잭션 어노테이션 추가가 적절합니다.

조회 전용 메서드들에 @Transactional(readOnly = true) 어노테이션을 추가하여 성능 최적화와 의도를 명확히 했습니다.

Also applies to: 59-59, 69-69, 75-75, 80-80

api-user/src/main/java/com/wellmeet/reservation/ReservationController.java (1)

29-36: 예약 생성 엔드포인트 구현이 적절합니다.

REST 규칙에 맞는 POST 매핑과 적절한 HTTP 상태 코드(201 Created) 사용, 그리고 요청 검증이 올바르게 구현되었습니다.

build.gradle (2)

3-4: 멀티모듈 프로젝트를 위한 플러그인 설정이 적절합니다.

루트 프로젝트에서 플러그인 버전을 정의하고 apply false를 사용하여 서브프로젝트에서 선택적으로 적용할 수 있도록 한 것이 올바른 멀티모듈 설정입니다.


7-49: 멀티모듈 프로젝트 구성이 잘 설계되었습니다.

공통 설정의 중앙화, Java 21 툴체인 사용, Spring Boot BOM을 통한 의존성 버전 관리, 그리고 공통 테스트 의존성 포함 등이 Gradle 모범 사례를 잘 따르고 있습니다.

api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (3)

56-62: 예약 목록 조회 메서드 구현이 적절합니다.

읽기 전용 트랜잭션 어노테이션과 적절한 DTO 매핑을 사용한 깔끔한 구현입니다.


64-74: 예약 상세 조회 메서드가 잘 구현되었습니다.

적절한 권한 확인, 추가 데이터(평점, 선택 옵션) 조회, 그리고 포괄적인 응답 생성이 올바르게 구현되었습니다.


108-114: 예약 취소 메서드가 올바르게 구현되었습니다.

적절한 쓰기 트랜잭션, 권한 확인, 도메인 메서드 사용, 그리고 변경사항 저장이 올바르게 구현되어 도메인 주도 설계 원칙을 잘 따르고 있습니다.

Comment on lines 76 to 82
@Transactional(readOnly = true)
public List<ReservationResponse> getReservationsByRestaurant(String restaurantId, Long memberId) {
return reservationRepository.findAllByRestaurantId(restaurantId)
.stream()
.map(reservation -> getReservation(reservation.getId(), memberId))
.toList();
}
Copy link

@coderabbitai coderabbitai bot Jul 29, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

N+1 쿼리 문제가 발생할 수 있습니다.

각 예약에 대해 getReservation을 호출하면서 추가적인 데이터베이스 쿼리가 발생하여 성능 문제가 생길 수 있습니다.

성능을 개선하기 위해 배치 조회를 사용하는 것을 고려해보세요:

 @Transactional(readOnly = true)
 public List<ReservationResponse> getReservationsByRestaurant(String restaurantId, Long memberId) {
-    return reservationRepository.findAllByRestaurantId(restaurantId)
-            .stream()
-            .map(reservation -> getReservation(reservation.getId(), memberId))
-            .toList();
+    List<Reservation> reservations = reservationRepository.findAllByRestaurantId(restaurantId);
+    // 배치로 rating과 selected options를 조회하는 로직 추가 필요
+    return reservations.stream()
+            .map(reservation -> {
+                // 배치 조회된 데이터를 사용하여 ReservationResponse 생성
+            })
+            .toList();
 }

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

🤖 Prompt for AI Agents
In api-user/src/main/java/com/wellmeet/reservation/ReservationService.java
around lines 76 to 82, the current implementation calls getReservation for each
reservation individually, causing N+1 query issues and performance degradation.
To fix this, refactor the method to fetch all necessary reservation details in a
single batch query instead of calling getReservation repeatedly. This may
involve modifying the repository to support batch fetching and mapping the
results accordingly to avoid multiple database hits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

이것도 다음 pr에서 사장님용 모듈로 옮겨지며 리팩토링 될 예정입니다

Copy link

Choose a reason for hiding this comment

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

@unifolio0 네, 사장님용 모듈로 이전될 예정이라는 점 이해했습니다! 다음 PR에서 리팩토링하실 때 배치 조회 방식으로 개선하시면 됩니다. 현재 PR의 범위와 일정을 고려하면 합리적인 접근 방식이네요.


🧠 Learnings used
Learnt from: unifolio0
PR: Team-soft-macaron/WellMeet-Backend#23
File: api-user/src/main/java/com/wellmeet/reservation/ReservationController.java:53-59
Timestamp: 2025-07-31T08:28:13.009Z
Learning: In the WellMeet-Backend project, the `getReservationsByRestaurant` API endpoint in ReservationController is planned to be moved to the owner API module after the current PR is merged, so temporary path mapping conflicts with this endpoint can be accepted.

Learnt from: unifolio0
PR: Team-soft-macaron/WellMeet-Backend#14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at `com.wellmeet.restaurant.domain.Restaurant` after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Comment on lines 36 to 37
private int maxCapacity;
private boolean isAvailable;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

maxCapacity 필드에 유효성 검증을 추가하세요.

최대 수용 인원은 양수여야 하므로 유효성 검증 어노테이션을 추가하는 것을 권장합니다.

+import jakarta.validation.constraints.Positive;

-private int maxCapacity;
+@Positive
+private int maxCapacity;
📝 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
private int maxCapacity;
private boolean isAvailable;
// add this import alongside your other imports
import jakarta.validation.constraints.Positive;
@Positive
private int maxCapacity;
private boolean isAvailable;
🤖 Prompt for AI Agents
In
api-user/src/main/java/com/wellmeet/restaurant/availabledate/domain/AvailableDate.java
around lines 36 to 37, the maxCapacity field lacks validation to ensure it is
positive. Add a validation annotation such as @Positive or @Min(1) to the
maxCapacity field to enforce that its value must be a positive integer.

Comment on lines 43 to 49
public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
this.date = date;
this.time = time;
this.maxCapacity = maxCapacity;
this.isAvailable = true;
this.restaurant = restaurant;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

생성자에 매개변수 유효성 검증을 추가하세요.

null 값이나 잘못된 값으로 엔티티가 생성되는 것을 방지하기 위해 매개변수 검증을 추가하는 것을 권장합니다.

 public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
+    if (date == null || time == null || restaurant == null) {
+        throw new IllegalArgumentException("필수 매개변수는 null일 수 없습니다");
+    }
+    if (maxCapacity <= 0) {
+        throw new IllegalArgumentException("최대 수용 인원은 양수여야 합니다");
+    }
     this.date = date;
     this.time = time;
     this.maxCapacity = maxCapacity;
     this.isAvailable = true;
     this.restaurant = restaurant;
 }
📝 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
public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
this.date = date;
this.time = time;
this.maxCapacity = maxCapacity;
this.isAvailable = true;
this.restaurant = restaurant;
}
public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
if (date == null || time == null || restaurant == null) {
throw new IllegalArgumentException("필수 매개변수는 null일 수 없습니다");
}
if (maxCapacity <= 0) {
throw new IllegalArgumentException("최대 수용 인원은 양수여야 합니다");
}
this.date = date;
this.time = time;
this.maxCapacity = maxCapacity;
this.isAvailable = true;
this.restaurant = restaurant;
}
🤖 Prompt for AI Agents
In
api-user/src/main/java/com/wellmeet/restaurant/availabledate/domain/AvailableDate.java
around lines 43 to 49, the constructor lacks validation for its parameters. Add
checks to ensure none of the parameters are null and that maxCapacity is a
positive integer. Throw appropriate exceptions if any validation fails to
prevent creating an entity with invalid or null values.

Comment on lines 37 to 42
@GetMapping("/available/{id}")
public List<AvailableDateResponse> isRestaurantAvailable(
@PathVariable String id
) {
return restaurantService.getRestaurantAvailableDate(id);
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

메서드명이 기능과 일치하지 않습니다.

메서드명 isRestaurantAvailable은 boolean 반환을 암시하지만 실제로는 List<AvailableDateResponse>를 반환합니다. 기능에 맞게 getRestaurantAvailableDates로 변경하는 것이 좋겠습니다.

다음 스크립트로 RestaurantService.getRestaurantAvailableDate 메서드의 구현을 확인해주세요:

메서드명 개선을 위한 diff:

-    public List<AvailableDateResponse> isRestaurantAvailable(
+    public List<AvailableDateResponse> getRestaurantAvailableDates(
         @PathVariable String id
     ) {
         return restaurantService.getRestaurantAvailableDate(id);
     }

🏁 Script executed:

#!/bin/bash
# RestaurantService에서 getRestaurantAvailableDate 메서드 구현 확인
ast-grep --pattern 'public $_ getRestaurantAvailableDate($_) {
  $$$
}'

Length of output: 73


AST-grep로 메서드 정의를 찾지 못했으므로, ripgrep을 사용해 getRestaurantAvailableDate의 정의 위치를 다시 확인해 주세요.


🏁 Script executed:

#!/bin/bash
# 모든 Java 파일에서 getRestaurantAvailableDate 사용 및 정의 검색
rg -n "getRestaurantAvailableDate" --glob "*.java"

Length of output: 343


메서드명 일관성 유지: 반환 타입에 맞춰 복수형으로 수정

현재 isRestaurantAvailable 메서드는 List<AvailableDateResponse>를 반환하므로, boolean을 암시하는 is… 대신 get…Dates 형태로 복수형 네이밍을 권장합니다. 서비스 메서드명도 동일하게 복수형으로 맞추면 더 일관적입니다.

수정 대상:

  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java (37–42줄)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (81줄)

제안하는 diff:

--- a/api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java
+++ b/api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java
@@ -37,7 +37,7 @@ public class RestaurantController {
     @GetMapping("/available/{id}")
-    public List<AvailableDateResponse> isRestaurantAvailable(
+    public List<AvailableDateResponse> getRestaurantAvailableDates(
         @PathVariable String id
     ) {
-        return restaurantService.getRestaurantAvailableDate(id);
+        return restaurantService.getRestaurantAvailableDates(id);
     }
 }

--- a/api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java
+++ b/api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java
@@ -81,7 +81,7 @@ public class RestaurantService {
-    public List<AvailableDateResponse> getRestaurantAvailableDate(String id) {
+    public List<AvailableDateResponse> getRestaurantAvailableDates(String id) {
         // …기존 로직 유지
     }
📝 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("/available/{id}")
public List<AvailableDateResponse> isRestaurantAvailable(
@PathVariable String id
) {
return restaurantService.getRestaurantAvailableDate(id);
}
// api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java
@GetMapping("/available/{id}")
public List<AvailableDateResponse> getRestaurantAvailableDates(
@PathVariable String id
) {
return restaurantService.getRestaurantAvailableDates(id);
}
// api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java
public List<AvailableDateResponse> getRestaurantAvailableDates(String id) {
// …기존 로직 유지
}
🤖 Prompt for AI Agents
In api-user/src/main/java/com/wellmeet/restaurant/RestaurantController.java
lines 37 to 42, rename the method from isRestaurantAvailable to
getAvailableDates to reflect that it returns a list rather than a boolean. Also,
in api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java around
line 81, rename the corresponding service method from getRestaurantAvailableDate
to getAvailableDates to maintain naming consistency and clarity.

Comment on lines 1 to 5
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

common 모듈에 Spring Boot 의존성만 있고 플러그인이 없습니다

common 모듈이 실제로 Spring Bean을 포함하거나 실행 가능 JAR를 만들 필요가 없다면 org.springframework.boot 플러그인을 적용하지 않고, implementation 'org.springframework.boot:spring-boot-starter' 대신 모듈 간 공통 코드만 제공하는 java-library 역할로 두는 편이 가볍습니다.
반대로 Boot 기능이 꼭 필요하다면 plugins { id("org.springframework.boot") } 선언이 누락된 상태이므로 빌드 시 오류가 발생할 수 있습니다. 루트 build.gradle에서 subprojects { apply(plugin = "org.springframework.boot") } 식으로 일괄 적용하는 구조인지 확인 바랍니다.


아래 스크립트를 실행하여 루트 build.gradle 및 설정 파일에서 org.springframework.boot 플러그인 적용 여부를 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 루트 build.gradle에서 subprojects 블록 확인
rg -n "subprojects" -n build.gradle

# spring-boot 플러그인 직접 적용 여부 확인
rg -n "apply.*org.springframework.boot" -n .

# plugins 블록 내 spring-boot 플러그인 선언 확인
rg -n "plugins.*org.springframework.boot" -n .

Length of output: 148


common 모듈에 Spring Boot 플러그인 누락

현재 common/build.gradle에는 Spring Boot 의존성만 선언되어 있고, 플러그인 적용이 없어 빌드 시 다음과 같은 이슈가 발생할 수 있습니다.

  1. 공통 코드만 제공하는 라이브러리라면 불필요한 Spring Boot 스타터 의존성을 제거하고 java-library 플러그인으로 경량화
  2. Spring Boot 기능이 필요하다면 common/build.gradle에 플러그인 선언 추가 또는 루트 build.gradle에서 일괄 적용 확인

수정 제안:

  • common/build.gradle 수정 (라이브러리 전용)
    plugins {
        id 'java-library'
    }
    dependencies {
        // implementation 'org.springframework.boot:spring-boot-starter' 제거
        // 필요한 공통 의존성만 선언
    }
  • 또는 Spring Boot 실행/빈 기능이 필요하다면
    plugins {
        id 'org.springframework.boot' version '2.x.x'
        id 'io.spring.dependency-management' version '1.x.x'
    }
  • 루트 build.gradle에
    subprojects {
        apply plugin: 'org.springframework.boot'
        apply plugin: 'io.spring.dependency-management'
    }
    식으로 일괄 적용 여부도 함께 검토 바랍니다.
    위 중 한 가지 방향으로 설정을 정리해 주세요.
🤖 Prompt for AI Agents
In common/build.gradle lines 1 to 5, the Spring Boot plugin is missing while
Spring Boot starter dependencies are declared, causing build issues. To fix,
either remove the Spring Boot starter dependencies and apply the 'java-library'
plugin if this module is only a common library, or add the Spring Boot and
dependency management plugins to this build file or ensure they are applied in
the root build.gradle for consistent plugin application across subprojects.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
domain/src/test/java/com/wellmeet/DataBaseCleaner.java (1)

33-33: String.formatted() 사용은 안전하지만 일관성을 위해 개선 가능.

INFORMATION_SCHEMA에서 가져온 테이블 이름이므로 SQL 인젝션 위험은 없지만, 일관성을 위해 다른 쿼리와 동일한 방식의 문자열 연결을 사용하는 것을 고려해보세요.

- em.createNativeQuery("TRUNCATE TABLE %s".formatted(tableName)).executeUpdate();
+ em.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate();
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f93b93e and a2b64bb.

📒 Files selected for processing (60)
  • api-owner/src/main/java/com/wellmeet/ApiOwnerApplication.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/exception/ErrorCode.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/exception/GlobalExceptionHandler.java (2 hunks)
  • api-user/src/main/java/com/wellmeet/exception/WellMeetException.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/dto/FavoriteRestaurantResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/member/service/MemberRestaurantService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/member/service/MemberService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (3 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/dto/CreateReservationResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/dto/ReservationResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/dto/SummaryReservationResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (4 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/AvailableDateResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/NearbyRestaurantResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RestaurantResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/review/ReviewService.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/BaseControllerTest.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/BaseRepositoryTest.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java (1 hunks)
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (1 hunks)
  • domain/build.gradle (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/common/BaseEntity.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/config/JpaAuditingConfig.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/exception/DomainErrorCode.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/exception/WellMeetDomainException.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/domain/Member.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/domain/MemberRestaurant.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/repository/MemberRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/repository/MemberRestaurantRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/domain/Reservation.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/domain/ReservationStatus.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/domain/SelectedPremiumOption.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/ReservationRepository.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/SelectedPremiumOptionRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/domain/AvailableDate.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/repository/AvailableDateRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/domain/BoundingBox.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/domain/PremiumOption.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/domain/Restaurant.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/domain/Menu.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/repository/MenuRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/PremiumOptionRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/RestaurantRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/Review.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/ReviewTag.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/Situation.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/Tag.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/repository/ReviewRepository.java (1 hunks)
  • domain/src/test/java/com/wellmeet/BaseRepositoryTest.java (1 hunks)
  • domain/src/test/java/com/wellmeet/DataBaseCleaner.java (1 hunks)
  • domain/src/test/java/com/wellmeet/TestConfiguration.java (1 hunks)
  • domain/src/test/java/com/wellmeet/domain/restaurant/domain/BoundingBoxTest.java (2 hunks)
  • domain/src/test/java/com/wellmeet/domain/restaurant/repository/RestaurantRepositoryTest.java (1 hunks)
  • domain/src/test/java/com/wellmeet/domain/restaurant/review/domain/ReviewTest.java (2 hunks)
  • domain/src/test/resources/application.yml (1 hunks)
✅ Files skipped from review due to trivial changes (43)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RestaurantResponse.java
  • domain/src/main/java/com/wellmeet/domain/config/JpaAuditingConfig.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/ReviewTag.java
  • api-user/src/main/java/com/wellmeet/favorite/dto/FavoriteRestaurantResponse.java
  • domain/src/main/java/com/wellmeet/domain/common/BaseEntity.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/domain/PremiumOption.java
  • api-user/src/main/java/com/wellmeet/reservation/dto/SummaryReservationResponse.java
  • api-user/src/main/java/com/wellmeet/member/service/MemberService.java
  • domain/src/main/java/com/wellmeet/domain/member/repository/MemberRestaurantRepository.java
  • api-user/src/main/java/com/wellmeet/member/service/MemberRestaurantService.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/Situation.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/domain/Restaurant.java
  • api-user/src/main/java/com/wellmeet/reservation/dto/CreateReservationResponse.java
  • api-user/src/main/java/com/wellmeet/reservation/dto/ReservationResponse.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/NearbyRestaurantResponse.java
  • domain/src/test/resources/application.yml
  • domain/src/main/java/com/wellmeet/domain/member/repository/MemberRepository.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/repository/MenuRepository.java
  • domain/src/main/java/com/wellmeet/domain/member/domain/MemberRestaurant.java
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/SelectedPremiumOptionRepository.java
  • domain/src/main/java/com/wellmeet/domain/member/domain/Member.java
  • domain/src/main/java/com/wellmeet/domain/reservation/domain/SelectedPremiumOption.java
  • domain/src/test/java/com/wellmeet/TestConfiguration.java
  • domain/src/main/java/com/wellmeet/domain/reservation/domain/Reservation.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/domain/Menu.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/RestaurantRepository.java
  • api-user/src/main/java/com/wellmeet/restaurant/availabledate/AvailableDateService.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/repository/ReviewRepository.java
  • api-user/src/test/java/com/wellmeet/BaseControllerTest.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/Tag.java
  • domain/src/test/java/com/wellmeet/domain/restaurant/repository/RestaurantRepositoryTest.java
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/PremiumOptionRepository.java
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java
  • api-owner/src/main/java/com/wellmeet/ApiOwnerApplication.java
  • api-user/src/main/java/com/wellmeet/restaurant/review/ReviewService.java
  • domain/src/test/java/com/wellmeet/domain/restaurant/review/domain/ReviewTest.java
  • domain/src/main/java/com/wellmeet/domain/reservation/domain/ReservationStatus.java
  • domain/src/test/java/com/wellmeet/BaseRepositoryTest.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/domain/Review.java
  • domain/src/test/java/com/wellmeet/domain/restaurant/domain/BoundingBoxTest.java
  • domain/src/main/java/com/wellmeet/domain/exception/DomainErrorCode.java
  • api-user/src/main/java/com/wellmeet/exception/ErrorCode.java
🚧 Files skipped from review as they are similar to previous changes (9)
  • api-user/src/test/java/com/wellmeet/BaseRepositoryTest.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java
  • api-user/src/main/java/com/wellmeet/restaurant/menu/MenuService.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java
  • api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java
  • domain/build.gradle
  • api-user/src/main/java/com/wellmeet/restaurant/dto/AvailableDateResponse.java
  • api-user/src/main/java/com/wellmeet/reservation/ReservationService.java
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: unifolio0
PR: Team-soft-macaron/WellMeet-Backend#14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at `com.wellmeet.restaurant.domain.Restaurant` after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.
domain/src/main/java/com/wellmeet/domain/reservation/repository/ReservationRepository.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/restaurant/domain/BoundingBox.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/repository/AvailableDateRepository.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/domain/AvailableDate.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

🧬 Code Graph Analysis (4)
domain/src/main/java/com/wellmeet/domain/reservation/repository/ReservationRepository.java (6)
src/main/java/com/wellmeet/restaurant/model/review/repository/ReviewRepository.java (1)
  • ReviewRepository (8-12)
src/main/java/com/wellmeet/reservation/repository/ReservationRepository.java (1)
  • ReservationRepository (9-15)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (1)
  • MenuRepository (8-12)
src/main/java/com/wellmeet/reservation/domain/Reservation.java (1)
  • Reservation (19-78)
src/main/java/com/wellmeet/reservation/ReservationService.java (1)
  • ReservationService (21-107)
src/main/java/com/wellmeet/restaurant/domain/Restaurant.java (1)
  • Restaurant (11-37)
api-user/src/main/java/com/wellmeet/exception/GlobalExceptionHandler.java (3)
src/main/java/com/wellmeet/exception/WellMeetException.java (2)
  • WellMeetException (6-15)
  • WellMeetException (11-14)
src/main/java/com/wellmeet/exception/GlobalExceptionHandler.java (4)
  • handleOAuthClientException (11-14)
  • GlobalExceptionHandler (8-30)
  • handleException (16-19)
  • toResponse (21-23)
src/main/java/com/wellmeet/exception/ErrorCode.java (1)
  • ErrorCode (6-29)
domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/repository/AvailableDateRepository.java (9)
src/main/java/com/wellmeet/restaurant/model/review/repository/ReviewRepository.java (1)
  • ReviewRepository (8-12)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (2)
  • MenuRepository (8-12)
  • findByRestaurantId (11-11)
src/main/java/com/wellmeet/restaurant/repository/PremiumOptionRepository.java (1)
  • PremiumOptionRepository (8-11)
src/main/java/com/wellmeet/member/repository/MemberRestaurantRepository.java (1)
  • MemberRestaurantRepository (11-19)
src/main/java/com/wellmeet/reservation/repository/ReservationRepository.java (1)
  • ReservationRepository (9-15)
src/main/java/com/wellmeet/restaurant/repository/RestaurantRepository.java (1)
  • RestaurantRepository (11-21)
src/main/java/com/wellmeet/reservation/repository/SelectedPremiumOptionRepository.java (1)
  • SelectedPremiumOptionRepository (8-14)
src/main/java/com/wellmeet/member/repository/MemberRepository.java (1)
  • MemberRepository (7-9)
src/test/java/com/wellmeet/BaseRepositoryTest.java (1)
  • BaseRepositoryTest (10-17)
domain/src/test/java/com/wellmeet/DataBaseCleaner.java (3)
src/test/java/com/wellmeet/BaseRepositoryTest.java (1)
  • BaseRepositoryTest (10-17)
src/test/java/com/wellmeet/WellMeetBackendApplicationTests.java (2)
  • WellMeetBackendApplicationTests (6-12)
  • contextLoads (9-11)
src/test/java/com/wellmeet/BaseControllerTest.java (1)
  • BaseControllerTest (19-55)
🔇 Additional comments (14)
domain/src/main/java/com/wellmeet/domain/reservation/repository/ReservationRepository.java (3)

1-1: 패키지 구조 변경이 적절합니다.

멀티모듈 아키텍처로의 전환에 따른 패키지 구조 변경이 도메인과 API 계층을 명확히 분리하여 관심사의 분리 원칙을 잘 따르고 있습니다.


3-3: 임포트 문 업데이트가 올바릅니다.

새로운 도메인 패키지 구조에 맞게 Reservation 엔티티의 임포트 경로가 정확히 업데이트되었습니다.


16-16: 새로운 레포지토리 메서드가 잘 구현되었습니다.

findAllByRestaurantId 메서드는 Spring Data JPA의 명명 규칙을 올바르게 따르고 있으며, 매개변수 타입(String)이 Restaurant 엔티티의 id 필드 타입과 일치합니다. 식당별 예약 조회 기능을 지원하는 필수적인 메서드입니다.

domain/src/test/java/com/wellmeet/DataBaseCleaner.java (3)

1-10: 임포트와 패키지 구조가 적절합니다.

JUnit 5 확장과 Spring 테스트 컨텍스트 관련 임포트가 올바르게 구성되어 있습니다.


11-17: BeforeEachCallback 구현이 올바르게 되어 있습니다.

JUnit 5 확장 인터페이스를 올바르게 구현하고 Spring 애플리케이션 컨텍스트를 가져와서 cleanup 메서드에 전달하는 로직이 정확합니다.


19-28: 트랜잭션 내에서 데이터베이스 정리가 적절히 수행됩니다.

EntityManager와 TransactionTemplate을 사용하여 트랜잭션 컨텍스트 내에서 데이터베이스 정리를 수행하는 것이 올바른 접근법입니다. em.clear()로 영속성 컨텍스트를 정리하는 것도 적절합니다.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/repository/AvailableDateRepository.java (1)

1-12: 깔끔한 리포지토리 구현입니다!

Spring Data JPA 패턴을 올바르게 따르고 있으며, 다른 리포지토리들(ReviewRepository, MenuRepository)과 일관된 구조를 유지하고 있습니다. findAllByRestaurantId 메서드명은 Spring Data JPA 컨벤션을 잘 따르고 있습니다.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/domain/AvailableDate.java (1)

3-3: Restaurant import 경로 확인 불필요

fd 결과를 확인한 결과, domain/src/main/java/com/wellmeet/domain/restaurant/domain/Restaurant.java에 클래스가 존재하므로
현재의 import com.wellmeet.domain.restaurant.domain.Restaurant; 경로는 올바릅니다.
해당 부분은 수정할 필요가 없습니다.

Likely an incorrect or invalid review comment.

domain/src/main/java/com/wellmeet/domain/exception/WellMeetDomainException.java (1)

5-14: 깔끔한 도메인 예외 클래스 구현입니다!

도메인 계층의 예외 처리를 위한 기본 클래스가 잘 설계되었습니다. DomainErrorCode와의 조합을 통해 일관된 예외 처리가 가능하고, RuntimeException을 상속하여 도메인 예외의 특성을 잘 반영했습니다.

domain/src/main/java/com/wellmeet/domain/restaurant/domain/BoundingBox.java (2)

1-4: 패키지 구조 리팩토링이 잘 적용되었습니다.

도메인 모듈의 새로운 패키지 구조 com.wellmeet.domain.restaurant.domain로 올바르게 이동되었고, 새로운 도메인 예외 클래스들을 import하여 일관된 예외 처리 구조를 유지하고 있습니다.


24-27: INVALID_LATITUDE 및 INVALID_LONGITUDE 상수 정의 확인 완료

DomainErrorCode enum(domain/src/main/java/com/wellmeet/domain/exception/DomainErrorCode.java)에

  • INVALID_LATITUDE(400, "유효하지 않은 위도입니다.")
  • INVALID_LONGITUDE(400, "유효하지 않은 경도입니다.")
    가 정상적으로 정의되어 있어, BoundingBox의 예외 처리 로직이 올바르게 동작합니다.

변경사항을 승인합니다.

api-user/src/main/java/com/wellmeet/exception/GlobalExceptionHandler.java (2)

12-12: 예외 처리 메서드 호출이 올바르게 업데이트되었습니다.

WellMeetException의 새로운 getStatusCode() 메서드를 사용하도록 변경되어 정수 상태 코드 기반 예외 처리 구조와 일치합니다.


21-21: ErrorCode 사용법이 일관되게 업데이트되었습니다.

ErrorCode.getStatusCode() 호출로 변경되어 새로운 정수 상태 코드 패턴을 따르고 있습니다.

api-user/src/main/java/com/wellmeet/exception/WellMeetException.java (1)

8-8: 필드 타입 변경이 적절합니다.

HttpStatus status에서 int statusCode로의 변경이 새로운 정수 기반 상태 코드 구조와 일치합니다. Lombok의 @Getter 어노테이션이 자동으로 getStatusCode() 메서드를 생성해줍니다.

Comment on lines +24 to 27
private ResponseEntity<ErrorResponse> toResponse(int statusCode, String message) {
ErrorResponse errorResponse = new ErrorResponse(message);
return ResponseEntity.status(httpStatus)
return ResponseEntity.status(statusCode)
.body(errorResponse);
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

메서드 시그니처 변경이 적절합니다.

HttpStatus에서 int statusCode로의 변경이 올바르게 적용되었고, ResponseEntity.status(statusCode) 호출도 정수 매개변수를 올바르게 사용하고 있습니다.

WellMeetExceptionErrorCode 클래스가 getStatusCode() 메서드를 제공하는지 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# Description: WellMeetException과 ErrorCode 클래스에서 getStatusCode 메서드 확인

echo "=== WellMeetException getStatusCode 메서드 확인 ==="
ast-grep --pattern 'class WellMeetException {
  $$$
  getStatusCode() {
    $$$
  }
  $$$
}'

echo "=== ErrorCode getStatusCode 메서드 확인 ==="
ast-grep --pattern 'enum ErrorCode {
  $$$
  getStatusCode() {
    $$$
  }
  $$$
}'

Length of output: 370


WellMeetException 및 ErrorCode에 getStatusCode() 메서드 추가 필요

GlobalExceptionHandler에서 toResponse(ex.getStatusCode(), ex.getMessage())를 호출하고 있지만, 두 클래스에서 해당 메서드가 구현되어 있지 않아 컴파일 오류가 발생합니다.

다음 파일들에 getStatusCode() 메서드를 추가하거나, HttpStatus 반환 시 .value() 호출 로직을 구현해주세요:

  • api-user/src/main/java/com/wellmeet/exception/WellMeetException.java
  • api-user/src/main/java/com/wellmeet/exception/ErrorCode.java

수정 후 빌드 및 예외 처리 로직을 재검증해주시기 바랍니다.

🤖 Prompt for AI Agents
In api-user/src/main/java/com/wellmeet/exception/GlobalExceptionHandler.java
around lines 24 to 27, the method toResponse calls ex.getStatusCode() but the
getStatusCode() method is missing in WellMeetException and ErrorCode classes. To
fix this, add a getStatusCode() method in both WellMeetException.java and
ErrorCode.java that returns the appropriate HTTP status code as an int, either
by returning an int field or by calling .value() on an HttpStatus object. After
adding these methods, rebuild the project and verify the exception handling
works correctly.

public WellMeetException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.status = errorCode.getStatus();
this.statusCode = errorCode.getStatusCode();
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

생성자 로직이 새로운 구조에 맞게 업데이트되었습니다.

ErrorCode.getStatus() 대신 ErrorCode.getStatusCode()를 사용하도록 변경되어 일관된 예외 처리 패턴을 유지하고 있습니다.

ErrorCode enum에 getStatusCode() 메서드가 구현되어 있는지 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# Description: ErrorCode enum에서 getStatusCode 메서드 구현 확인

echo "=== ErrorCode enum 구조 확인 ==="
ast-grep --pattern 'enum ErrorCode {
  $$$
}'

echo "=== ErrorCode에서 status 관련 필드와 메서드 확인 ==="
rg -A 10 -B 5 "getStatusCode|statusCode" --type java api-user/src/main/java/com/wellmeet/exception/ErrorCode.java

Length of output: 707


ErrorCode enum에 getStatusCode() 메서드 추가 필요

WellMeetException 생성자에서 errorCode.getStatusCode()를 호출하도록 변경되었으나, 현재 ErrorCode enum에는 해당 접근자가 구현되어 있지 않아 컴파일 에러가 발생합니다.

코드 수정 제안:

  • 파일: api-user/src/main/java/com/wellmeet/exception/ErrorCode.java
  • 아래와 같이 public getter 메서드를 추가해주세요.
 enum ErrorCode {
     MEMBER_RESTAURANT_NOT_FOUND(404, "즐겨찾기 하지 않은 레스토랑입니다."),
     PREMIUM_OPTION_NOT_FOUND(404, "해당 프리미엄 옵션을 찾을 수 없습니다."),
     UNAUTHORIZED_RESERVATION_ACCESS(400, "예약에 대한 권한이 없습니다."),
     ;

     private final int statusCode;
     private final String message;

     ErrorCode(int statusCode, String message) {
         this.statusCode = statusCode;
         this.message = message;
     }

+    /** HTTP 상태 코드를 반환합니다. */
+    public int getStatusCode() {
+        return this.statusCode;
+    }
 }

위 변경으로 WellMeetException의 호출부가 정상 동작합니다.

🤖 Prompt for AI Agents
In api-user/src/main/java/com/wellmeet/exception/ErrorCode.java, add a public
getter method named getStatusCode() to the ErrorCode enum to return the
statusCode field. This will resolve the compilation error caused by calling
errorCode.getStatusCode() in WellMeetException.java by providing the necessary
accessor method.

Comment on lines 22 to 41
public class AvailableDate {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
@Column(name = "available_date")
private LocalDate date;

@NotNull
@Column(name = "available_time")
private LocalTime time;

private int maxCapacity;
private boolean isAvailable;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

엔티티 구조 개선을 위한 제안사항들

전반적으로 좋은 구조이지만 몇 가지 개선사항을 제안합니다:

다음 변경사항을 적용해주세요:

+@Table(name = "available_dates")
 @Getter
 @Entity
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
 public class AvailableDate {
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
 
     @NotNull
     @Column(name = "available_date")
     private LocalDate date;
 
     @NotNull
     @Column(name = "available_time")
     private LocalTime time;
 
-    private int maxCapacity;
-    private boolean isAvailable;
+    @Min(1)
+    @Column(name = "max_capacity")
+    private int maxCapacity;
+    
+    @Column(name = "is_available")
+    private boolean isAvailable;

추가로 다음 import도 필요합니다:

+import jakarta.persistence.Table;
+import jakarta.validation.constraints.Min;
📝 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
public class AvailableDate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Column(name = "available_date")
private LocalDate date;
@NotNull
@Column(name = "available_time")
private LocalTime time;
private int maxCapacity;
private boolean isAvailable;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
// add these at the top with the other imports
import jakarta.persistence.Table;
import jakarta.validation.constraints.Min;
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "available_dates")
public class AvailableDate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Column(name = "available_date")
private LocalDate date;
@NotNull
@Column(name = "available_time")
private LocalTime time;
@Min(1)
@Column(name = "max_capacity")
private int maxCapacity;
@Column(name = "is_available")
private boolean isAvailable;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
// ... rest of the class ...
}
🤖 Prompt for AI Agents
In
domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/domain/AvailableDate.java
between lines 22 and 41, improve the entity structure by applying the suggested
changes such as adding missing annotations or modifying field declarations as
per best practices. Also, ensure to add the necessary import statements that
support these changes to maintain proper compilation and functionality.

Comment on lines 43 to 49
public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
this.date = date;
this.time = time;
this.maxCapacity = maxCapacity;
this.isAvailable = true;
this.restaurant = restaurant;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

생성자에 매개변수 검증 추가 권장

현재 생성자에서 입력값 검증이 없어서 잘못된 데이터로 엔티티가 생성될 수 있습니다.

다음과 같이 검증 로직을 추가해주세요:

 public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
+    if (date == null || time == null || restaurant == null) {
+        throw new IllegalArgumentException("필수 필드는 null일 수 없습니다");
+    }
+    if (maxCapacity <= 0) {
+        throw new IllegalArgumentException("최대 수용 인원은 1명 이상이어야 합니다");
+    }
     this.date = date;
     this.time = time;
     this.maxCapacity = maxCapacity;
     this.isAvailable = true;
     this.restaurant = restaurant;
 }
📝 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
public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
this.date = date;
this.time = time;
this.maxCapacity = maxCapacity;
this.isAvailable = true;
this.restaurant = restaurant;
}
public AvailableDate(LocalDate date, LocalTime time, int maxCapacity, Restaurant restaurant) {
if (date == null || time == null || restaurant == null) {
throw new IllegalArgumentException("필수 필드는 null일 수 없습니다");
}
if (maxCapacity <= 0) {
throw new IllegalArgumentException("최대 수용 인원은 1명 이상이어야 합니다");
}
this.date = date;
this.time = time;
this.maxCapacity = maxCapacity;
this.isAvailable = true;
this.restaurant = restaurant;
}
🤖 Prompt for AI Agents
In
domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/domain/AvailableDate.java
around lines 43 to 49, the constructor lacks validation for its parameters,
which may allow invalid data to create the entity. Add validation checks to
ensure date and time are not null, maxCapacity is positive, and restaurant is
not null. Throw appropriate exceptions if any validation fails to prevent
invalid entity creation.

Comment on lines +30 to +36
private void truncateTables(EntityManager em) {
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 0").executeUpdate();
for (String tableName : findTableNames(em)) {
em.createNativeQuery("TRUNCATE TABLE %s".formatted(tableName)).executeUpdate();
}
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 1").executeUpdate();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

MySQL 전용 구문 사용으로 인한 데이터베이스 이식성 제한.

현재 구현은 MySQL의 FOREIGN_KEY_CHECKS 구문을 사용하여 다른 데이터베이스(PostgreSQL, H2 등)와 호환되지 않습니다. 또한 데이터베이스 작업에 대한 예외 처리가 없습니다.

데이터베이스 독립적인 접근 방식을 고려해보세요:

 private void truncateTables(EntityManager em) {
-    em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 0").executeUpdate();
-    for (String tableName : findTableNames(em)) {
-        em.createNativeQuery("TRUNCATE TABLE %s".formatted(tableName)).executeUpdate();
-    }
-    em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 1").executeUpdate();
+    try {
+        // Try MySQL syntax first
+        em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 0").executeUpdate();
+        for (String tableName : findTableNames(em)) {
+            em.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate();
+        }
+        em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 1").executeUpdate();
+    } catch (Exception e) {
+        // Fallback for other databases
+        for (String tableName : findTableNames(em)) {
+            em.createNativeQuery("DELETE FROM " + tableName).executeUpdate();
+        }
+    }
 }
📝 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
private void truncateTables(EntityManager em) {
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 0").executeUpdate();
for (String tableName : findTableNames(em)) {
em.createNativeQuery("TRUNCATE TABLE %s".formatted(tableName)).executeUpdate();
}
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 1").executeUpdate();
}
private void truncateTables(EntityManager em) {
try {
// Try MySQL syntax first
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 0").executeUpdate();
for (String tableName : findTableNames(em)) {
em.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate();
}
em.createNativeQuery("SET FOREIGN_KEY_CHECKS = 1").executeUpdate();
} catch (Exception e) {
// Fallback for other databases
for (String tableName : findTableNames(em)) {
em.createNativeQuery("DELETE FROM " + tableName).executeUpdate();
}
}
}
🤖 Prompt for AI Agents
In domain/src/test/java/com/wellmeet/DataBaseCleaner.java around lines 30 to 36,
the method uses MySQL-specific syntax "SET FOREIGN_KEY_CHECKS" which limits
compatibility with other databases like PostgreSQL or H2 and lacks exception
handling. Refactor the method to use a database-independent approach for
disabling and enabling foreign key constraints, such as leveraging JPA or
Hibernate APIs if available, and add proper try-catch blocks to handle
exceptions during the truncate operations to ensure robustness across different
database systems.

Comment on lines +38 to +49
@SuppressWarnings("unchecked")
private List<String> findTableNames(EntityManager em) {
String tableNameSelectQuery = """
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND TABLE_TYPE = 'BASE TABLE'
""";

return em.createNativeQuery(tableNameSelectQuery)
.getResultList();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

스키마 이름이 하드코딩되어 환경별 유연성이 부족합니다.

'test' 스키마가 하드코딩되어 있어 다른 테스트 환경에서 문제가 될 수 있습니다. @SuppressWarnings("unchecked") 어노테이션은 적절하지만 더 구체적으로 지정할 수 있습니다.

스키마 이름을 설정 가능하게 만들고 경고를 더 구체적으로 지정하세요:

-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     private List<String> findTableNames(EntityManager em) {
+        // Consider making schema name configurable via application properties
         String tableNameSelectQuery = """
                 SELECT TABLE_NAME
                 FROM INFORMATION_SCHEMA.TABLES
-                WHERE TABLE_SCHEMA = 'test'
+                WHERE TABLE_SCHEMA = DATABASE()
                 AND TABLE_TYPE = 'BASE TABLE'
                 """;

또는 application.yml에서 스키마 이름을 주입받도록 리팩토링을 고려해보세요.

📝 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
@SuppressWarnings("unchecked")
private List<String> findTableNames(EntityManager em) {
String tableNameSelectQuery = """
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND TABLE_TYPE = 'BASE TABLE'
""";
return em.createNativeQuery(tableNameSelectQuery)
.getResultList();
}
@SuppressWarnings({"unchecked", "rawtypes"})
private List<String> findTableNames(EntityManager em) {
// Consider making schema name configurable via application properties
String tableNameSelectQuery = """
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_TYPE = 'BASE TABLE'
""";
return em.createNativeQuery(tableNameSelectQuery)
.getResultList();
}
🤖 Prompt for AI Agents
In domain/src/test/java/com/wellmeet/DataBaseCleaner.java around lines 38 to 49,
the schema name 'test' is hardcoded in the SQL query, reducing flexibility
across environments. Refactor the method to accept the schema name as a
parameter or inject it from application.yml configuration. Also, replace the
generic @SuppressWarnings("unchecked") with a more specific warning suppression
if possible to improve code clarity.

@unifolio0 unifolio0 changed the title SCRUM-64 사용자는 원하는 식당을 예약할 수 있다. SCRUM-64 예약 기능 및 종합 리팩토링 Jul 31, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (2)
domain/src/main/java/com/wellmeet/domain/restaurant/entity/PremiumOption.java (1)

33-34: 가격 필드에 비즈니스 규칙 검증이 필요합니다.

가격이 음수가 될 수 없도록 검증을 추가하고, description 필드의 길이 제한을 고려해 보세요.

+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.Size;

-    private String description;
-    private int price;
+    @Size(max = 500, message = "설명은 500자를 초과할 수 없습니다")
+    private String description;
+    
+    @Min(value = 0, message = "가격은 0원 이상이어야 합니다")
+    private int price;
domain/src/main/java/com/wellmeet/domain/reservation/entity/SelectedPremiumOption.java (1)

28-29: Reservation 엔티티 import가 누락되었습니다.

Reservation 타입을 사용하고 있지만 import 문이 없어 컴파일 오류가 발생할 것입니다.

 import com.wellmeet.domain.common.BaseEntity;
 import com.wellmeet.domain.restaurant.entity.PremiumOption;
+import com.wellmeet.domain.reservation.entity.Reservation;
🧹 Nitpick comments (9)
domain/src/main/java/com/wellmeet/domain/owner/entity/Owner.java (2)

26-34: 필드 정의가 적절하지만 생성자에서 null 체크를 고려해보세요.

필드들이 적절한 유효성 검증 어노테이션을 가지고 있고, boolean 필드들의 기본값 설정도 합리적입니다. 다만 생성자에서 추가적인 null 체크를 고려해볼 수 있습니다.


39-46: 생성자 구현이 올바르지만 null 체크 추가를 권장합니다.

필수 필드들을 모두 초기화하고 boolean 플래그들을 true로 설정하는 것이 적절합니다. 하지만 null 안전성을 위해 매개변수 검증을 추가하는 것을 고려해보세요.

 public Owner(String name, String email, Restaurant restaurant) {
+    if (name == null || name.isBlank()) {
+        throw new IllegalArgumentException("Owner name cannot be null or blank");
+    }
+    if (email == null || email.isBlank()) {
+        throw new IllegalArgumentException("Owner email cannot be null or blank");
+    }
+    if (restaurant == null) {
+        throw new IllegalArgumentException("Restaurant cannot be null");
+    }
     this.name = name;
     this.email = email;
     this.reservationEnabled = true;
     this.reviewEnabled = true;
     this.restaurant = restaurant;
 }
domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/BusinessHour.java (1)

44-46: ManyToOne 관계에 fetch 전략 명시를 고려해 주세요.

성능 최적화를 위해 fetch 전략을 명시적으로 지정하는 것을 권장합니다.

-@ManyToOne
+@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/ReviewTag.java (1)

25-33: 연관 엔티티 생성을 위한 생성자 추가를 고려해 보세요.

현재 protected 기본 생성자만 있어서 새로운 ReviewTag 인스턴스 생성이 번거롭습니다.

+    public ReviewTag(Review review, Tag tag) {
+        this.review = review;
+        this.tag = tag;
+    }
domain/src/main/java/com/wellmeet/domain/member/entity/FavoriteRestaurant.java (1)

31-34: 소프트 참조 방식 변경을 고려해보세요.

TODO 주석에 언급된 대로 소프트 참조 방식으로 변경하는 것을 고려해보세요. 현재의 하드 참조 방식은 Restaurant 엔티티가 삭제될 때 외래키 제약 조건 문제를 일으킬 수 있습니다.

소프트 참조 방식 구현에 대한 도움이 필요하시면 새로운 이슈를 생성해드릴 수 있습니다.

domain/src/main/java/com/wellmeet/domain/member/entity/Member.java (2)

22-42: 엔티티 설계가 잘 되어 있습니다.

필드 구성과 생성자 구현이 적절합니다. boolean 필드들을 기본값 true로 설정한 것도 사용자 친화적인 접근입니다.

다음 개선사항을 고려해보세요:

 @NotBlank
+@Email
 private String email;

이메일 필드에 @Email 검증 어노테이션을 추가하여 이메일 형식을 검증하는 것을 권장합니다.


31-33: 기능 플래그 필드명을 명확히 해보세요.

reservationEnabled, remindEnabled, reviewEnabled 필드들이 정확히 어떤 기능을 제어하는지 주석이나 더 명확한 네이밍을 고려해보세요.

예를 들어:

  • reservationNotificationEnabled (예약 알림 기능)
  • reviewNotificationEnabled (리뷰 알림 기능)

또는 각 필드에 대한 JavaDoc 주석을 추가하는 것을 권장합니다.

domain/src/main/java/com/wellmeet/domain/member/FavoriteRestaurantDomainService.java (1)

25-27: 저장 메서드의 반환 타입 검토가 필요합니다.

대부분의 JPA 저장 작업에서는 저장된 엔티티를 반환하는 것이 일반적입니다. 일관성을 위해 검토해보세요.

-public void save(FavoriteRestaurant favoriteRestaurant) {
-    favoriteRestaurantRepository.save(favoriteRestaurant);
+public FavoriteRestaurant save(FavoriteRestaurant favoriteRestaurant) {
+    return favoriteRestaurantRepository.save(favoriteRestaurant);
 }
domain/src/main/java/com/wellmeet/domain/restaurant/RestaurantDomainService.java (1)

55-59: 프리미엄 옵션 조회 메서드가 올바르게 구현되었습니다.

Restaurant 엔티티와 optionId를 모두 받아서 해당 식당에 속한 옵션만 조회하도록 하는 것은 데이터 무결성 측면에서 좋은 설계입니다. 예외 처리도 일관성 있게 구현되어 있습니다.

메서드명이 다소 길어 보입니다. 가독성을 위해 다음과 같이 단축하는 것을 고려해보세요:

-    public PremiumOption getOptionByRestaurantAndOptionId(Restaurant restaurant, Long optionId) {
+    public PremiumOption getPremiumOption(Restaurant restaurant, Long optionId) {
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a2b64bb and 95b9ffa.

📒 Files selected for processing (64)
  • api-owner/src/main/java/com/wellmeet/ownermanage/OwnerController.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/ownermanage/OwnerService.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/ownermanage/owner/OwnerService.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/ownermanage/reservation/ReservationService.java (1 hunks)
  • api-owner/src/main/java/com/wellmeet/ownermanage/restaurant/RestaurantService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/exception/ErrorCode.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/favorite/dto/FavoriteRestaurantResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/ReservationService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/dto/CreateReservationResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/dto/ReservationResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/reservation/dto/SummaryReservationResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/AvailableDateResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/NearbyRestaurantResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java (1 hunks)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RestaurantResponse.java (1 hunks)
  • api-user/src/main/resources/application-dev.yml (0 hunks)
  • api-user/src/main/resources/application-local.yml (1 hunks)
  • api-user/src/test/java/com/wellmeet/BaseControllerTest.java (2 hunks)
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java (2 hunks)
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/common/BaseEntity.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/exception/DomainErrorCode.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/FavoriteRestaurantDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/MemberDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/entity/FavoriteRestaurant.java (3 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/entity/Member.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/repository/FavoriteRestaurantRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/member/repository/MemberRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/owner/OwnerDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/owner/entity/Owner.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/owner/repository/OwnerRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/ReservationDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/entity/Reservation.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/entity/ReservationStatus.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/entity/SelectedPremiumOption.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/ReservationRepository.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/SelectedPremiumOptionRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/RestaurantDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/AvailableDateDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/entity/AvailableDate.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/repository/AvailableDateRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/BusinessHourDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/BusinessHour.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/DayOfWeek.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/entity/BoundingBox.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/entity/PremiumOption.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/entity/Restaurant.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/MenuDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/entity/Menu.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/repository/MenuRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/PremiumOptionRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/RestaurantRepository.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/ReviewDomainService.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/Review.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/ReviewTag.java (2 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/Situation.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/Tag.java (1 hunks)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/repository/ReviewRepository.java (1 hunks)
  • domain/src/test/java/com/wellmeet/domain/restaurant/entity/BoundingBoxTest.java (2 hunks)
  • domain/src/test/java/com/wellmeet/domain/restaurant/repository/RestaurantRepositoryTest.java (1 hunks)
  • domain/src/test/java/com/wellmeet/domain/restaurant/review/entity/ReviewTest.java (2 hunks)
💤 Files with no reviewable changes (1)
  • api-user/src/main/resources/application-dev.yml
✅ Files skipped from review due to trivial changes (24)
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/Situation.java
  • domain/src/main/java/com/wellmeet/domain/reservation/entity/ReservationStatus.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/DayOfWeek.java
  • api-user/src/main/resources/application-local.yml
  • domain/src/main/java/com/wellmeet/domain/owner/OwnerDomainService.java
  • domain/src/test/java/com/wellmeet/domain/restaurant/repository/RestaurantRepositoryTest.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/PremiumOptionRepository.java
  • api-owner/src/main/java/com/wellmeet/ownermanage/OwnerService.java
  • api-owner/src/main/java/com/wellmeet/ownermanage/restaurant/RestaurantService.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/BusinessHourDomainService.java
  • domain/src/main/java/com/wellmeet/domain/reservation/entity/Reservation.java
  • domain/src/main/java/com/wellmeet/domain/owner/repository/OwnerRepository.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/entity/Menu.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/entity/Restaurant.java
  • api-owner/src/main/java/com/wellmeet/ownermanage/OwnerController.java
  • api-owner/src/main/java/com/wellmeet/ownermanage/owner/OwnerService.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/repository/ReviewRepository.java
  • api-owner/src/main/java/com/wellmeet/ownermanage/reservation/ReservationService.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/entity/BoundingBox.java
  • domain/src/test/java/com/wellmeet/domain/restaurant/entity/BoundingBoxTest.java
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java
  • domain/src/main/java/com/wellmeet/domain/member/repository/FavoriteRestaurantRepository.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/Tag.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/Review.java
🚧 Files skipped from review as they are similar to previous changes (21)
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeMenuResponse.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RestaurantResponse.java
  • api-user/src/main/java/com/wellmeet/favorite/dto/FavoriteRestaurantResponse.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/NearbyRestaurantResponse.java
  • api-user/src/main/java/com/wellmeet/reservation/dto/SummaryReservationResponse.java
  • api-user/src/main/java/com/wellmeet/reservation/dto/ReservationResponse.java
  • api-user/src/main/java/com/wellmeet/reservation/dto/CreateReservationResponse.java
  • domain/src/main/java/com/wellmeet/domain/member/repository/MemberRepository.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/RepresentativeReviewResponse.java
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/SelectedPremiumOptionRepository.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/menu/repository/MenuRepository.java
  • api-user/src/main/java/com/wellmeet/restaurant/dto/AvailableDateResponse.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/repository/RestaurantRepository.java
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java
  • domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/repository/AvailableDateRepository.java
  • domain/src/main/java/com/wellmeet/domain/common/BaseEntity.java
  • api-user/src/test/java/com/wellmeet/BaseControllerTest.java
  • domain/src/main/java/com/wellmeet/domain/reservation/repository/ReservationRepository.java
  • api-user/src/main/java/com/wellmeet/reservation/ReservationService.java
  • api-user/src/main/java/com/wellmeet/exception/ErrorCode.java
  • api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: unifolio0
PR: Team-soft-macaron/WellMeet-Backend#14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at `com.wellmeet.restaurant.domain.Restaurant` after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.
domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/ReviewTag.java (3)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/CrawlingReviewAtmosphere.java:17-18
Timestamp: 2025-06-25T08:57:27.229Z
Learning: CrawlingReviewAtmosphere 엔티티는 크롤링 리뷰와 분위기 간의 관계를 나타내는 중간 테이블이므로 외부 식별자를 보존할 필요가 없어서 @GeneratedValue를 사용한 자동 ID 생성 전략을 적용해야 한다.

domain/src/main/java/com/wellmeet/domain/reservation/entity/SelectedPremiumOption.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/restaurant/entity/PremiumOption.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

domain/src/main/java/com/wellmeet/domain/restaurant/menu/MenuDomainService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/member/entity/FavoriteRestaurant.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

domain/src/main/java/com/wellmeet/domain/restaurant/review/ReviewDomainService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/BusinessHour.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/reservation/ReservationDomainService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/member/FavoriteRestaurantDomainService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/entity/AvailableDate.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/owner/entity/Owner.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/AvailableDateDomainService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/main/java/com/wellmeet/domain/exception/DomainErrorCode.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

domain/src/test/java/com/wellmeet/domain/restaurant/review/entity/ReviewTest.java (2)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

Learnt from: ezcolin2
PR: #4
File: src/main/java/com/wellmeet/restaurant/domain/crawlingreview/domain/Atmosphere.java:15-16
Timestamp: 2025-06-25T08:56:15.148Z
Learning: CrawlingReview와 Restaurant 엔티티는 외부에서 수집한 식별자를 직접 사용하므로 @GeneratedValue 없이 수동으로 ID를 설정하는 것이 적합하다.

domain/src/main/java/com/wellmeet/domain/restaurant/RestaurantDomainService.java (1)

Learnt from: unifolio0
PR: #14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at com.wellmeet.restaurant.domain.Restaurant after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.

🧬 Code Graph Analysis (7)
domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/ReviewTag.java (4)
src/main/java/com/wellmeet/restaurant/model/review/domain/ReviewTag.java (1)
  • ReviewTag (15-33)
src/main/java/com/wellmeet/restaurant/model/review/domain/Tag.java (1)
  • Tag (13-24)
src/main/java/com/wellmeet/restaurant/model/review/domain/Review.java (1)
  • Review (23-65)
src/main/java/com/wellmeet/common/domain/BaseEntity.java (1)
  • BaseEntity (11-19)
domain/src/main/java/com/wellmeet/domain/reservation/entity/SelectedPremiumOption.java (6)
src/main/java/com/wellmeet/reservation/domain/SelectedPremiumOption.java (2)
  • SelectedPremiumOption (16-43)
  • SelectedPremiumOption (35-38)
src/main/java/com/wellmeet/restaurant/domain/PremiumOption.java (2)
  • PremiumOption (15-41)
  • PremiumOption (35-40)
src/main/java/com/wellmeet/reservation/repository/SelectedPremiumOptionRepository.java (2)
  • SelectedPremiumOptionRepository (8-14)
  • findAllByReservationId (13-13)
src/main/java/com/wellmeet/restaurant/repository/PremiumOptionRepository.java (1)
  • PremiumOptionRepository (8-11)
src/main/java/com/wellmeet/reservation/ReservationService.java (1)
  • saveSelectedPremiumOption (49-54)
src/main/java/com/wellmeet/common/domain/BaseEntity.java (1)
  • BaseEntity (11-19)
domain/src/main/java/com/wellmeet/domain/restaurant/menu/MenuDomainService.java (3)
domain/src/main/java/com/wellmeet/domain/restaurant/RestaurantDomainService.java (1)
  • Service (20-60)
src/main/java/com/wellmeet/restaurant/model/menu/repository/MenuRepository.java (2)
  • MenuRepository (8-12)
  • findByRestaurantId (11-11)
src/main/java/com/wellmeet/restaurant/model/menu/domain/Menu.java (2)
  • Menu (18-44)
  • Menu (38-43)
domain/src/main/java/com/wellmeet/domain/member/entity/FavoriteRestaurant.java (5)
src/main/java/com/wellmeet/member/domain/MemberRestaurant.java (2)
  • MemberRestaurant (16-40)
  • MemberRestaurant (36-39)
src/main/java/com/wellmeet/member/service/MemberRestaurantService.java (1)
  • MemberRestaurantService (13-39)
src/main/java/com/wellmeet/favorite/FavoriteService.java (4)
  • removeFavoriteRestaurant (44-49)
  • FavoriteService (15-50)
  • addFavoriteRestaurant (36-42)
  • getFavoriteRestaurants (24-29)
src/main/java/com/wellmeet/favorite/dto/FavoriteRestaurantResponse.java (1)
  • FavoriteRestaurantResponse (7-24)
src/main/java/com/wellmeet/restaurant/domain/Restaurant.java (1)
  • Restaurant (11-37)
domain/src/main/java/com/wellmeet/domain/member/MemberDomainService.java (3)
src/main/java/com/wellmeet/member/service/MemberService.java (2)
  • MemberService (10-20)
  • getById (16-19)
src/main/java/com/wellmeet/member/domain/Member.java (1)
  • Member (13-28)
src/main/java/com/wellmeet/member/repository/MemberRepository.java (1)
  • MemberRepository (7-9)
domain/src/main/java/com/wellmeet/domain/restaurant/review/ReviewDomainService.java (8)
api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (1)
  • Service (15-49)
api-user/src/main/java/com/wellmeet/restaurant/RestaurantService.java (1)
  • Service (19-67)
domain/src/main/java/com/wellmeet/domain/restaurant/RestaurantDomainService.java (1)
  • Service (20-60)
src/main/java/com/wellmeet/restaurant/model/review/service/ReviewService.java (3)
  • ReviewService (10-30)
  • findByRestaurantId (16-21)
  • getAverageRating (23-29)
src/main/java/com/wellmeet/restaurant/model/review/repository/ReviewRepository.java (1)
  • ReviewRepository (8-12)
src/main/java/com/wellmeet/restaurant/RestaurantService.java (2)
  • getAverageRating (67-69)
  • RestaurantService (22-70)
src/main/java/com/wellmeet/restaurant/model/review/domain/Review.java (1)
  • Review (23-65)
src/main/java/com/wellmeet/favorite/FavoriteService.java (2)
  • FavoriteService (15-50)
  • getFavoriteRestaurantResponse (31-34)
domain/src/main/java/com/wellmeet/domain/owner/entity/Owner.java (3)
domain/src/main/java/com/wellmeet/domain/common/BaseEntity.java (1)
  • Getter (12-24)
domain/src/main/java/com/wellmeet/domain/member/entity/Member.java (1)
  • Getter (13-43)
domain/src/main/java/com/wellmeet/domain/restaurant/entity/Restaurant.java (1)
  • Getter (11-37)
🔇 Additional comments (42)
domain/src/main/java/com/wellmeet/domain/owner/entity/Owner.java (4)

1-16: 패키지 구조와 import 문이 적절합니다.

도메인 레이어의 owner 엔티티 패키지 구조가 멀티 모듈 아키텍처에 잘 맞고, 필요한 의존성들이 모두 올바르게 import되어 있습니다.


17-20: JPA 엔티티 어노테이션이 올바르게 설정되었습니다.

Lombok의 @Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)가 JPA 표준을 잘 따르고 있으며, BaseEntity 상속으로 공통 필드를 재사용하는 것이 좋습니다.


22-24: ID 생성 전략이 적절합니다.

@GeneratedValue(strategy = GenerationType.IDENTITY)를 사용한 Long 타입 ID는 Owner 엔티티에 적합한 선택입니다. Restaurant 엔티티와 달리 Owner는 내부적으로 생성되는 엔티티이므로 자동 생성이 맞습니다.


35-37: Restaurant 관계 매핑 확인 완료

Restaurant 엔티티의 @Id 필드가 String 타입(private String id;)임을 아래 파일에서 확인했습니다.

  • domain/src/main/java/com/wellmeet/domain/restaurant/entity/Restaurant.java:16–17

따라서 Owner 엔티티의

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;

매핑은 올바르게 설정되어 있으며, restaurant_id 컬럼도 String 타입으로 생성됩니다.

domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/BusinessHour.java (2)

1-18: 패키지 구조와 임포트가 적절합니다.

도메인 주도 설계 패턴에 따른 패키지 구조가 잘 정의되어 있고, 필요한 JPA, 검증, 시간 처리 클래스들이 모두 적절히 임포트되어 있습니다.


19-22: 클래스 구조가 JPA 모범 사례를 따르고 있습니다.

Lombok과 JPA 어노테이션이 적절히 사용되었고, protected 접근 수준의 기본 생성자는 JPA 엔티티 모범 사례를 따릅니다.

domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/AvailableDateDomainService.java (1)

15-17: AvailableDateDomainService: restaurantId 타입 일치 여부 수동 확인 필요

깔끔한 도메인 서비스 구현입니다. 단일 책임 원칙에 맞게 리포지토리에 적절히 위임하고 있습니다.
다만 메서드 시그니처의 restaurantId 파라미터가 String 타입인데, 실제 Restaurant 엔티티의 ID 필드 타입과 일치하는지 수동으로 검증해 주세요.

  • 점검 대상: domain/src/main/java/com/wellmeet/domain/restaurant/entity/Restaurant.java 파일 내 @Id가 붙은 필드의 타입
domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/entity/AvailableDate.java (1)

44-50: LGTM! 생성자 구현이 적절합니다.

생성자에서 isAvailable을 기본값 true로 설정하는 것이 합리적이며, 필수 필드들을 모두 초기화하고 있습니다.

domain/src/main/java/com/wellmeet/domain/restaurant/review/entity/ReviewTag.java (1)

1-1: 도메인 구조 리팩토링이 잘 적용되었습니다.

새로운 패키지 구조와 BaseEntity 확장이 일관성 있게 적용되었습니다.

Also applies to: 3-3, 19-19

domain/src/main/java/com/wellmeet/domain/restaurant/entity/PremiumOption.java (2)

1-1: 도메인 구조 리팩토링이 적절히 적용되었습니다.

새로운 패키지 구조와 BaseEntity 확장이 일관되게 적용되었습니다.

Also applies to: 3-3, 19-19


36-41: LGTM! 비즈니스 로직 생성자가 잘 구현되었습니다.

모든 필수 필드를 적절히 초기화하는 생성자입니다.

domain/src/main/java/com/wellmeet/domain/reservation/entity/SelectedPremiumOption.java (2)

1-1: 도메인 구조 리팩토링이 일관성 있게 적용되었습니다.

새로운 패키지 구조와 BaseEntity 확장, PremiumOption import 업데이트가 적절합니다.

Also applies to: 3-4, 20-20


36-43: LGTM! 비즈니스 생성자와 편의 메서드가 잘 구현되었습니다.

생성자에서 필수 연관관계를 설정하고, getName() 편의 메서드로 PremiumOption의 이름에 쉽게 접근할 수 있습니다.

domain/src/main/java/com/wellmeet/domain/restaurant/menu/MenuDomainService.java (1)

9-18: 도메인 서비스 구조가 잘 설계되었습니다.

깔끔한 도메인 서비스 구현입니다. 단일 책임 원칙을 잘 따르고 있으며, 다른 도메인 서비스들과 일관된 패턴을 사용하고 있습니다. 현재는 단순한 리포지토리 위임 역할이지만, 향후 메뉴 관련 비즈니스 로직이 추가될 때 적절한 위치가 될 것입니다.

domain/src/main/java/com/wellmeet/domain/member/MemberDomainService.java (1)

16-19: MemberService 중복 없음 확인 및 승인
코드베이스를 확인한 결과 MemberService.java 파일이 존재하지 않아 MemberDomainService.getById와 중복되지 않습니다.
또한 WellMeetDomainExceptionDomainErrorCode를 이용한 도메인 예외 처리도 적절하므로 변경사항을 승인합니다.

Likely an incorrect or invalid review comment.

domain/src/main/java/com/wellmeet/domain/member/entity/FavoriteRestaurant.java (1)

1-4: 패키지 구조와 네이밍 개선이 잘 되었습니다.

MemberRestaurant에서 FavoriteRestaurant로의 네이밍 변경과 도메인 계층으로의 이동이 매우 적절합니다. 의미가 더 명확해졌고, 도메인 계층의 구조에도 잘 맞습니다.

domain/src/main/java/com/wellmeet/domain/restaurant/review/ReviewDomainService.java (2)

1-11: 도메인 계층으로의 리팩토링이 잘 되었습니다.

ReviewService에서 ReviewDomainService로의 변경과 도메인 계층으로의 이동이 적절합니다. 도메인 서비스와 애플리케이션 서비스의 책임이 명확히 분리되었습니다.


23-25: 엔티티 직접 반환으로 개선되었습니다.

DTO 변환 로직을 도메인 서비스에서 제거하고 엔티티를 직접 반환하도록 변경한 것이 좋습니다. 도메인 서비스는 도메인 객체만 다루어야 하며, DTO 변환은 애플리케이션 계층의 책임입니다.

domain/src/test/java/com/wellmeet/domain/restaurant/review/entity/ReviewTest.java (4)

1-1: 패키지 구조가 새로운 도메인 아키텍처와 일치합니다.

멀티 모듈 구조로의 리팩토링이 올바르게 반영되어 도메인 계층이 명확히 분리되었습니다.


5-8: 도메인 예외 처리로의 전환이 적절합니다.

기존의 일반적인 예외 처리에서 도메인 특화 예외(WellMeetDomainException, DomainErrorCode)로 변경되어 도메인 계층의 책임이 명확해졌습니다.


23-23: Member 엔티티 생성자 변경이 정확히 반영되었습니다.

새로운 도메인 구조에서 Member 엔티티의 생성자가 추가 매개변수("test", "email@email.com")를 포함하도록 업데이트되어 일관성이 유지되었습니다.


26-27: 예외 타입과 메시지 검증이 올바릅니다.

WellMeetDomainExceptionDomainErrorCode.INVALID_RATING을 사용한 예외 검증이 새로운 도메인 예외 처리 구조와 일치합니다.

domain/src/main/java/com/wellmeet/domain/exception/DomainErrorCode.java (3)

5-6: 도메인 예외 코드 enum 설계가 적절합니다.

Lombok의 @Getter를 사용하여 간결하게 구현되었고, 도메인 계층의 예외 처리를 위한 명확한 구조를 제공합니다.


8-16: 에러 코드와 상태 코드 매핑이 적절합니다.

  • 400 상태 코드: 클라이언트 입력 오류 (유효성 검사, 권한)
  • 404 상태 코드: 리소스 찾을 수 없음
    각 에러 코드가 적절한 HTTP 상태 코드와 매핑되어 있고, 한국어 메시지가 명확합니다.

18-24: 생성자와 필드 구조가 깔끔합니다.

불변 필드를 사용하여 enum의 안정성을 보장하고, 생성자를 통한 초기화가 올바르게 구현되었습니다.

api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java (4)

15-22: 서비스 의존성 주입이 올바르게 구성되었습니다.

@RequiredArgsConstructor를 사용하여 도메인 서비스들을 깔끔하게 주입받고, API 계층에서 도메인 계층의 서비스들을 적절히 활용하고 있습니다.


24-29: 즐겨찾기 조회 로직이 효율적입니다.

스트림 API를 사용하여 도메인 엔티티를 응답 DTO로 변환하는 로직이 간결하고 읽기 쉽게 구현되었습니다.


31-34: 평점 정보를 포함한 응답 생성이 적절합니다.

리뷰 도메인 서비스를 통해 평균 평점을 조회하여 응답에 포함시키는 로직이 올바르게 구현되었습니다.


44-48: 즐겨찾기 삭제 로직이 적절합니다.

존재하지 않는 즐겨찾기에 대한 예외 처리가 도메인 서비스에서 적절히 처리되고 있습니다.

domain/src/main/java/com/wellmeet/domain/reservation/ReservationDomainService.java (5)

16-22: 도메인 서비스 구조가 잘 설계되었습니다.

레포지토리와 다른 도메인 서비스에 대한 의존성이 명확하게 정의되어 있고, 도메인 계층 내에서의 책임 분리가 적절합니다.


24-26: 예약 저장 로직이 간단명료합니다.

기본적인 CRUD 작업을 도메인 서비스에서 래핑하여 일관된 인터페이스를 제공합니다.


28-33: 프리미엄 옵션 선택 로직이 올바르게 구현되었습니다.

레스토랑과 옵션 ID를 통해 유효성을 검증하고 선택된 옵션을 저장하는 비즈니스 로직이 적절히 캡슐화되었습니다.


39-42: 예약 권한 검증이 보안 관점에서 중요합니다.

멤버 ID와 예약 ID를 모두 확인하여 무단 접근을 방지하는 보안 로직이 잘 구현되었습니다. 도메인 예외를 통한 에러 처리도 적절합니다.


52-54: 선택된 옵션 삭제 로직이 효율적입니다.

예약 ID를 기반으로 관련된 모든 프리미엄 옵션을 일괄 삭제하는 로직이 간결하게 구현되었습니다.

domain/src/main/java/com/wellmeet/domain/member/FavoriteRestaurantDomainService.java (4)

11-15: 도메인 서비스 구조가 적절합니다.

Spring의 @Service와 Lombok의 @RequiredArgsConstructor를 사용하여 깔끔한 의존성 주입을 구현했습니다.


17-19: 즐겨찾기 여부 확인 메서드가 효율적입니다.

existsByMemberIdAndRestaurantId를 사용하여 불필요한 데이터 로딩 없이 존재 여부만 확인하는 효율적인 구현입니다.


29-32: 조회 및 예외 처리가 적절합니다.

존재하지 않는 즐겨찾기에 대해 적절한 도메인 예외(MEMBER_RESTAURANT_NOT_FOUND)를 발생시키는 로직이 올바르게 구현되었습니다.


34-36: 삭제 로직이 간단명료합니다.

엔티티 기반 삭제 방식을 사용하여 안전하고 명확한 삭제 로직을 구현했습니다.

domain/src/main/java/com/wellmeet/domain/restaurant/RestaurantDomainService.java (4)

1-18: 패키지 구조와 임포트가 멀티 모듈 아키텍처에 잘 맞습니다.

새로운 도메인 계층 구조에 맞는 깔끔한 패키지 선언과 임포트 구성입니다. 도메인별 예외 처리와 엔티티들이 적절히 구성되어 있습니다.


20-28: 도메인 서비스 설계가 적절합니다.

Spring의 의존성 주입과 Lombok을 적절히 활용하고 있으며, 리포지토리와 다른 도메인 서비스들을 조합하여 식당 도메인의 비즈니스 로직을 잘 조율하고 있습니다.


30-37: 핵심 식당 조회 메서드들이 잘 구현되었습니다.

ID로 식당을 조회하는 메서드는 적절한 도메인 예외 처리를 하고 있고, 경계 박스를 이용한 지리적 검색도 깔끔하게 구현되어 있습니다. 리포지토리 계층으로의 위임이 적절합니다.


39-53: 다른 도메인 서비스로의 위임 메서드들이 잘 설계되었습니다.

평점, 예약 가능 날짜, 리뷰, 메뉴 조회 등을 각각의 전문 도메인 서비스에 위임하는 것은 관심사의 분리와 단일 진입점 제공이라는 측면에서 좋은 아키텍처 패턴입니다.

Comment on lines +36 to +42
public FavoriteRestaurantResponse addFavoriteRestaurant(Long memberId, String restaurantId) {
Member member = memberDomainService.getById(memberId);
Restaurant restaurant = restaurantDomainService.getById(restaurantId);
FavoriteRestaurant favoriteRestaurant = new FavoriteRestaurant(member, restaurant);
favoriteRestaurantDomainService.save(favoriteRestaurant);
return getFavoriteRestaurantResponse(restaurant);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

즐겨찾기 추가 로직이 트랜잭션 관점에서 검토 필요합니다.

멤버와 레스토랑 조회 후 즐겨찾기를 생성하는 로직은 올바르지만, 중복 추가에 대한 처리와 트랜잭션 경계를 고려해야 할 수 있습니다.

+@Transactional
 public FavoriteRestaurantResponse addFavoriteRestaurant(Long memberId, String restaurantId) {
+    // 중복 체크 로직 추가 고려
     Member member = memberDomainService.getById(memberId);
     Restaurant restaurant = restaurantDomainService.getById(restaurantId);
     FavoriteRestaurant favoriteRestaurant = new FavoriteRestaurant(member, restaurant);
     favoriteRestaurantDomainService.save(favoriteRestaurant);
     return getFavoriteRestaurantResponse(restaurant);
 }
📝 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
public FavoriteRestaurantResponse addFavoriteRestaurant(Long memberId, String restaurantId) {
Member member = memberDomainService.getById(memberId);
Restaurant restaurant = restaurantDomainService.getById(restaurantId);
FavoriteRestaurant favoriteRestaurant = new FavoriteRestaurant(member, restaurant);
favoriteRestaurantDomainService.save(favoriteRestaurant);
return getFavoriteRestaurantResponse(restaurant);
}
@Transactional
public FavoriteRestaurantResponse addFavoriteRestaurant(Long memberId, String restaurantId) {
// 중복 체크 로직 추가 고려
Member member = memberDomainService.getById(memberId);
Restaurant restaurant = restaurantDomainService.getById(restaurantId);
FavoriteRestaurant favoriteRestaurant = new FavoriteRestaurant(member, restaurant);
favoriteRestaurantDomainService.save(favoriteRestaurant);
return getFavoriteRestaurantResponse(restaurant);
}
🤖 Prompt for AI Agents
In api-user/src/main/java/com/wellmeet/favorite/FavoriteService.java around
lines 36 to 42, the addFavoriteRestaurant method lacks transaction management
and duplicate favorite checks. To fix this, annotate the method with a
transactional annotation to ensure atomicity, and add logic to check if the
favorite already exists before creating a new one to prevent duplicates. Handle
the duplicate case appropriately, such as returning the existing favorite or
throwing a specific exception.

Comment on lines +37 to +38
private int maxCapacity;
private boolean isAvailable;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

용량 및 가용성 관리를 위한 검증 및 비즈니스 메서드가 필요합니다.

maxCapacity 필드에 최소값 검증이 없고, isAvailable 상태를 변경하는 비즈니스 메서드가 없습니다. 예약 관리를 위해 다음을 고려해 보세요:

+import jakarta.validation.constraints.Min;

-    private int maxCapacity;
+    @Min(value = 1, message = "최대 수용 인원은 1명 이상이어야 합니다")
+    private int maxCapacity;
     private boolean isAvailable;
+
+    public void makeUnavailable() {
+        this.isAvailable = false;
+    }
+
+    public void makeAvailable() {
+        this.isAvailable = true;
+    }
📝 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
private int maxCapacity;
private boolean isAvailable;
import jakarta.validation.constraints.Min;
@Min(value = 1, message = "최대 수용 인원은 1명 이상이어야 합니다")
private int maxCapacity;
private boolean isAvailable;
public void makeUnavailable() {
this.isAvailable = false;
}
public void makeAvailable() {
this.isAvailable = true;
}
🤖 Prompt for AI Agents
In
domain/src/main/java/com/wellmeet/domain/restaurant/availabledate/entity/AvailableDate.java
around lines 37 to 38, add validation logic to ensure maxCapacity has a minimum
value (e.g., greater than zero) either in the setter or constructor. Also,
implement business methods to safely change the isAvailable status, such as
methods to mark availability or unavailability, encapsulating state changes and
enforcing any related rules.

Comment on lines +48 to +56
public BusinessHour(DayOfWeek dayOfWeek, LocalTime openTime, LocalTime closeTime,
LocalTime breakStartTime, LocalTime breakEndTime, Restaurant restaurant) {
this.dayOfWeek = dayOfWeek;
this.openTime = openTime;
this.closeTime = closeTime;
this.breakStartTime = breakStartTime;
this.breakEndTime = breakEndTime;
this.restaurant = restaurant;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

생성자에 비즈니스 규칙 검증 로직을 추가하는 것을 고려해 주세요.

현재 생성자는 단순한 필드 할당만 수행하고 있습니다. 데이터 무결성을 위해 다음과 같은 검증 로직을 추가하는 것을 권장합니다.

public BusinessHour(DayOfWeek dayOfWeek, LocalTime openTime, LocalTime closeTime,
                    LocalTime breakStartTime, LocalTime breakEndTime, Restaurant restaurant) {
+    validateBusinessHours(openTime, closeTime, breakStartTime, breakEndTime);
    this.dayOfWeek = dayOfWeek;
    this.openTime = openTime;
    this.closeTime = closeTime;
    this.breakStartTime = breakStartTime;
    this.breakEndTime = breakEndTime;
    this.restaurant = restaurant;
}

+private void validateBusinessHours(LocalTime openTime, LocalTime closeTime, 
+                                 LocalTime breakStartTime, LocalTime breakEndTime) {
+    if (openTime != null && closeTime != null && openTime.isAfter(closeTime)) {
+        throw new IllegalArgumentException("영업 시작 시간은 종료 시간보다 앞서야 합니다.");
+    }
+    if (breakStartTime != null && breakEndTime != null) {
+        if (breakStartTime.isAfter(breakEndTime)) {
+            throw new IllegalArgumentException("휴게 시작 시간은 종료 시간보다 앞서야 합니다.");
+        }
+        // 휴게시간이 영업시간 내에 있는지 확인
+        if (openTime != null && closeTime != null) {
+            if (breakStartTime.isBefore(openTime) || breakEndTime.isAfter(closeTime)) {
+                throw new IllegalArgumentException("휴게시간은 영업시간 내에 있어야 합니다.");
+            }
+        }
+    }
+}
📝 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
public BusinessHour(DayOfWeek dayOfWeek, LocalTime openTime, LocalTime closeTime,
LocalTime breakStartTime, LocalTime breakEndTime, Restaurant restaurant) {
this.dayOfWeek = dayOfWeek;
this.openTime = openTime;
this.closeTime = closeTime;
this.breakStartTime = breakStartTime;
this.breakEndTime = breakEndTime;
this.restaurant = restaurant;
}
public BusinessHour(DayOfWeek dayOfWeek, LocalTime openTime, LocalTime closeTime,
LocalTime breakStartTime, LocalTime breakEndTime, Restaurant restaurant) {
validateBusinessHours(openTime, closeTime, breakStartTime, breakEndTime);
this.dayOfWeek = dayOfWeek;
this.openTime = openTime;
this.closeTime = closeTime;
this.breakStartTime = breakStartTime;
this.breakEndTime = breakEndTime;
this.restaurant = restaurant;
}
private void validateBusinessHours(LocalTime openTime, LocalTime closeTime,
LocalTime breakStartTime, LocalTime breakEndTime) {
if (openTime != null && closeTime != null && openTime.isAfter(closeTime)) {
throw new IllegalArgumentException("영업 시작 시간은 종료 시간보다 앞서야 합니다.");
}
if (breakStartTime != null && breakEndTime != null) {
if (breakStartTime.isAfter(breakEndTime)) {
throw new IllegalArgumentException("휴게 시작 시간은 종료 시간보다 앞서야 합니다.");
}
// 휴게시간이 영업시간 내에 있는지 확인
if (openTime != null && closeTime != null) {
if (breakStartTime.isBefore(openTime) || breakEndTime.isAfter(closeTime)) {
throw new IllegalArgumentException("휴게시간은 영업시간 내에 있어야 합니다.");
}
}
}
}
🤖 Prompt for AI Agents
In
domain/src/main/java/com/wellmeet/domain/restaurant/businesshour/entity/BusinessHour.java
around lines 48 to 56, the constructor currently only assigns fields without
validating input. Add validation logic to enforce business rules such as
ensuring openTime is before closeTime, breakStartTime and breakEndTime are
within operating hours, and that breakStartTime is before breakEndTime. Throw
appropriate exceptions if these conditions are not met to maintain data
integrity.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
build.gradle (2)

38-44: 모든 서브모듈에 spring-boot-starter-test 주입은 과도
domain, common 같은 순수 Java 모듈까지 Boot 테스트 의존성이 추가되어 컴파일 시간과 JAR 크기가 불필요하게 증가합니다. Boot가 필요한 모듈(예: api-*)에서만 선언하거나 plugins.withId("org.springframework.boot") 조건부 블록으로 분기하는 방식을 고려해 주세요.


46-48: tasks.named('test') 대신 withType<Test>().configureEach 사용 권장
모듈 내부에서 커스텀 테스트 태스크를 추가할 경우 현재 방식은 누락될 수 있습니다. Gradle 권장 패턴인 tasks.withType(Test).configureEach { useJUnitPlatform() } 로 변경하면 모든 Test 태스크에 일관되게 적용됩니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 95b9ffa and 06e8f51.

📒 Files selected for processing (6)
  • api-owner/build.gradle (1 hunks)
  • api-user/build.gradle (1 hunks)
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java (4 hunks)
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java (2 hunks)
  • build.gradle (1 hunks)
  • common/build.gradle (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • common/build.gradle
  • api-user/src/test/java/com/wellmeet/favorite/controller/FavoriteControllerTest.java
  • api-user/src/test/java/com/wellmeet/restaurant/RestaurantControllerTest.java
  • api-owner/build.gradle
  • api-user/build.gradle
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: unifolio0
PR: Team-soft-macaron/WellMeet-Backend#14
File: src/main/java/com/wellmeet/recommend/dto/RecommendRestaurantResponse.java:3-3
Timestamp: 2025-07-10T02:52:48.337Z
Learning: The Restaurant class is located at `com.wellmeet.restaurant.domain.Restaurant` after the package refactoring in the WellMeet-Backend project, not in a nested model package structure.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-push
🔇 Additional comments (1)
build.gradle (1)

3-4: 확인 완료: Spring Boot / Dependency-Management 플러그인 버전 존재

  • build.gradle (3–4행)에서 사용된
    • org.springframework.boot 3.5.3
    • io.spring.dependency-management 1.1.7
      버전이 모두 Gradle Plugin Portal에 정상적으로 등록된 것이 확인되었습니다. CI 빌드에 문제 없습니다.

Copy link
Contributor

@ezcolin2 ezcolin2 left a comment

Choose a reason for hiding this comment

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

리뷰 남겼습니다~
지금 변경된 파일 부분이 많아서 경로 중복 같은 이슈만 해결하고 새로운 PR에서 리팩토링 진행하는 편이 좋을 것 같아요.

Comment on lines 15 to 21
public double getAverageRating(String restaurantId) {
return reviewRepository.findByRestaurantId(restaurantId)
.stream()
.mapToDouble(Review::getRating)
.average()
.orElse(0.0);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

평점 평균의 경우 모든 식당을 조회해서 애플리케이션에서 수행하기 보다 쿼리 한 번으로 집계하는 편이 더 좋을 것 같아요.
즐겨찾기 반환하는 API에서 찜한 식당 정보 모두 가져와서 각 식당마다 이 메소드를 호출하고 있던데 나중에 리뷰 데이터와 즐겨찾기 데이터가 많아졌을 때 성능 문제가 발생할 수도 있을 것 같아요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

반영했습니다

@PostMapping
@ResponseStatus(value = HttpStatus.CREATED)
public CreateReservationResponse reserve(
@GetMapping("{restaurantId}")
Copy link
Contributor

Choose a reason for hiding this comment

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

경로가 중복되어 있네요 식당과 예약은 구분하면 좋을 것 같아요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#23 (comment)
위에 언급한 것처럼 다음 pr에 반영할 예정입니다

Comment on lines 48 to 50
public List<Reservation> getAllByRestaurantId(String restaurantId) {
return reservationRepository.findAllByRestaurantId(restaurantId);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

이 메소드 이름은 get보다는 find가 조금 더 어울릴 것 같아요

Copy link
Contributor Author

Choose a reason for hiding this comment

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

반영했습니다

Copy link
Contributor

@ezcolin2 ezcolin2 left a comment

Choose a reason for hiding this comment

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

확인했습니다~

@unifolio0 unifolio0 merged commit 2fee340 into Team-soft-macaron:develop Jul 31, 2025
1 check passed
@unifolio0 unifolio0 deleted the feat/SCRUM-64 branch July 31, 2025 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants