Skip to content

Conversation

@unifolio0
Copy link
Contributor

@unifolio0 unifolio0 commented Nov 2, 2025

🚩 Issue

closed #58

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

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 독립 예약 관리 REST API 추가 — 생성/조회(회원·식당·ID)/수정/취소 및 중복 확인, 상태 전환 처리와 표준화된 응답 제공
    • 입력 검증(요청 유효성) 적용
  • 문서

    • Phase 4 마이크로서비스 전환 상세 계획 및 BFF vs 도메인 책임 분리 가이드, 예약 흐름·거래 전략 문서화
  • Chores

    • 예약 서비스 컨테이너화·배포 설정 추가(이미터·헬스체크·재시도·프로파일·모니터링 구성 포함)

@unifolio0 unifolio0 self-assigned this Nov 2, 2025
@unifolio0 unifolio0 added the feat label Nov 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 2, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

예약 도메인을 독립 마이크로서비스로 분리하고 domain-reservation 모듈에 REST 컨트롤러, 애플리케이션 서비스, DTO들, Dockerfile·docker-compose·build.gradle·application.yml 등 배포·운영 스캐폴드를 추가했으며 Phase4 마이그레이션 및 BFF/분산 트랜잭션 문서를 포함합니다.

Changes

Cohort / File(s) 요약
문서·계획·아키텍처
CLAUDE.md, claudedocs/microservices-migration-plan.md, claudedocs/phase4-detailed-plan.md
BFF 패턴·분산 트랜잭션 전략 문서 및 Phase4 상세 계획·흐름·샘플 코드와 배치(중복된 BFF 내용 포함) 추가
새 마이크로서비스 스캐폴드
domain-reservation/build.gradle, domain-reservation/Dockerfile, domain-reservation/src/main/resources/application.yml
domain-reservation용 의존성(spring-web, actuator, eureka), 다중 스테이지 Dockerfile, 프로파일·DB/Flyway/JPA/Eureka/Actuator/로깅 설정 추가
도커 컴포즈 및 인프라 변경
docker-compose.yml
reservation-service 서비스 항목 추가(빌드·포트·환경·헬스체크), 기존 서비스 healthcheck 세부 조정 및 retries 추가
컨트롤러(REST API)
domain-reservation/src/main/java/.../controller/DomainReservationController.java
생성/조회(회원/식당/ID)/수정/취소 엔드포인트 추가, ReservationApplicationService로 위임, 응답 코드(201/200/204) 사용
애플리케이션 레이어(오케스트레이션)
domain-reservation/src/main/java/.../service/ReservationApplicationService.java
트랜잭션 경계 설정, create/get/list/update/cancel 오케스트레이션 및 ReservationDomainService 호출과 DTO 매핑 수행
DTOs 및 매퍼
domain-reservation/src/main/java/.../dto/*
CreateReservationRequest, UpdateReservationRequest, ReservationResponse 레코드 추가; ReservationResponse.from(...) 정적 매퍼 포함
스캐폴딩/기타 클래스
domain-reservation/src/main/java/com/wellmeet/domain/ReservationServiceApplication.java
주석 처리된 Spring Boot 애플리케이션 스캐폴드 파일 추가 (비활성)

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client as 클라이언트
    participant Controller as DomainReservationController
    participant AppService as ReservationApplicationService
    participant DomainService as ReservationDomainService
    participant Repo as Repository

    Client->>Controller: POST /api/reservation (CreateReservationRequest)
    activate Controller
    Controller->>AppService: createReservation(request)
    activate AppService

    AppService->>DomainService: alreadyReserved(memberId, restaurantId, availableDateId)
    activate DomainService
    DomainService->>Repo: 중복 조회
    Repo-->>DomainService: 중복 여부
    deactivate DomainService

    alt 중복 없음
        AppService->>DomainService: save(new Reservation)
        activate DomainService
        DomainService->>Repo: save(Reservation)
        Repo-->>DomainService: 저장된 Reservation
        DomainService-->>AppService: Reservation
        deactivate DomainService

        AppService->>AppService: ReservationResponse.from(...)
        AppService-->>Controller: ReservationResponse (201 Created)
    else 중복 있음
        AppService-->>Controller: 예외/에러 응답
    end

    deactivate AppService
    Controller-->>Client: 201 Created / 4xx 에러 등
    deactivate Controller
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

주의 집중 권장 항목:

  • ReservationApplicationService: 트랜잭션 경계, 상태 전이(update/cancel) 및 예외 처리 흐름
  • DTO 유효성 어노테이션과 ReservationResponse.from 매핑 정확성
  • docker-compose.yml 및 domain-reservation/Dockerfile: 헬스체크, 포트·환경변수, depends_on 및 이미지/권한 설정
  • application.yml: 프로파일별 DB/Flyway/Eureka/Actuator 노출 설정 검증

Possibly related PRs

Suggested reviewers

  • ezcolin2

Poem

🐇 포트 8085에 달을 비추며,
작은 서비스 토굴을 파놓았네,
Docker 연기 속에 스케마 심고,
예약 한 마디, 큐에 담아 고이,
내일의 테이블엔 햇살이 앉겠네.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 "[FEAT] reservation 서버 분리"는 변경 사항의 주요 목표인 예약 서비스를 독립적인 서버로 분리하는 것을 명확하고 간결하게 요약하고 있습니다. 제목은 구체적이고 설명적이며, 팀 맴버가 commit 이력을 스캔할 때 주요 변경 사항을 쉽게 파악할 수 있도록 합니다.
Linked Issues Check ✅ Passed 연결된 issue #58의 목표는 "reservation 서버 분리"이며, PR의 코드 변경 사항이 이를 완전히 충족합니다. 추가된 DomainReservationController, DomainReservationService, DTO들, application.yml 설정, Dockerfile, 그리고 docker-compose.yml 업데이트는 예약 서비스를 독립적인 마이크로서비스로 분리하는 구현을 명확하게 보여줍니다. 모든 주요 구성 요소(API, 비즈니스 로직, 데이터 전송 객체, 배포 설정)가 포함되어 있습니다.
Out of Scope Changes Check ✅ Passed 모든 변경 사항이 예약 서버 분리라는 연결된 issue의 목표와 직접적으로 관련이 있습니다. 추가된 컨트롤러, 서비스, DTO, 설정 파일, Dockerfile, 의존성 업데이트, 그리고 docker-compose 수정은 모두 새로운 독립적인 예약 서비스를 배포하기 위한 필수 구성 요소입니다. 관련 없는 모듈 리팩토링, 다른 서비스의 버그 수정, 또는 분리와 관련 없는 변경 사항은 없습니다.
Description Check ✅ Passed PR 설명은 저장소의 필수 템플릿 구조를 따르고 있습니다. "# 🚩 Issue" 섹션에서 closed #58이 적절히 명시되어 있고, "# 🗣️ 리뷰 요구사항 (선택)" 섹션이 선택 사항으로 포함되어 있습니다. 비록 리뷰 요구사항 섹션이 비어 있지만, 이는 선택 사항이므로 승인 기준을 충족합니다.

📜 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 ad1ce73 and f4bd433.

📒 Files selected for processing (1)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/UpdateReservationRequest.java (1 hunks)

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @unifolio0, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 마이크로서비스 전환 계획의 일환으로 예약 도메인 서버를 독립적인 서비스로 분리하는 중요한 단계입니다. domain-reservation 서비스의 역할을 명확히 정의하고, 필요한 REST API와 내부 로직을 구현하며, Docker 환경에 통합하여 독립적인 배포가 가능하도록 준비했습니다. 또한, BFF 패턴과 분산 트랜잭션 처리 전략에 대한 상세한 문서화를 통해 향후 아키텍처 발전 방향을 제시하고 있습니다.

Highlights

  • 예약 서버 분리 (Phase 4): 예약 도메인 서버를 독립적인 마이크로서비스로 분리하는 작업이 진행되었습니다. 이는 마이크로서비스 전환 계획의 4단계에 해당하며, domain-reservation 서비스는 이제 독립적으로 배포됩니다.
  • BFF 패턴 및 분산 트랜잭션 전략 문서화: BFF(Backend For Frontend) 패턴과 분산 트랜잭션 처리 전략(Phase 4-6)에 대한 상세한 설계 원칙, 구현 단계, 책임 비교 및 권장 사항이 CLAUDE.mdclaudedocs/phase4-detailed-plan.md에 추가되었습니다.
  • domain-reservation 서비스 책임 명확화: 새롭게 분리된 domain-reservation 서비스는 예약 엔티티의 CRUD 및 도메인 검증(중복 체크, 파티 사이즈 검증 등)만을 담당하며, 다른 도메인 서버 호출이나 Redis 분산 락 관리, 데이터 조합 등의 복잡한 로직은 BFF(api-* 모듈)에서 처리하도록 책임이 명확히 분리되었습니다.
  • 예약 REST API 구현: domain-reservation 서비스 내에 예약 생성, 조회(회원별, 식당별, 단건), 수정, 취소, 확정, 중복 체크를 위한 REST API 엔드포인트가 구현되었습니다.
  • Docker 및 빌드 환경 통합: domain-reservation 서비스를 위한 Dockerfile이 추가되었고, docker-compose.yml에 새로운 서비스로 등록되어 독립적인 실행 및 Eureka 서버와의 연동 준비가 완료되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

이 Pull Request는 예약 도메인을 별도의 마이크로서비스로 분리하는 중요한 단계입니다. 아키텍처 변경에 대한 상세한 문서 업데이트는 매우 인상적이며, 새로운 domain-reservation 서비스의 구조는 컨트롤러, 애플리케이션 서비스, 도메인 서비스로 잘 분리되어 있습니다. 특히 Dockerfile에서 non-root 사용자를 설정한 점은 보안적으로 훌륭한 결정입니다.

다만, 몇 가지 개선점을 발견했습니다. 문서와 구현 간의 불일치, Docker 설정에서의 보안 및 모범 사례 관련 이슈, 그리고 애플리케이션 서비스 로직의 복잡성 등입니다. 특히 updateReservation 메소드는 리팩토링이 필요해 보이며, createReservation에서는 불필요한 중복 확인으로 인한 경쟁 조건이 존재합니다. 이러한 부분들에 대해 구체적인 리뷰 의견을 남겼습니다.

Comment on lines 62 to 85
@Transactional
public ReservationResponse updateReservation(Long reservationId, UpdateReservationRequest request) {
Reservation reservation = reservationDomainService.getById(reservationId);

if (request.status() != null && reservation.getStatus() != request.status()) {
if (request.status() == ReservationStatus.CONFIRMED) {
reservation.confirm();
} else if (request.status() == ReservationStatus.CANCELED) {
reservation.cancel();
}
}

if (request.partySize() != null || request.specialRequest() != null) {
Long availableDateId = reservation.getAvailableDateId();
int partySize = request.partySize() != null ? request.partySize() : reservation.getPartySize();
String specialRequest = request.specialRequest() != null ? request.specialRequest()
: reservation.getSpecialRequest();

reservation.update(availableDateId, partySize, specialRequest);
}

Reservation saved = reservationDomainService.save(reservation);
return ReservationResponse.from(saved);
}

Choose a reason for hiding this comment

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

high

updateReservation 메소드의 로직이 복잡하고 이해하기 어렵습니다. 특히 상태 변경 로직과 다른 필드 업데이트 로직이 분리되어 있고, reservation.update() 메소드 호출 방식에 혼란의 여지가 있습니다.

  • 상태 변경 로직: if (request.status() != null && ...) 블록은 CONFIRMEDCANCELED 상태 변경만 처리합니다. 이 로직은 Reservation 엔티티 내부로 옮겨 캡슐화하는 것이 좋습니다.
  • 필드 업데이트 로직: partySizespecialRequestnull이 아닐 때 reservation.update()를 호출합니다. 이때 availableDateId는 기존 예약의 값을 그대로 사용하므로, 사실상 availableDateId는 이 메소드를 통해 변경할 수 없습니다. 이는 Reservation.update() 메소드의 시그니처와 UpdateReservationRequest DTO의 필드 간에 불일치를 만듭니다.

이 메소드를 더 명확하고 견고하게 리팩토링하는 것을 제안합니다. 예를 들어, 엔티티에 상태 변경과 세부 정보 업데이트를 위한 명확한 책임의 메소드를 만들고, 서비스 레이어에서는 이를 호출만 하도록 단순화할 수 있습니다.

@Transactional
public ReservationResponse updateReservation(Long reservationId, UpdateReservationRequest request) {
    Reservation reservation = reservationDomainService.getById(reservationId);

    // partySize나 specialRequest가 제공된 경우에만 업데이트
    if (request.partySize() != null || request.specialRequest() != null) {
        // availableDateId는 업데이트하지 않으므로 기존 값을 사용
        // partySize와 specialRequest는 null일 수 있으므로 엔티티에서 처리
        reservation.updateDetails(
            request.partySize(),
            request.specialRequest()
        );
    }

    // 상태 변경 요청이 있는 경우 처리
    if (request.status() != null) {
        reservation.changeStatusTo(request.status());
    }

    // save는 @Transactional에 의해 관리되므로 명시적으로 호출할 필요가 없을 수 있습니다.
    // 하지만 명시적으로 호출하는 것도 괜찮습니다.
    Reservation saved = reservationDomainService.save(reservation);
    return ReservationResponse.from(saved);
}

위 예시처럼 엔티티(Reservation)에 updateDetailschangeStatusTo 같은 메소드를 만들어 로직을 위임하면 서비스 레이어가 더 깔끔해집니다.

Comment on lines +567 to +570
// 1. BFF가 Redis 분산 락 획득
if (!redisService.isReserving(memberId, request.restaurantId(), request.availableDateId())) {
throw new AlreadyReservingException();
}

Choose a reason for hiding this comment

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

medium

BFF의 reserve 메소드 예시 코드에서 redisService.isReserving 메소드 사용법이 실제 구현과 다릅니다.

예시 코드에서는 isReserving이 boolean을 반환하는 것처럼 if (!redisService.isReserving(...)) 형태로 사용되었지만, 실제 ReservationRedisServiceisReserving 메소드는 lock 획득에 실패하면 예외를 던지고 반환 값이 void입니다.

문서의 정확성을 위해 예시 코드를 실제 사용법에 맞게 수정하는 것이 좋겠습니다.

// 수정 제안
public CreateReservationResponse reserve(String memberId, CreateReservationRequest request) {
    // 1. BFF가 Redis 분산 락 획득
    redisService.isReserving(memberId, request.restaurantId(), request.availableDateId());

    try {
        // ... 이하 로직
    } catch (Exception e) {
        // ...
    }
}

Comment on lines +198 to +199
SPRING_DATASOURCE_PASSWORD: password
DB_PASSWORD: password

Choose a reason for hiding this comment

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

medium

reservation-service의 환경 변수 설정에 몇 가지 개선점이 있습니다.

  1. 하드코딩된 비밀번호: DB_PASSWORDSPRING_DATASOURCE_PASSWORD가 'password'로 하드코딩되어 있습니다. 보안 강화를 위해 .env 파일을 사용하여 민감한 정보를 관리하고, .env 파일은 .gitignore에 추가하는 것을 권장합니다.
  2. 중복 및 비일관적인 변수: DB_PASSWORDSPRING_DATASOURCE_PASSWORD 두 변수가 모두 암호를 설정하고 있습니다. domain-reservation/application.yml에서는 DB_PASSWORD를 사용하므로 SPRING_DATASOURCE_PASSWORD는 불필요합니다. 또한 다른 서비스(owner-service 등)는 SPRING_DATASOURCE_PASSWORD를 사용하므로, 변수명을 통일하여 일관성을 유지하는 것이 좋습니다.

아래와 같이 수정하는 것을 제안합니다.

docker-compose.yml:

...
  reservation-service:
    ...
    environment:
      SPRING_PROFILES_ACTIVE: docker
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-reservation:3306/wellmeet_reservation
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD} # .env 파일에서 읽어오도록 변경
      EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE: http://discovery-server:8761/eureka/
...

domain-reservation/src/main/resources/application.yml:

...
  datasource:
    ...
    password: ${SPRING_DATASOURCE_PASSWORD} # 다른 서비스와 통일
...

.env (새 파일, .gitignore에 추가):

DB_PASSWORD=your_local_password


ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar --spring.profiles.active=docker"]

Choose a reason for hiding this comment

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

medium

ENTRYPOINT--spring.profiles.active=docker 프로필을 하드코딩하는 대신, docker-compose.yml에 정의된 SPRING_PROFILES_ACTIVE 환경 변수를 사용하도록 하는 것이 더 유연한 방법입니다.

현재 docker-compose.yml에도 SPRING_PROFILES_ACTIVE: docker가 설정되어 있어 중복이며, 다른 환경(예: 스테이징)에서 다른 프로필로 이 이미지를 재사용하기 어렵게 만듭니다.

ENTRYPOINT에서 프로필 설정을 제거하여 환경 변수로 제어하도록 변경하는 것을 권장합니다.

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/domain/reservation")

Choose a reason for hiding this comment

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

medium

컨트롤러의 기본 경로가 /domain/reservation으로 설정되어 있습니다. 이는 마이그레이션 계획 문서(claudedocs/microservices-migration-plan.md, claudedocs/phase4-detailed-plan.md)에 명시된 /api/reservations와 일치하지 않습니다.

문서와 구현 간의 일관성을 유지하고, 향후 Feign 클라이언트에서 호출할 때 혼동을 피하기 위해 경로를 문서와 동일하게 /api/reservations로 변경하거나, 의도된 것이라면 문서를 업데이트하는 것이 좋겠습니다.

Suggested change
@RequestMapping("/domain/reservation")
@RequestMapping("/api/reservations")

Comment on lines +24 to +29
public ReservationResponse createReservation(CreateReservationRequest request) {
reservationDomainService.alreadyReserved(
request.memberId(),
request.restaurantId(),
request.availableDateId()
);

Choose a reason for hiding this comment

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

medium

createReservation 메소드에서 reservationDomainService.alreadyReserved()를 호출하여 중복 예약을 확인한 후 reservationDomainService.save()를 호출하고 있습니다. 이는 TOCTOU(Time-of-check to time-of-use) 경쟁 조건을 유발할 수 있습니다.

두 개의 동시 요청이 alreadyReserved() 체크를 통과한 후 save()를 시도하면, 하나는 데이터베이스의 unique 제약 조건 위반으로 실패하게 됩니다. ReservationDomainService.save() 메소드 내에서 이미 DataIntegrityViolationException을 처리하여 ALREADY_RESERVED 예외를 던지도록 구현되어 있으므로, alreadyReserved()를 미리 호출하는 것은 중복이며 불필요합니다.

경쟁 조건을 없애고 코드를 단순화하기 위해 alreadyReserved() 호출을 제거하는 것을 권장합니다.

    public ReservationResponse createReservation(CreateReservationRequest request) {

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docker-compose.yml (1)

183-208: reservation-service의 프로파일을 local로 수정 필요

검증 결과, domain-reservation 서비스는 application-domain-local.yml 파일을 가지고 있지만, application-domain-docker.yml 파일은 존재하지 않습니다.

현재 설정:

  • reservation-service: SPRING_PROFILES_ACTIVE: docker (해당 파일 없음)
  • 다른 모든 서비스: SPRING_PROFILES_ACTIVE: local (설정 파일 존재)

이는 명백한 오류입니다. reservation-service도 다른 서비스들과 동일하게 local 프로파일을 사용하도록 수정하세요.

      SPRING_PROFILES_ACTIVE: local
🧹 Nitpick comments (3)
docker-compose.yml (1)

196-200: 환경 변수 중복 설정

SPRING_DATASOURCE_URL, SPRING_DATASOURCE_PASSWORDDB_PASSWORD가 모두 설정되어 있습니다. application.yml의 docker 프로파일은 ${DB_PASSWORD}만 사용하므로 Spring 환경 변수가 불필요할 수 있습니다.

중복을 제거하여 설정을 단순화하세요:

     environment:
       SPRING_PROFILES_ACTIVE: docker
-      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-reservation:3306/wellmeet_reservation
-      SPRING_DATASOURCE_USERNAME: root
-      SPRING_DATASOURCE_PASSWORD: password
       DB_PASSWORD: password
       EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE: http://discovery-server:8761/eureka/

application.yml의 docker 프로파일에서 이미 URL과 username을 정의하고 있으므로, DB_PASSWORD만 환경 변수로 주입하면 됩니다.

domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/CreateReservationRequest.java (1)

16-17: partySize 필드에 최소값 검증 추가 필요

partySize@NotNull만 있고 최소값 검증이 없어서 0 이하의 값이 허용될 수 있습니다. 예약 인원은 최소 1명 이상이어야 합니다.

다음 diff를 적용하여 검증을 추가하세요:

+    @Min(1)
     @NotNull
     Integer partySize,
claudedocs/phase4-detailed-plan.md (1)

683-721: 코드 블록에 언어 지정 추가 (선택적)

Markdown 코드 블록에 언어 식별자를 추가하면 가독성이 향상됩니다. Lines 683, 696, 709의 코드 블록에 언어를 지정하세요.

예시:

-```
+```text
 domain-reservation
 └── Reservation CRUD + 도메인 검증
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 906fd04 and b782264.

📒 Files selected for processing (13)
  • CLAUDE.md (1 hunks)
  • claudedocs/microservices-migration-plan.md (1 hunks)
  • claudedocs/phase4-detailed-plan.md (1 hunks)
  • docker-compose.yml (3 hunks)
  • domain-reservation/Dockerfile (1 hunks)
  • domain-reservation/build.gradle (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/ReservationServiceApplication.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/CreateReservationRequest.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/ReservationResponse.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/UpdateReservationRequest.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/service/ReservationApplicationService.java (1 hunks)
  • domain-reservation/src/main/resources/application.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-10T02:52:48.337Z
Learnt from: unifolio0
Repo: Team-soft-macaron/WellMeet-Backend 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.

Applied to files:

  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/service/ReservationApplicationService.java
  • domain-reservation/src/main/java/com/wellmeet/domain/ReservationServiceApplication.java
🪛 markdownlint-cli2 (0.18.1)
claudedocs/phase4-detailed-plan.md

14-14: Link fragments should be valid

(MD051, link-fragments)


683-683: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


696-696: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


709-709: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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 (15)
domain-reservation/build.gradle (1)

13-15: 마이크로서비스 전환을 위한 의존성 추가 확인

Spring Boot Web, Actuator, Eureka Client 의존성이 적절히 추가되었습니다. 이들은 Phase 4의 도메인 예약 서비스 분리를 위해 필수적입니다.

domain-reservation/Dockerfile (2)

28-29: 보안 모범 사례 준수 확인

non-root 사용자로 애플리케이션을 실행하는 것은 좋은 보안 관행입니다.


33-33: 메모리 설정 검토 필요

Xms512m, Xmx1024m 설정이 예약 도메인의 실제 부하에 적합한지 확인이 필요합니다.

프로덕션 환경에서 메모리 사용량을 모니터링하고 필요시 조정하세요. 특히 동시 예약 처리량이 높은 경우 힙 크기 증가가 필요할 수 있습니다.

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

1-14: Phase 4 단계적 전환을 위한 주석 처리 확인

애플리케이션 클래스가 의도적으로 주석 처리되어 있습니다. CLAUDE.md 문서에 따르면 Phase 5에서 활성화 예정입니다.

단계적 전환 전략은 이해되나, 완전히 주석 처리된 파일을 유지하는 것보다 다음을 고려해보세요:

  • Phase 4에서는 파일 자체를 제거하고 Phase 5에서 추가
  • 또는 @Profile("phase5") 어노테이션을 활용하여 조건부 활성화

현재 방식으로 진행하려면 주석에 Phase 정보를 명시하는 것이 좋습니다:

// Phase 4: 이 클래스는 의도적으로 비활성화되어 있습니다.
// Phase 5에서 주석을 제거하여 독립 서비스로 전환합니다.
// 관련 이슈: #58
domain-reservation/src/main/resources/application.yml (2)

31-46: Phase별 Eureka 설정 문서화 잘 되어 있음

Phase 4/5 전환 시점에 대한 주석이 명확하게 작성되어 Eureka 활성화 시점을 이해하기 쉽습니다.


115-119: Docker 환경에서 Eureka 활성화 설정 확인

Docker 프로파일에서 Eureka가 활성화되어 있으나, Phase 5 이후라는 주석이 있습니다. Phase 4에서는 비활성화되어야 하는지 확인이 필요합니다.

현재 Phase와 Eureka 활성화 시점이 일치하는지 확인하세요. Phase 4라면 다음과 같이 수정을 고려하세요:

eureka:
  client:
    enabled: false  # Phase 4에서는 비활성화, Phase 5에서 true로 변경
domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/UpdateReservationRequest.java (1)

5-11: 부분 업데이트 의도 확인 및 검증 추가 고려

모든 필드가 nullable이며 검증 어노테이션이 없습니다. PATCH 방식의 부분 업데이트를 의도한 것인지 확인이 필요합니다.

전체 업데이트(PUT)를 의도했다면 검증 추가를 권장합니다:

public record UpdateReservationRequest(
        @Min(1) @Max(20)
        Integer partySize,

        @Size(max = 500)
        String specialRequest,

        @NotNull
        ReservationStatus status
) {
}

부분 업데이트(PATCH)가 의도라면 서비스 레이어에서 null이 아닌 필드만 업데이트하는 로직이 있는지 확인하세요.

CLAUDE.md (1)

228-456: BFF 패턴 및 분산 트랜잭션 문서화 잘 작성됨

Phase별 전환 전략, 책임 분리, 그리고 Saga 패턴에 대한 상세한 가이드가 잘 작성되어 있습니다. 코드 예시와 비교표가 이해를 돕습니다.

docker-compose.yml (1)

125-130: 헬스체크 재시도 설정 추가 확인

기존 서비스들에 retries: 3 설정이 추가되어 서비스 안정성이 향상되었습니다.

Also applies to: 151-156, 177-182

domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/ReservationResponse.java (1)

19-31: 검증 완료: 코드 변경 불필요

Reservation 엔티티의 null-safety 검증 결과:

  • specialRequest: 필드는 null 가능하도록 설계됨 (validateRequest() 메서드에서 specialRequest != null 조건으로 명시적 처리)
  • updatedAt/createdAt: BaseEntity에서 @NotNull@LastModifiedDate/@CreatedDate로 관리되어 항상 non-null 보장
  • 기타 필드: 모두 @NotNull 또는 @NotBlank 주석으로 보호됨
  • partySize: 원시형 int, validatePartySize()에서 양수 검증

ReservationResponse.from() 메서드는 Lombok의 @Getter로 자동 생성된 getter를 호출하며, 모든 필드에 대해 null-safe합니다. 정적 팩토리 메서드 매핑 로직은 명확하고 안전합니다.

domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java (1)

20-76: 잘 구현된 REST 컨트롤러

HTTP 메서드와 상태 코드를 적절히 사용하고, @Valid를 통한 입력 검증이 올바르게 적용되어 있습니다. 서비스 레이어로의 위임도 깔끔합니다.

domain-reservation/src/main/java/com/wellmeet/domain/reservation/service/ReservationApplicationService.java (1)

13-93: 트랜잭션 경계 및 서비스 로직 적절함

@Transactional(readOnly = true)를 클래스 레벨에 적용하고 쓰기 작업에만 @Transactional을 명시한 구조가 좋습니다. updateReservation 메서드의 상태 변경과 필드 업데이트 로직도 올바르게 분리되어 있습니다.

claudedocs/microservices-migration-plan.md (1)

534-567: DTO 검증 규칙 문서와 구현 불일치

문서의 DTO 검증 규칙(line 539: @Min(1), line 540: @Size(max=255))이 실제 CreateReservationRequest 구현과 일치하지 않습니다. 실제 코드에서 partySize@Min 검증이 없고, specialRequest@Size 검증이 없습니다.

일관성을 위해:

  1. 코드를 문서에 맞게 수정하거나
  2. 문서를 실제 구현에 맞게 업데이트하세요

기술 부채를 줄이려면 문서에 명시된 검증 규칙을 코드에 적용하는 것을 권장합니다.

claudedocs/phase4-detailed-plan.md (2)

58-84: API 경로 불일치 (Phase 4 계획)

이 문서에도 /api/reservations 경로가 명시되어 있지만, 실제 컨트롤러는 /domain/reservation을 사용합니다. microservices-migration-plan.md와 함께 일관성 있게 수정이 필요합니다.


270-291: DTO 검증 규칙 일관성

문서에 명시된 검증 규칙(@Min(1) for partySize, @Size(max=255) for specialRequest)이 실제 구현에 누락되어 있습니다. CreateReservationRequest.java에 이러한 검증을 추가하여 문서와 코드를 일치시키세요.

Comment on lines +450 to +487
**파일**: `domain-reservation/src/main/java/com/wellmeet/domain/reservation/api/DomainReservationController.java`

3. **Dockerfile 생성**: `domain-reservation/Dockerfile`
**엔드포인트**:
- POST `/api/reservations` - 예약 생성 (저장만)
- GET `/api/reservations/member/{memberId}` - 회원별 예약 조회
- GET `/api/reservations/restaurant/{restaurantId}` - 식당별 예약 조회
- GET `/api/reservations/{id}` - 예약 단건 조회
- PUT `/api/reservations/{id}` - 예약 수정
- PATCH `/api/reservations/{id}/cancel` - 예약 취소
- PATCH `/api/reservations/{id}/confirm` - 예약 확정
- GET `/api/reservations/check-duplicate` - 중복 예약 체크

4. **docker-compose.yml 업데이트**: domain-reservation-service 추가
```java
@RestController
@RequestMapping("/api/reservations")
@RequiredArgsConstructor
public class DomainReservationController {

private final DomainReservationService domainReservationService;

// 예약 생성 (저장만)
@PostMapping
public ReservationResponse createReservation(@Valid @RequestBody CreateReservationRequest request) {
Reservation reservation = domainReservationService.createReservation(request);
return ReservationResponse.from(reservation);
}

// 회원별 조회
@GetMapping("/member/{memberId}")
public List<ReservationResponse> getReservationsByMember(@PathVariable String memberId) {
return domainReservationService.findAllByMemberId(memberId).stream()
.map(ReservationResponse::from)
.toList();
}

// ... 나머지 엔드포인트
}
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

문서와 실제 구현 간 API 경로 불일치

문서에는 /api/reservations 경로가 명시되어 있지만, 실제 DomainReservationController/domain/reservation 경로를 사용합니다. API 경로의 일관성을 위해 문서를 업데이트하거나 코드를 수정해야 합니다.

실제 구현:

  • DomainReservationController.java line 21: @RequestMapping("/domain/reservation")

문서:

  • Line 453, 463-487: /api/reservations 경로 명시
🤖 Prompt for AI Agents
In claudedocs/microservices-migration-plan.md around lines 450–487 the
documented endpoints use /api/reservations but the actual controller
(DomainReservationController.java line 21) is annotated with
@RequestMapping("/domain/reservation"); make them consistent by either updating
the docs to reflect /domain/reservation or changing the controller annotation to
@RequestMapping("/api/reservations") and adjusting any path segments in the
controller methods, integration tests, and OpenAPI/swagger configuration
accordingly; ensure only one canonical base path is used across code, docs, and
tests.

Comment on lines +23 to +26
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8085/actuator/health || exit 1

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

curl 설치 순서 문제로 헬스체크 실패 가능

헬스체크 정의(Line 23-24)가 curl 설치(Line 26)보다 먼저 실행됩니다. 이로 인해 컨테이너 시작 시 헬스체크가 실패할 수 있습니다.

다음과 같이 순서를 변경하세요:

+RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
+
 HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
   CMD curl -f http://localhost:8085/actuator/health || exit 1
-
-RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
📝 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
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8085/actuator/health || exit 1
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8085/actuator/health || exit 1
🤖 Prompt for AI Agents
In domain-reservation/Dockerfile around lines 23-26, the HEALTHCHECK uses curl
before curl is installed which can cause startup healthcheck failures; move the
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
line to appear before the HEALTHCHECK (or install curl in an earlier layer/base
image), then keep the HEALTHCHECK as-is so curl is available when the health
probe runs.

Comment on lines +7 to +9
url: jdbc:mysql://localhost:3306/wellmeet_reservation?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
username: root
password: ${DB_PASSWORD:}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

로컬 환경 DB 비밀번호 기본값 검증 필요

로컬 환경의 DB 비밀번호 기본값이 빈 문자열입니다. docker-compose.yml의 MySQL 설정과 일치하는지 확인이 필요합니다.

다음 스크립트로 docker-compose.yml의 MySQL 비밀번호 설정을 확인하세요:


🏁 Script executed:

#!/bin/bash
# docker-compose.yml에서 mysql-reservation의 비밀번호 확인
rg -A2 'mysql-reservation:' docker-compose.yml | rg 'MYSQL_ROOT_PASSWORD'

Length of output: 0


더 포괄적인 검증을 위해 다음 스크립트를 실행하겠습니다.


---

🏁 Script executed:

```shell
#!/bin/bash
# 1. docker-compose.yml 파일 위치 찾기
echo "=== Searching for docker-compose.yml ==="
fd 'docker-compose\.yml' -type f

# 2. application.yml 위치 확인
echo -e "\n=== Searching for application.yml ==="
fd 'application\.yml' -type f

Length of output: 421


🏁 Script executed:

#!/bin/bash
# 3. docker-compose.yml 내용 확인 (모든 내용)
echo "=== docker-compose.yml 전체 내용 ==="
find . -name 'docker-compose.yml' -type f -exec cat {} \;

# 4. application.yml에서 DB 설정 확인
echo -e "\n=== application.yml의 DB 설정 ==="
find . -name 'application.yml' -type f -exec grep -A5 'spring:' {} + | grep -A3 'datasource:'

Length of output: 7720


🏁 Script executed:

#!/bin/bash
# 5. MySQL 관련 환경 변수 및 비밀번호 설정 모두 확인
echo "=== docker-compose.yml에서 MySQL 관련 설정 모두 ==="
find . -name 'docker-compose.yml' -type f -exec grep -i 'mysql\|password' {} +

Length of output: 2424


🏁 Script executed:

#!/bin/bash
# 6. application.yml에서 DB 비밀번호 설정 확인
echo "=== application.yml에서 DB 비밀번호 설정 ==="
find . -name 'application.yml' -type f -exec cat {} +

Length of output: 5691


로컬 환경 DB 비밀번호 불일치 - 수정 필요

검증 결과, 설정이 일치하지 않습니다:

  • docker-compose.yml: MYSQL_ROOT_PASSWORD: password, DB_PASSWORD: password
  • application.yml (로컬 프로파일): password: ${DB_PASSWORD:} → 기본값이 빈 문자열

DB_PASSWORD 환경 변수를 설정하지 않고 로컬에서 실행하면 빈 비밀번호로 연결을 시도하여 실패합니다. domain-member, domain-owner 등 다른 서비스들은 password: password로 일관되게 설정되어 있습니다.

수정 방법: application.yml 로컬 프로파일의 7-9번 줄을 다음 중 하나로 변경하세요:

  • password: ${DB_PASSWORD:password} (다른 서비스와 일관성)
  • 또는 password: password (환경 변수 제거)
🤖 Prompt for AI Agents
In domain-reservation/src/main/resources/application.yml around lines 7 to 9,
the DB password reference uses password: ${DB_PASSWORD:} which defaults to an
empty string and causes local connection failures; update the property to
provide a default matching the docker-compose value so it is consistent with
other services — either change to password: ${DB_PASSWORD:password} or to
password: password depending on whether you prefer an environment-backed or
hardcoded value.

Comment on lines +110 to +113
datasource:
url: jdbc:mysql://mysql-reservation:3306/wellmeet_reservation?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
username: root
password: ${DB_PASSWORD:wellmeet123}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Docker 환경 기본 비밀번호 보안 취약

Docker 프로파일의 기본 DB 비밀번호가 하드코딩되어 있습니다 ("wellmeet123"). 프로덕션 환경에서 이 값이 노출될 위험이 있습니다.

다음 개선 사항을 적용하세요:

  1. 기본값 제거 또는 더 강력한 값으로 변경:
-    password: ${DB_PASSWORD:wellmeet123}
+    password: ${DB_PASSWORD}
  1. Docker Compose나 K8s Secret을 통해 비밀번호 주입을 필수화하세요.

  2. 로컬 개발 환경용이라면 주석으로 명시:

# 로컬 개발 전용 - 프로덕션에서는 반드시 DB_PASSWORD 환경변수 설정 필요
password: ${DB_PASSWORD:wellmeet123}
🤖 Prompt for AI Agents
In domain-reservation/src/main/resources/application.yml around lines 110 to
113, the DB password is hardcoded as a weak default ("wellmeet123"); remove this
insecure default and require the password from the environment (no fallback
value), update deployment docs to inject DB_PASSWORD via Docker Compose or
Kubernetes Secret, and if needed for local dev add a clear commented note above
the property indicating it is only for local development and that production
must set DB_PASSWORD via secrets.

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: 1

♻️ Duplicate comments (3)
domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java (1)

20-21: 문서와의 경로 불일치 확인 필요

기본 경로가 /api/reservation (단수)으로 설정되어 있습니다. 이전 리뷰에서 마이그레이션 문서에는 /api/reservations (복수)로 명시되어 있다고 지적되었습니다. REST API 관례상 리소스 컬렉션은 복수형을 사용하는 것이 일반적입니다.

문서와의 일관성을 위해 경로를 /api/reservations로 변경하거나, 의도된 설계라면 문서를 업데이트해 주세요.

-@RequestMapping("/api/reservation")
+@RequestMapping("/api/reservations")
domain-reservation/src/main/java/com/wellmeet/domain/reservation/service/ReservationApplicationService.java (2)

24-29: TOCTOU 경쟁 조건으로 인한 중복 예약 체크 불필요

alreadyReserved() 체크와 save() 호출 사이에 경쟁 조건(TOCTOU)이 발생할 수 있습니다. 두 개의 동시 요청이 alreadyReserved() 체크를 통과한 후 save()를 시도하면 중복 예약이 발생할 수 있습니다. ReservationDomainService.save() 메소드에서 이미 DataIntegrityViolationException을 처리하여 중복 예약 예외를 던지므로, 이 체크는 불필요하며 제거하는 것이 좋습니다.

     @Transactional
     public ReservationResponse createReservation(CreateReservationRequest request) {
-        reservationDomainService.alreadyReserved(
-                request.memberId(),
-                request.restaurantId(),
-                request.availableDateId()
-        );
-
         Reservation reservation = new Reservation(
                 request.restaurantId(),
                 request.availableDateId(),

62-81: updateReservation 로직 복잡도 및 설계 개선 필요

updateReservation 메소드의 로직이 여전히 복잡하고 개선이 필요합니다:

  • 상태 변경과 필드 업데이트 혼재: 상태 변경(lines 66-71)과 필드 업데이트(lines 73-77)가 분리되어 있어 가독성이 떨어집니다.
  • 불필요한 availableDateId 처리: Line 73에서 기존 예약의 availableDateId를 가져와서 line 77에서 update()에 다시 전달하고 있습니다. 이는 availableDateId를 실제로 변경할 수 없음에도 혼란을 야기합니다.
  • 무조건적인 update() 호출: Line 77에서 필드 변경 여부와 관계없이 항상 update()를 호출하여 불필요한 업데이트가 발생할 수 있습니다.

엔티티(Reservation)에 상태 변경과 필드 업데이트를 위한 명확한 메소드(예: updateDetails(), changeStatusTo())를 구현하고, 서비스 레이어에서는 이를 호출하도록 리팩토링하는 것을 권장합니다.

🧹 Nitpick comments (2)
domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/UpdateReservationRequest.java (1)

11-11: specialRequest 필드에 대한 유효성 검사 추가 검토

specialRequest 필드에 유효성 검사가 없어 null 값이나 무제한 길이의 문자열을 허용합니다. 비즈니스 요구사항에 따라 최대 길이 제한이나 다른 제약 조건이 필요한지 검토해 주세요.

필요한 경우 다음과 같이 유효성 검사를 추가할 수 있습니다:

+        @Size(max = 500)
         String specialRequest,
domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java (1)

44-60: 목록 조회 엔드포인트에 페이지네이션 고려

레스토랑별, 회원별 예약 목록을 조회하는 엔드포인트에 페이지네이션이 적용되어 있지 않습니다. 예약이 많은 레스토랑이나 활동적인 회원의 경우 응답 크기가 과도하게 커질 수 있어 성능 문제가 발생할 수 있습니다.

Pageable 파라미터를 추가하고 Page<ReservationResponse>를 반환하도록 변경하는 것을 권장합니다.

예시:

@GetMapping("/restaurant/{restaurantId}")
public ResponseEntity<Page<ReservationResponse>> getReservationsByRestaurant(
        @PathVariable String restaurantId,
        Pageable pageable
) {
    Page<ReservationResponse> responses = reservationApplicationService
            .getReservationsByRestaurant(restaurantId, pageable);
    return ResponseEntity.ok(responses);
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b782264 and ad1ce73.

📒 Files selected for processing (3)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/dto/UpdateReservationRequest.java (1 hunks)
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/service/ReservationApplicationService.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-10T02:52:48.337Z
Learnt from: unifolio0
Repo: Team-soft-macaron/WellMeet-Backend 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.

Applied to files:

  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java
  • domain-reservation/src/main/java/com/wellmeet/domain/reservation/service/ReservationApplicationService.java
⏰ 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 (3)
domain-reservation/src/main/java/com/wellmeet/domain/reservation/controller/DomainReservationController.java (3)

24-28: 생성자 주입 방식 잘 적용됨

생성자를 통한 의존성 주입이 올바르게 구현되어 있습니다. 이는 Spring의 권장 방식이며 테스트 가능성도 높입니다.


30-36: 생성 엔드포인트 구현 적절함

POST 엔드포인트가 적절한 HTTP 상태 코드(201 Created)를 반환하고 있으며, @Valid를 통한 요청 검증도 올바르게 적용되어 있습니다.


62-75: 업데이트 및 취소 엔드포인트 구현 적절함

  • 업데이트 엔드포인트는 @Valid를 통한 검증과 함께 적절히 구현되어 있습니다.
  • 취소 엔드포인트는 PATCH 메서드와 204 No Content 응답을 사용하여 REST 관례를 잘 따르고 있습니다.

@unifolio0 unifolio0 merged commit b4ca8f9 into Team-soft-macaron:develop Nov 2, 2025
1 of 2 checks passed
@unifolio0 unifolio0 deleted the feat/#58 branch November 2, 2025 05:16
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.

[FEAT] reservation 서버 분리

1 participant