Skip to content

Conversation

@yesrin
Copy link
Owner

@yesrin yesrin commented Oct 11, 2025

📋 작업 내용

MSA 핵심 패턴 구현을 통한 시스템 안정성 및 확장성 향상

Closes #7

✨ 주요 변경사항

1. 🔧 Config Server 추가

  • Spring Cloud Config Server 구현 (Native profile)
  • 중앙 설정 관리로 서비스별 설정 일관성 확보
  • config-server/src/main/resources/config/에서 각 서비스 설정 관리

2. 🗄️ Database per Service 패턴

  • User Service: MySQL userdb (포트 3306)
  • Order Service: MySQL orderdb (포트 3307)
  • 서비스별 데이터 독립성 및 확장성 확보
  • MSA 핵심 원칙 준수

3. ⚡ Resilience4j Circuit Breaker

  • API Gateway에 Circuit Breaker 패턴 적용
  • FallbackController 구현으로 장애 시 적절한 응답 제공
  • 서비스 장애 전파 방지 및 시스템 안정성 향상

4. 🆕 최신 설정 방식 적용

  • bootstrap.yml 제거 (Spring Cloud 2020.0.0 이전 방식)
  • spring.config.import 적용 (현재 권장 방식)
  • 더 간결하고 명확한 설정 구조

5. 🐳 Docker Compose 업데이트

  • MySQL 컨테이너 추가 (health check 포함)
  • 서비스 간 의존성 및 시작 순서 관리
  • 환경변수 기반 설정 주입

🛠 기술 스택

  • Spring Cloud Config
  • Resilience4j
  • MySQL 8.0
  • Docker Compose

📊 시스템 아키텍처

┌─────────────────────┐
│   Config Server     │ ← 중앙 설정 관리
│   (port 8888)       │
└─────────────────────┘

┌─────────────────────┐
│   Eureka Server     │ ← 서비스 디스커버리
│   (port 8761)       │
└─────────────────────┘

┌─────────────────────┐
│   API Gateway       │ ← Circuit Breaker
│   (port 8080)       │
└──────────┬──────────┘
           │
    ┌──────┴───────────────┐
    │                      │
┌───▼──────────┐   ┌──────▼────────┐
│ User Service │   │ Order Service │
│ (port 8081)  │   │ (port 8082)   │
└───────┬──────┘   └──────┬────────┘
        │                 │
   ┌────▼─────┐      ┌───▼─────┐
   │ MySQL    │      │ MySQL   │
   │ userdb   │      │ orderdb │
   │ (3306)   │      │ (3307)  │
   └──────────┘      └─────────┘

🔍 주요 파일 변경

새로 추가된 파일

  • config-server/ - Config Server 전체 모듈
  • api-gateway/src/main/java/com/example/gateway/FallbackController.java - Fallback 컨트롤러
  • config-server/src/main/resources/config/*.yml - 서비스별 설정 파일

수정된 파일

  • docker-compose.yml - MySQL 컨테이너 및 Config Server 추가
  • */build.gradle - Config Client, Circuit Breaker 의존성 추가
  • */application.yml - spring.config.import 설정 추가

삭제된 파일

  • */bootstrap.yml - 구식 설정 방식 제거

📸 스크린샷

추천 캡쳐:

  1. Docker 컨테이너 실행 상태 (docker ps)
  2. Eureka Dashboard (http://localhost:8761)
  3. Config Server Health Check (http://localhost:8888/actuator/health)
  4. 서비스별 로그 (정상 시작 확인)
image

✅ 테스트 체크리스트

  • Config Server 정상 시작
  • MySQL 컨테이너 health check 통과
  • User Service - Config Server 연동 확인
  • Order Service - Config Server 연동 확인
  • API Gateway - Circuit Breaker 설정 확인
  • Eureka에 모든 서비스 등록 확인
  • 서비스 간 의존성 순서 정상 동작

🎯 기술적 의사결정

Database per Service 패턴 선택

장점:

  • ✅ 서비스 독립성 및 확장성 향상
  • ✅ 장애 격리 (한 DB 장애가 다른 서비스에 영향 없음)
  • ✅ 각 서비스가 적합한 DB 기술 선택 가능

Trade-off:

  • ❌ 트랜잭션 관리 복잡도 증가 (Saga 패턴 필요)
  • ❌ 데이터 조인 불가 → API 호출 또는 이벤트 기반 통신 필요

spring.config.import 선택

  • Spring Cloud 2020.0.0+ 권장 방식
  • Bootstrap context 불필요로 복잡도 감소
  • 실무 표준 적용

📝 향후 개선 사항

  • Kafka/RabbitMQ를 통한 이벤트 기반 통신
  • Distributed Tracing (Zipkin/Jaeger)
  • API Gateway Rate Limiting
  • Kubernetes 배포 설정
  • Saga 패턴 구현 (분산 트랜잭션)

Related Issue: #7
Commits: a9d03e4

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 신규 기능
    • 구성 서버 도입으로 서비스 설정 중앙화 및 동적 로딩 지원
    • API 게이트웨이에 서킷 브레이커와 서비스별 폴백 엔드포인트 추가
    • 모니터링을 위한 애플리케이션 상태/지표 노출 활성화
  • 변경
    • 사용자/주문 서비스가 외부 구성 연동 및 MySQL 사용으로 전환
    • Docker Compose에 구성 서버와 MySQL 서비스 통합, 서비스 간 의존/헬스체크 개선
  • 문서
    • 배포용 환경 변수 예시(.env.example) 추가 및 보안 가이드 제공

MSA 핵심 패턴 구현:

1. Config Server 추가
   - Spring Cloud Config Server 구현 (Native profile)
   - 중앙 설정 관리로 설정 일관성 확보
   - 각 서비스의 설정을 config/ 디렉토리에서 관리

2. Database per Service 패턴 구현
   - User Service용 MySQL (userdb, 3306)
   - Order Service용 MySQL (orderdb, 3307)
   - 서비스 간 데이터 독립성 확보
   - 각 서비스가 독립적으로 확장 가능

3. Resilience4j Circuit Breaker 구현
   - API Gateway에 Circuit Breaker 추가
   - 서비스 장애 시 Fallback 응답 제공
   - 장애 격리로 시스템 안정성 향상

4. 최신 설정 방식 적용
   - bootstrap.yml 제거 (deprecated)
   - spring.config.import 사용 (Spring Cloud 2020.0.0+)
   - 더 간결하고 명확한 설정 구조

5. Docker Compose 업데이트
   - MySQL 컨테이너 추가 (health check 포함)
   - 서비스 간 의존성 및 시작 순서 관리
   - 환경변수 기반 설정 주입

기술 스택:
- Spring Cloud Config
- Resilience4j
- MySQL 8.0
- Docker Compose

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Oct 11, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (2)
  • docs/Circuit-Breaker-QNA.md is excluded by !**/*.md, !**/docs/**
  • docs/resilience4j-patterns.md is excluded by !**/*.md, !**/docs/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Config Server 모듈을 신규 추가하고, 각 서비스가 spring.config.import로 중앙 설정을 참조하도록 구성했다. API Gateway에 Resilience4j 기반 서킷브레이커와 FallbackController를 도입했다. User/Order 서비스는 MySQL로 전환되었고 Docker Compose에 DB와 의존성/헬스체크가 추가됐다. IDE/Gradle 설정과 공용 빌드 스크립트가 보완됐다.

Changes

Cohort / File(s) Summary
IDE 설정 업데이트
/.idea/compiler.xml, /.idea/gradle.xml
어노테이션 프로세싱 프로필 정리, GradleMigrationSettings 추가, 모듈/프로젝트 설정 갱신
루트 빌드/세팅
/settings.gradle, /build.gradle, /common/build.gradle
config-server 모듈 포함, Lombok 버전 명시(1.18.30), common 모듈을 라이브러리 JAR로 빌드(bootJar 비활성, jar 활성)
Config Server 모듈 추가
/config-server/build.gradle, /config-server/Dockerfile, /config-server/src/main/java/.../ConfigServerApplication.java, /config-server/src/main/resources/application.yml, /config-server/src/main/resources/application-docker.yml
Spring Cloud Config Server 애플리케이션 추가, 네이티브 프로필 구성, 도커 멀티스테이지 빌드 및 런타임 이미지/비루트 사용자 설정
중앙 설정 리포지토리(서비스별 설정)
/config-server/src/main/resources/config/api-gateway.yml, /config-server/src/main/resources/config/user-service.yml, /config-server/src/main/resources/config/order-service.yml
게이트웨이 라우팅/서킷브레이커/타임리미터 설정, 각 서비스의 MySQL/Eureka/로그 레벨 및 앱별 설정 추가
API Gateway 기능 추가
/api-gateway/build.gradle, /api-gateway/src/main/java/com/example/gateway/FallbackController.java, /api-gateway/src/main/resources/application.yml
Config Client, Resilience4j, Actuator 의존성 추가, 서킷 오픈 시 폴백 엔드포인트(/fallback/*) 제공, Config Server 임포트 구성
User Service 구성 변경
/user-service/build.gradle, /user-service/src/main/resources/application.yml, /user-service/src/main/resources/application-docker.yml
Config Client 추가, H2 → MySQL 드라이버로 교체, spring.config.import 추가, Docker 프로필에서 H2 설정 제거 및 ddl-auto 업데이트
Order Service 구성 변경
/order-service/build.gradle, /order-service/src/main/resources/application.yml, /order-service/src/main/resources/application-docker.yml
Config Client 추가, H2 → MySQL 드라이버로 교체, spring.config.import 추가, Docker 프로필에서 H2 설정 제거 및 ddl-auto 업데이트
컨테이너 오케스트레이션
/docker-compose.yml, /.env.example
MySQL(user/order) 서비스 추가와 볼륨/헬스체크, Config Server 서비스 정의, 각 서비스에 configserver 임포트/의존 조건 설정, 예시 환경변수 추가

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant A as Service (User/Order/API GW)
  participant C as Config Server
  participant S as Local Config (application.yml)

  A->>S: 부트 시 로컬 설정 로드
  A->>C: spring.config.import로 원격 설정 조회
  alt Config Server 응답 성공
    C-->>A: 외부 설정 병합
    A->>A: 환경 구성 완료
  else Config Server 미가용 (optional)
    A->>A: 로컬 설정만으로 기동
  end
Loading
sequenceDiagram
  autonumber
  participant Client as Client
  participant GW as API Gateway
  participant US as User Service
  participant OS as Order Service

  rect rgba(200,235,255,0.25)
    note over GW: Resilience4j Circuit Breaker
    Client->>GW: /api/users/** 요청
    GW->>US: 프록시 호출
    alt 성공
      US-->>GW: 2xx 응답
      GW-->>Client: 응답 전달
    else 실패/지연 또는 임계치 초과
      GW->>GW: Circuit OPEN
      GW-->>Client: /fallback/user-service 503 응답
    end
  end

  rect rgba(200,255,200,0.25)
    Client->>GW: /api/orders/** 요청
    GW->>OS: 프록시 호출
    alt 성공
      OS-->>GW: 2xx 응답
      GW-->>Client: 응답 전달
    else 실패/지연 또는 임계치 초과
      GW->>GW: Circuit OPEN
      GW-->>Client: /fallback/order-service 503 응답
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

깡총, 설정 바구니 한가득 들고
게이트 앞 서킷은 톡—열렸다 닫히고
폴백 길 따라 503 바람이 분다
토끼는 두 개의 강—user와 order를 건너
각자 DB에 당근 씨를 심는다 🍃🥕
바람결에 속삭인다: 중앙의 숲, 평안하라!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning 휴대 개발 환경용 .idea 설정 파일 변경과 Lombok 버전 고정, common 모듈의 bootJar/jar 설정 조정 등은 이슈 #7의 핵심 목표인 Config Server 구현, 데이터베이스 분리, Circuit Breaker 및 Docker Compose 업데이트와 직접적인 관련이 없으므로 범위를 벗어납니다. 이러한 변경은 별도의 PR로 분리하거나 제거하는 것이 적절합니다. IDE 설정 파일과 라이브러리 버전 고정 관련 변경을 별도의 PR로 분리하고 해당 파일을 복원 또는 삭제하여 이슈 범위에 집중하도록 수정하세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목은 Config Server 추가, 서비스별 데이터베이스 분리 및 Circuit Breaker 구현이라는 주요 변경 사항을 명확하게 요약하고 있습니다. 따라서 동료가 변경의 핵심을 빠르게 이해할 수 있어 요건을 충족합니다.
Linked Issues Check ✅ Passed 이번 PR은 중앙 설정 관리 서버 추가, 서비스별 MySQL 데이터베이스 구성, API Gateway에 Resilience4j Circuit Breaker와 FallbackController 구현, spring.config.import 적용 및 Docker Compose 파일 업데이트 등 이슈 #7의 모든 코딩 목표를 충족하고 있습니다. 구체적인 코드 및 설정 변경이 링크된 요구 사항과 일치하므로 추가 조치 없이 요건이 완전히 반영되었습니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

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

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

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)

92-110: 치명적: order-service가 mysql-order에 의존하지 않음

order-service는 MySQL orderdb를 사용한다고 설정되어 있지만(라인 100의 SPRING_CONFIG_IMPORT 참조), depends_onmysql-order가 없습니다. 이로 인해 MySQL이 준비되기 전에 order-service가 시작되어 연결 실패가 발생할 수 있습니다.

다음 diff를 적용하세요:

   order-service:
     build:
       context: .
       dockerfile: order-service/Dockerfile
     ports:
       - "8082:8082"
     environment:
       - SPRING_PROFILES_ACTIVE=docker
       - SPRING_CONFIG_IMPORT=optional:configserver:http://config-server:8888
       - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka/
+      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql-order:3306/orderdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
+      - SPRING_DATASOURCE_USERNAME=user
+      - SPRING_DATASOURCE_PASSWORD=password
     depends_on:
+      mysql-order:
+        condition: service_healthy
       eureka-server:
         condition: service_started
       config-server:
         condition: service_started
       user-service:
         condition: service_started

참고: user-service처럼 MySQL 환경변수도 추가해야 합니다 (config 파일의 H2 설정을 오버라이드하기 위해).

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

35-36: Lombok 버전 명시가 올바르게 적용되었습니다.

Lombok 1.18.30은 Java 21과 호환되며 모든 서브프로젝트에 일관된 버전이 적용되어 재현 가능한 빌드를 보장합니다.

더 최신 Lombok 버전(예: 1.18.34+)으로 업그레이드를 고려할 수 있지만, 현재 버전도 안정적으로 작동합니다.

config-server/src/main/java/com/example/configserver/ConfigServerApplication.java (1)

7-12: Config Server 애플리케이션이 올바르게 구성되었습니다.

@EnableConfigServer 어노테이션과 표준 Spring Boot 구조가 정확하게 적용되었습니다.

프로덕션 배포 시에는 Config Server 엔드포인트에 인증/인가를 추가하는 것을 권장합니다(예: Spring Security 기본 인증 또는 암호화된 설정 사용).

config-server/src/main/resources/config/api-gateway.yml (1)

45-66: Circuit Breaker 설정이 잘 구성되었습니다.

Resilience4j 설정이 전반적으로 적절하며 서비스별 Circuit Breaker 인스턴스가 올바르게 정의되었습니다.

다음 사항을 고려해보시기 바랍니다:

  • slowCallDurationThreshold: 2stimeoutDuration: 3s의 관계: 2~3초 사이의 호출은 "느린 호출"로 집계되지만 타임아웃은 발생하지 않습니다. 이 값들을 더 명확하게 조정하거나(예: slowCallDurationThreshold를 1s로 낮추기) 의도를 문서화하는 것을 권장합니다.
  • 프로덕션 환경에서는 DEBUG 로깅 레벨을 INFO 또는 WARN으로 조정하세요.
config-server/Dockerfile (2)

25-25: JAR 파일 복사 시 와일드카드 사용 위험

*.jar 와일드카드는 여러 JAR 파일이 존재할 경우 예상치 못한 결과를 초래할 수 있습니다. 명시적인 파일명을 사용하는 것이 더 안전합니다.

다음과 같이 명시적으로 변경하세요:

-COPY --from=builder /app/config-server/build/libs/*.jar app.jar
+COPY --from=builder /app/config-server/build/libs/config-server-*.jar app.jar

또는 bootJar 태스크에서 고정된 이름을 사용하도록 build.gradle에서 설정:

// config-server/build.gradle
bootJar {
    archiveFileName = 'config-server.jar'
}

28-28: JVM 최적화 옵션 추가 권장

Config Server는 여러 서비스의 중심이 되므로 JVM 메모리 설정과 컨테이너 환경 최적화가 필요합니다.

다음과 같이 JVM 옵션을 추가하세요:

-ENTRYPOINT ["java", "-jar", "app.jar"]
+ENTRYPOINT ["java", \
+    "-XX:+UseContainerSupport", \
+    "-XX:MaxRAMPercentage=75.0", \
+    "-Djava.security.egd=file:/dev/./urandom", \
+    "-jar", "app.jar"]

설명:

  • UseContainerSupport: 컨테이너 메모리 제한 인식
  • MaxRAMPercentage=75.0: 컨테이너 메모리의 75% 사용
  • java.security.egd: 빠른 난수 생성 (시작 시간 개선)
api-gateway/src/main/java/com/example/gateway/FallbackController.java (3)

9-9: 타임스탬프에 LocalDateTime 대신 Instant 사용 권장

LocalDateTime은 타임존 정보가 없어 분산 시스템에서 문제를 일으킬 수 있습니다. Instant 또는 OffsetDateTime을 사용하는 것이 좋습니다.

다음과 같이 변경하세요:

-import java.time.LocalDateTime;
+import java.time.Instant;

 // 그리고 createFallbackResponse 메서드에서:
-response.put("timestamp", LocalDateTime.now());
+response.put("timestamp", Instant.now());

이렇게 하면 ISO-8601 UTC 형식으로 직렬화되어 타임존 문제를 방지할 수 있습니다.


25-34: 타입 안전성: DTO 클래스 사용 권장

Map<String, Object>는 타입 안전하지 않으며 컴파일 타임 검증이 불가능합니다. 전용 DTO 클래스를 사용하는 것이 좋습니다.

다음과 같이 DTO를 생성할 수 있습니다:

// FallbackResponse.java
public record FallbackResponse(
    String status,
    String message,
    Instant timestamp,
    String service
) {
    public static FallbackResponse of(String serviceName, String message) {
        return new FallbackResponse(
            "SERVICE_UNAVAILABLE",
            message,
            Instant.now(),
            serviceName
        );
    }
}

// FallbackController.java에서:
public ResponseEntity<FallbackResponse> userServiceFallback() {
    return ResponseEntity
        .status(HttpStatus.SERVICE_UNAVAILABLE)
        .body(FallbackResponse.of("user-service", "..."));
}

Java 17+ record를 사용하면 불변성과 타입 안전성을 동시에 확보할 수 있습니다.


28-28: 국제화(i18n) 고려 필요

메시지가 한국어로 하드코딩되어 있어 다국어 지원이 어렵습니다. 향후 글로벌 서비스 확장을 고려한다면 메시지 외부화를 권장합니다.

Spring의 MessageSource를 사용할 수 있습니다:

// messages.properties
fallback.user.service=User 서비스가 일시적으로 사용 불가능합니다. 잠시  다시 시도해주세요.
fallback.order.service=Order 서비스가 일시적으로 사용 불가능합니다. 잠시  다시 시도해주세요.

// FallbackController.java
@Autowired
private MessageSource messageSource;

private String getMessage(String key) {
    return messageSource.getMessage(key, null, LocaleContextHolder.getLocale());
}
docker-compose.yml (2)

4-140: 리소스 제한 미정의

컨테이너에 대한 CPU 및 메모리 제한이 설정되지 않아 한 서비스가 모든 리소스를 소비할 수 있습니다. 이는 프로덕션 환경에서 안정성 문제를 일으킬 수 있습니다.

각 서비스에 리소스 제한을 추가하세요:

# 예시: user-service
  user-service:
    # ... 기존 설정 ...
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

권장 설정:

  • MySQL: 512M-1G 메모리, 1-2 CPU
  • Config Server: 256M-512M 메모리, 0.5-1 CPU
  • Eureka Server: 256M-512M 메모리, 0.5-1 CPU
  • 마이크로서비스: 256M-512M 메모리, 0.5-1 CPU
  • API Gateway: 512M-1G 메모리, 1-2 CPU (더 많은 트래픽 처리)

134-136: 네트워크 보안 설정 개선 권장

bridge 드라이버를 사용하지만 추가 보안 설정이 없습니다. 내부 통신만 허용하도록 네트워크를 격리하는 것이 좋습니다.

다음과 같이 네트워크 설정을 개선할 수 있습니다:

 networks:
   msa-network:
     driver: bridge
+    internal: false  # 외부 접근 필요 시 false, 순수 내부 통신만 허용 시 true
+    ipam:
+      config:
+        - subnet: 172.28.0.0/16

또는 민감한 서비스(예: MySQL)를 별도의 내부 네트워크로 분리:

networks:
  msa-network:
    driver: bridge
  db-network:
    driver: bridge
    internal: true  # 외부 접근 차단

services:
  mysql-user:
    networks:
      - db-network
  user-service:
    networks:
      - msa-network
      - db-network
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adb5cd7 and a9d03e4.

📒 Files selected for processing (21)
  • .idea/compiler.xml (2 hunks)
  • .idea/gradle.xml (1 hunks)
  • api-gateway/build.gradle (1 hunks)
  • api-gateway/src/main/java/com/example/gateway/FallbackController.java (1 hunks)
  • api-gateway/src/main/resources/application.yml (1 hunks)
  • build.gradle (1 hunks)
  • common/build.gradle (1 hunks)
  • config-server/Dockerfile (1 hunks)
  • config-server/build.gradle (1 hunks)
  • config-server/src/main/java/com/example/configserver/ConfigServerApplication.java (1 hunks)
  • config-server/src/main/resources/application-docker.yml (1 hunks)
  • config-server/src/main/resources/application.yml (1 hunks)
  • config-server/src/main/resources/config/api-gateway.yml (1 hunks)
  • config-server/src/main/resources/config/order-service.yml (1 hunks)
  • config-server/src/main/resources/config/user-service.yml (1 hunks)
  • docker-compose.yml (5 hunks)
  • order-service/build.gradle (1 hunks)
  • order-service/src/main/resources/application.yml (1 hunks)
  • settings.gradle (1 hunks)
  • user-service/build.gradle (1 hunks)
  • user-service/src/main/resources/application.yml (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/build.gradle

⚙️ CodeRabbit configuration file

**/build.gradle: Review Gradle configuration for:

  1. Dependency management best practices
  2. Build optimization opportunities
  3. Plugin usage efficiency

Files:

  • build.gradle
  • user-service/build.gradle
  • api-gateway/build.gradle
  • common/build.gradle
  • config-server/build.gradle
  • order-service/build.gradle
**/*.java

⚙️ CodeRabbit configuration file

**/*.java: Review this Java code for:

  1. Spring Boot best practices
  2. Clean code principles
  3. Performance optimizations
  4. Security considerations
  5. Suggest more elegant solutions using Java features
  6. Check for proper exception handling
  7. Suggest better naming conventions

Files:

  • api-gateway/src/main/java/com/example/gateway/FallbackController.java
  • config-server/src/main/java/com/example/configserver/ConfigServerApplication.java
🔇 Additional comments (9)
.idea/gradle.xml (1)

3-3: LGTM!

IntelliJ IDEA의 Gradle 마이그레이션 설정과 config-server 모듈 추가가 올바르게 반영되었습니다.

Also applies to: 15-15

settings.gradle (1)

7-8: LGTM!

config-server 모듈이 멀티 프로젝트 빌드에 올바르게 추가되었습니다.

.idea/compiler.xml (1)

5-5: LGTM!

어노테이션 프로세싱 프로파일 설정과 config-server 모듈이 올바르게 구성되었습니다. Lombok 및 Spring 어노테이션 처리가 정상적으로 작동할 것입니다.

Also applies to: 14-14

common/build.gradle (1)

11-18: LGTM!

common 모듈을 라이브러리로 올바르게 구성했습니다. bootJar 비활성화와 jar 활성화는 Spring Boot 멀티 프로젝트 빌드의 모범 사례입니다.

api-gateway/build.gradle (1)

8-10: LGTM!

Config Client, Circuit Breaker(Resilience4j), Actuator 의존성이 PR 목표와 일치하게 올바르게 추가되었습니다. 반응형 게이트웨이에 적합한 reactor 기반 Circuit Breaker를 선택했습니다.

config-server/src/main/resources/config/api-gateway.yml (1)

9-30: 게이트웨이 라우팅 설정이 올바르게 구성되었습니다.

Eureka 기반 로드 밸런싱(lb://), Circuit Breaker 필터, 경로 재작성이 정확하게 설정되었습니다. Fallback URI가 적절하게 지정되어 있어 Circuit Breaker OPEN 상태에서 올바른 폴백 응답을 제공할 것입니다.

config-server/src/main/resources/config/user-service.yml (2)

27-27: docker-compose.yml에서 Eureka URL 오버라이드 확인됨
docker-compose.yml에 EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE 환경 변수가 http://eureka-server:8761/eureka/로 설정돼 Docker 환경에서 defaultZone이 올바르게 오버라이드됩니다.


35-39: app.user 속성 사용 여부 확인 필요
config-server 내에서 app.user.default-role·app.user.max-login-attempts가 코드에 참조되지 않습니다. 실제 user-service 애플리케이션에서 해당 설정이 사용되는지 검증하고, 불필요하다면 제거해 주세요.

config-server/src/main/resources/config/order-service.yml (1)

32-36: app.order 프로퍼티 미사용 확인: 제거 또는 바인딩 필요

  • max-order-amountdelivery-fee가 코드에서 참조되지 않습니다. 실제 사용 여부를 재확인 후, 미사용 시 설정을 제거하거나 사용 시 @ConfigurationProperties 바인딩을 추가하세요.
  • 프로퍼티 이름에 통화 단위(-krw 등)를 명시하도록 수정하세요.

Comment on lines +12 to +13
ports:
- "3306:3306"
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

포트 충돌 위험: 호스트 포트 3306 사용

mysql-user가 호스트 포트 3306을 사용하면 로컬에 이미 MySQL이 실행 중인 경우 충돌이 발생합니다.

다음과 같이 다른 포트를 사용하는 것을 권장합니다:

     ports:
-      - "3306:3306"
+      - "3316:3306"

그리고 user-service의 JDBC URL도 업데이트:

-      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql-user:3306/userdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
+      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql-user:3306/userdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC

참고: 컨테이너 간 통신은 여전히 3306 포트를 사용하므로, 환경변수는 변경하지 않아도 됩니다.

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

🤖 Prompt for AI Agents
In docker-compose.yml around lines 12-13, the service maps host port 3306 which
can conflict with a local MySQL instance; change the host side of the port
mapping to an unused port (e.g., "3307:3306") and then update the user-service
JDBC URL/config that references localhost:3306 to use the new host port
(localhost:3307) so host-based connections work; leave container-internal ports
as 3306 so inter-container communication is unchanged.

- Config Server에 Actuator 헬스체크 구현 (interval: 30s, start_period: 60s)
- docker-compose에서 config-server의 depends_on을 service_healthy로 변경하여 안정적인 시작 보장
- Config Server Dockerfile에 curl 설치 (헬스체크용)
- 데이터베이스 설정을 H2에서 MySQL로 통합 (Database per Service 패턴)
- docker-compose에 환경변수 사용으로 보안 강화 (.env.example 추가)
- FallbackController 리팩토링 및 로깅 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
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: 2

♻️ Duplicate comments (1)
config-server/src/main/resources/config/user-service.yml (1)

6-9: DB 자격 증명은 환경 변수로 위임해야 합니다.

Config 저장소에 평문 비밀번호를 커밋하면 즉시 유출 위험이며, 이전 리뷰에서 안내드린 환경 변수 위임도 아직 반영되지 않았습니다. 도커 컴포즈가 주입하는 값을 사용하도록 플레이스홀더를 적용해 주세요.

-    url: jdbc:mysql://mysql-user:3306/userdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
+    url: ${SPRING_DATASOURCE_URL:jdbc:mysql://mysql-user:3306/userdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC}
     driverClassName: com.mysql.cj.jdbc.Driver
-    username: user
-    password: password
+    username: ${SPRING_DATASOURCE_USERNAME:user}
+    password: ${SPRING_DATASOURCE_PASSWORD:password}
🧹 Nitpick comments (1)
config-server/src/main/resources/config/user-service.yml (1)

11-18: 프로덕션에서는 자동 스키마 갱신을 비활성화하세요.

ddl-auto: update는 런타임에 스키마를 변경해 버그·데이터 손실을 야기할 수 있고, show-sql/format_sql은 민감 쿼리를 로그에 남깁니다. 마이그레이션 도구로 스키마를 관리하고, 런타임에는 검증만 하도록 조정하는 편이 안전합니다.

-      ddl-auto: update
-    show-sql: true
+      ddl-auto: validate
+    show-sql: false
         dialect: org.hibernate.dialect.MySQLDialect
-        format_sql: true
+        format_sql: false
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9d03e4 and baea25e.

📒 Files selected for processing (11)
  • .env.example (1 hunks)
  • api-gateway/src/main/java/com/example/gateway/FallbackController.java (1 hunks)
  • config-server/Dockerfile (1 hunks)
  • config-server/build.gradle (1 hunks)
  • config-server/src/main/resources/application-docker.yml (1 hunks)
  • config-server/src/main/resources/application.yml (1 hunks)
  • config-server/src/main/resources/config/order-service.yml (1 hunks)
  • config-server/src/main/resources/config/user-service.yml (1 hunks)
  • docker-compose.yml (4 hunks)
  • order-service/build.gradle (1 hunks)
  • user-service/build.gradle (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • order-service/build.gradle
  • user-service/build.gradle
  • config-server/build.gradle
  • config-server/src/main/resources/application-docker.yml
  • config-server/src/main/resources/application.yml
  • docker-compose.yml
  • api-gateway/src/main/java/com/example/gateway/FallbackController.java
🔇 Additional comments (1)
.env.example (1)

1-11: 환경 변수 템플릿이 명확합니다.

배포 전 교체 지침과 강한 비밀번호 권장 사항이 잘 정리되어 있어요.

Circuit Breaker, Fallback 패턴에 대한 상세 가이드 작성
- Circuit Breaker 3가지 상태(CLOSED/OPEN/HALF_OPEN) 설명
- Fallback forward: 방식의 동작 원리 다이어그램
- Config Server import 방식 설정 구조 설명
- 실제 테스트 방법 및 명령어
- 로그 분석 가이드
- 트러블슈팅 섹션

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
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 (4)
order-service/src/main/resources/application-docker.yml (1)

6-6: 운영/스테이징에서 ddl-auto: update는 위험합니다 — 마이그레이션 도구 전환 권장

런타임 스키마 변경(예상치 못한 DDL, 데이터 손실 위험)을 유발할 수 있습니다. Docker 프로필이 배포 환경에서 쓰일 가능성을 고려해 운영 계열 프로필에서는 validate(또는 none)로 전환하고, 스키마 관리는 Flyway/Liquibase로 일원화하는 것을 권장합니다. 초기 테이블 생성은 마이그레이션이나 DB init 스크립트로 처리해 주세요. 또한 이 파일에 datasource 설정이 없으므로 Config Server/환경변수로 공급되는지 확인 부탁드립니다.

적용 예:

-      ddl-auto: update
+      ddl-auto: validate

확인 요청:

  • 이 docker 프로필이 어느 환경(dev/stage/prod)에서 활성화되는지?
  • 해당 프로필 활성 시에도 spring.config.import(Config Server)가 병합되어 datasource/url/계정이 정상 주입되는지?
user-service/src/main/resources/application-docker.yml (3)

6-6: ddl-auto: update는 개발 한정 권장. 마이그레이션 도입/검증 모드 전환 고려 바랍니다.

운영/장기 실행 환경에서 스키마 자동 변경은 리스크가 큽니다. Flyway/Liquibase로 이관하고, 애플리케이션에서는 validate(또는 제거)를 권장합니다. 최소한 docker 프로필이 dev 전용인지 확인해 주세요.

예시 변경:

-      ddl-auto: update
+      ddl-auto: validate

12-18: Eureka 등록 값 정합성: prefer-ip-address와 hostname 동시 설정.

prefer-ip-address: true이면 IP로 등록되어 hostname은 무시됩니다. 의도대로라면 둘 중 하나만 사용해 혼동을 줄이세요.

예:

  • IP로 등록: 유지(현재 그대로)하고 hostname 제거
  • 호스트명으로 등록: prefer-ip-address: false로 변경

7-7: show-sql: true는 로그 소음/민감정보 노출 우려.

dev에서만 활성화하거나 로깅 레벨로 제어하세요.

예:

  • docker(dev) 프로필에서만 유지, 기타 프로필은 false
  • 또는 org.hibernate.SQL 로거 레벨로 제어
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between baea25e and eef3011.

⛔ Files ignored due to path filters (1)
  • docs/resilience4j-patterns.md is excluded by !**/*.md, !**/docs/**
📒 Files selected for processing (4)
  • docker-compose.yml (4 hunks)
  • order-service/src/main/resources/application-docker.yml (1 hunks)
  • user-service/build.gradle (1 hunks)
  • user-service/src/main/resources/application-docker.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • user-service/build.gradle
  • docker-compose.yml
🔇 Additional comments (1)
user-service/src/main/resources/application-docker.yml (1)

1-18: docker 프로필 spring.config.import 및 datasource env 변수 설정 확인

  • docker-compose.yml에서 SPRING_CONFIG_IMPORT 환경 변수로 Config Server import가 설정되어 있습니다.
  • 동일 파일에서 SPRING_DATASOURCE_URL/USERNAME/PASSWORD/DRIVER_CLASS_NAME 환경 변수가 제공됩니다.
  • 환경 변수는 Config Data보다 우선 적용되므로 주입 우선순위가 의도대로 동작함을 확인했습니다.

두 가지 목적의 문서로 분리:
- resilience4j-patterns.md: 구현 가이드 (589줄 → 394줄 간소화)
- Circuit-Breaker-QNA.md: 면접 대비 Q&A (신규 추가)

[resilience4j-patterns.md 개선]
- 불필요한 트러블슈팅 섹션 제거
- 구현되지 않은 Retry 패턴 설명 제거
- 핵심 내용만 유지 (Circuit Breaker 상태, Fallback, 설정, 테스트)

[Circuit-Breaker-QNA.md 추가]
- 실무 경험 중심의 Q&A 10개
- 면접에서 자주 묻는 질문 정리
- 실제 테스트 결과 및 로그 분석
- 개선 방안 제시

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@yesrin yesrin merged commit e0ad7a6 into main Oct 11, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Config Server, Database per Service, Circuit Breaker 구현

2 participants