Skip to content

Conversation

@1winhyun
Copy link
Member

@1winhyun 1winhyun commented Sep 21, 2025

Related issue 🛠

작업 내용 💻

  • CI/CD를 구축했습니다.
  • Gateway를 구현하여 모든 요청이 gateway로 들어와 각 서비스로 요청을 보낼 수 있도록 구현했습니다.
  • Gateway-service를 Client로서 Eureka서버에 등록했습니다.

스크린샷 📷

local 서버

image

dev 서버

image

prod 서버

image image
  • 추가적으로 prod 서버의 경우 8761번 포트의 경우 https 적용이 되어있지 않습니다. 왜냐하면 gateway를 포함한 서비스들이 eureka server에 등록이 되지만 모든 요청은 gateway-service에 해당하는 8000번 포트로 받아 각 서비스로 보내지기 때문입니다. 따라서 https 처리는 8000번 포트에 이루어졌습니다.
    다음 사진은 해당 부분을 확인할 수 있는 nginx의 default.conf 코드입니다.
server {
    listen 80;
    server_name 43.200.160.0.nip.io;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
        allow all;
    }

    location /nginx/health {
        access_log off;
        return 200 'ok';
        add_header Content-Type text/plain;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    listen 443 ssl;
    http2 on;
    server_name 43.200.160.0.nip.io;

    ssl_certificate     /etc/letsencrypt/live/43.200.160.0.nip.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/43.200.160.0.nip.io/privkey.pem;

    # (옵션) mozilla 권장 설정을 쓰고 싶다면 아래 파일들이 있을 때 include
    # include /etc/letsencrypt/options-ssl-nginx.conf;
    # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    client_max_body_size 10m;

    location / {
        proxy_pass         http://gateway-service-prod:8000;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }

    location /nginx/health {
        access_log off;
        return 200 'ok';
        add_header Content-Type text/plain;
    }
}

아키텍처

최종적으로 구축한 prod 서버의 아키텍처는 다음과 같습니다.
image
image

같이 얘기해보고 싶은 내용이 있다면 작성 📢

Summary by CodeRabbit

  • New Features

    • 게이트웨이 서비스 도입: 요청 라우팅 및 /api-docs/backend/**를 통한 백엔드 API 문서 프록시.
    • Swagger UI 제공: /swagger-ui.html에서 API 문서 확인.
    • CORS 활성화: http://localhost:3000 허용, 표준 메서드/헤더 및 인증 정보 지원.
    • WebFlux 기반 전환 및 프로필별 설정(로컬/개발/운영)으로 포트 8000 사용.
  • Chores

    • CI 추가: 빌드 및 도커 이미지 빌드/푸시 자동화.
    • Dev/Prod CD 추가: CI 성공 시 원격 서버에 컨테이너 재배포 및 이미지 정리 자동화.
    • Dockerfile 추가.

@1winhyun 1winhyun self-assigned this Sep 21, 2025
@1winhyun 1winhyun added chore chore feature New feature or request labels Sep 21, 2025
@1winhyun 1winhyun linked an issue Sep 21, 2025 that may be closed by this pull request
2 tasks
Copy link
Member

@huncozyboy huncozyboy left a comment

Choose a reason for hiding this comment

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

고생하셨습니다 !

아키텍처 구조까지 시각화 해주셨네요 👍🏻

Comment on lines 10 to 32
@Configuration
@Profile({"local","dev","prod"})
public class GatewayConfiguration {

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 인증 필요 없는 라우트
.route("backend_route", r -> r.path("/**")
.filters(f -> f
.removeRequestHeader(HttpHeaders.COOKIE)
)
.uri("lb://backend-service"))

//스웨거를 위한 라우트 설정(각 서비스마다 등록해줘야 합니다.)
.route("backend-service_api_docs", r -> r.path("/api-docs/backend/**")
.filters(f -> f
.rewritePath("/api-docs/backend/(?<rem>.*)", "/${rem}")
)
.uri("lb://backend-service"))
.build();
}
}
Copy link
Member

Choose a reason for hiding this comment

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

해당 config 설정에서 /**로 와일드 카드를 사용해주신 이유는 모든 요청(/**)을 backend-service로 전달해주는 역할을 한다고 이해하면 될까요 ??

.removeRequestHeader(HttpHeaders.COOKIE)로 클라이언트가 보낸 쿠키를 백엔드 서비스로 전달하지 않는다고 이해했는데, 이건 인증이 끝난 요청에 대한 내용에 대해서 무상태를 유지해주는 설정인지도 궁금했습니다

Copy link
Member Author

Choose a reason for hiding this comment

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

첫번째 질문에 대해서는 모든 요청(/**)을 backend-service로 전달해주는 역할이 맞습니다. 하지만 현재 저희는 user와 관련된 서비스, 메일과 관련된 서비스가 추가될 예정이기에 추후 해당 부분은 수정될 예정입니다. 예를 들면 다음 코드와 같이 구현될 예정입니다.

.route("user_public_route", r -> r.path("/users/public/**")
				.filters(f -> f
					.removeRequestHeader(HttpHeaders.COOKIE)
				)
				.uri("lb://USER-SERVICE"))

두번째 질문의 경우 취지는 동일합니다. .removeRequestHeader(HttpHeaders.COOKIE)의 경우 게이트웨이 -> 백엔드로 쿠키를 넘기지 않아 해당 서비스들이 쿠키나 세션 기반 상태에 의존하지 못하도록 합니다. 따라서 인증의 관점에서는 토큰만 보고 요청을 처리하는 상태를 강제합니다.

@coderabbitai
Copy link

coderabbitai bot commented Sep 28, 2025

Walkthrough

gateway-service에 CI/CD(개발/운영) 워크플로와 Dockerfile을 추가하고, Spring WebFlux 및 Spring Cloud Gateway로 전환했습니다. CORS 필터와 라우팅 구성, Eureka 및 SpringDoc 설정을 환경별 yml로 추가하고 application.properties의 애플리케이션 이름을 제거했습니다.

Changes

Cohort / File(s) Summary
CI/CD 워크플로
.github/workflows/ci.yaml, .github/workflows/cd-dev.yaml, .../cd-prod.yaml
CI: dev 브랜치 푸시/PR/dispatch 트리거, JDK21 빌드, Docker 이미지 빌드·푸시. CD(dev/prod): workflow_run 성공 시 SSH로 원격 호스트 접속하여 기존 컨테이너 제거, docker compose pulldocker compose up --no-deps --force-recreate --pull always, 이미지 정리 실행.
Docker 빌드
Dockerfile
openjdk:21-jdk 기반, 빌드 산출물 JAR을 app.jar로 복사, JAVA_OPTS/PROFILE 사용하여 실행 엔트리포인트 정의.
빌드 설정(Gradle)
build.gradle
spring-boot-starter-web 및 webmvc gateway 의존 제거, spring-boot-starter-webfluxspring-cloud-starter-gateway 추가, springdoc-openapi-starter-webflux-ui:2.8.8 추가.
애플리케이션 부트스트랩
src/main/java/.../GatewayServiceApplication.java
@LoadBalanced WebClient.Builder 빈과 RestClient.Builder 빈 추가.
보안/CORS
src/main/java/.../global/SecurityConfig.java
CorsWebFilter 빈 추가: origin http://localhost:3000, 표준 메서드 허용, 크리덴셜 허용, 모든 헤더 허용, Authorization 및 refresh 헤더 노출.
Gateway 라우팅
src/main/java/.../global/gateway/GatewayConfiguration.java
RouteLocator 빈 추가(프로필: local/dev/prod): /back 등 라우트들을 backend-service로 포워딩하고 일부 경로는 리라이트, COOKIE 헤더 제거 규칙 포함.
환경 설정
src/main/resources/application-local.yml, .../application-dev.yml, .../application-prod.yml
포트 8000, reactive(WebFlux) 설정, 애플리케이션 이름, 환경별 Eureka 서버 URL, SpringDoc/Swagger UI 경로 및 backend API-docs 매핑 추가.
기본 프로퍼티 정리
src/main/resources/application.properties
spring.application.name=gateway_service 설정 제거.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as 개발자
  participant GH as GitHub
  participant CI as CI 런너
  participant Reg as Container Registry
  participant CD as CD 워크플로
  participant SSH as 원격 호스트
  participant DK as Docker/Compose

  Dev->>GH: push/PR to dev 또는 workflow_dispatch
  GH-->>CI: "gateway-service CI pipeline" 트리거
  CI->>CI: 체크아웃, JDK21 설정, gradle 빌드
  CI->>Reg: Docker 이미지 빌드 및 푸시
  CI-->>GH: CI 완료(success)

  GH-->>CD: workflow_run (on: workflow_run success)
  CD->>SSH: SSH 연결 (appleboy/ssh-action)
  SSH->>DK: 기존 컨테이너 제거 (무시 가능한 에러)
  SSH->>DK: docker compose pull
  SSH->>DK: docker compose up --no-deps --force-recreate --pull always
  SSH->>DK: docker image prune
Loading
sequenceDiagram
  autonumber
  actor Client as 클라이언트
  participant G as Gateway (Spring Cloud Gateway)
  participant E as Eureka
  participant B as backend-service

  Client->>G: 요청 (/... 또는 /api-docs/backend/...)
  G->>E: 서비스 조회(backend-service)
  E-->>G: 인스턴스 정보 반환
  alt API Docs 경로
    G->>G: 경로 재작성 (/api-docs/backend/** -> /**)
  end
  G->>B: 요청 전달 (일반 경로에서 COOKIE 헤더 제거)
  B-->>G: 응답
  G-->>Client: 응답 반환
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

새벽 배포에 깡총댄다, 토끼의 발자국 🥕
푸시 한 번에 CI가 반짝, 이미지가 날아오네.
SSH로 훌쩍 원격에 닿아 컨테이너를 갈아끼우고,
게이트는 WebFlux 바람에 길을 열어주네.
유레카 불빛 따라, 스웨거 지도도 펼쳐진다.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning build.gradle에서 Spring MVC에서 WebFlux 및 Swagger UI 의존성을 추가하고 application.yml에 API 문서 설정 및 CORS 필터(SecurityConfig) 구현 등 PR 목적에 명시되지 않은 기능이 포함되어 있어 이슈 범위를 벗어납니다. WebFlux 전환과 Swagger UI, CORS 설정 등은 별도 이슈 또는 PR로 분리하여 범위에 집중된 변경만 남기도록 수정이 필요합니다.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed PR 제목은 CI/CD 구축과 Netflix Eureka Client 기반 Gateway 설정이라는 주요 변경사항을 명확하게 요약하고 있어 핵심을 잘 반영합니다.
Linked Issues Check ✅ Passed PR 변경사항은 GitHub Actions 기반 CI 및 CD 워크플로우 구축과 Spring Cloud Netflix Eureka Client 및 Gateway 구성(구성 파일과 RouteLocator 빈 정의 포함)을 온전히 구현하여 연결된 이슈의 요구사항을 충족합니다.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#1

📜 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 0bc45eb and b92874b.

📒 Files selected for processing (2)
  • build.gradle (1 hunks)
  • src/main/java/com/unionmate/gateway_service/global/gateway/GatewayConfiguration.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/unionmate/gateway_service/global/gateway/GatewayConfiguration.java
  • build.gradle

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.

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc8ac16 and 0bc45eb.

📒 Files selected for processing (12)
  • .github/workflows/cd-dev.yaml (1 hunks)
  • .github/workflows/cd-prod.yaml (1 hunks)
  • .github/workflows/ci.yaml (1 hunks)
  • Dockerfile (1 hunks)
  • build.gradle (1 hunks)
  • src/main/java/com/unionmate/gateway_service/GatewayServiceApplication.java (2 hunks)
  • src/main/java/com/unionmate/gateway_service/global/SecurityConfig.java (1 hunks)
  • src/main/java/com/unionmate/gateway_service/global/gateway/GatewayConfiguration.java (1 hunks)
  • src/main/resources/application-dev.yml (1 hunks)
  • src/main/resources/application-local.yml (1 hunks)
  • src/main/resources/application-prod.yml (1 hunks)
  • src/main/resources/application.properties (0 hunks)
💤 Files with no reviewable changes (1)
  • src/main/resources/application.properties

@UnionMate UnionMate deleted a comment from coderabbitai bot Sep 29, 2025
@UnionMate UnionMate deleted a comment from coderabbitai bot Sep 29, 2025
@1winhyun 1winhyun merged commit 50b5d34 into dev Sep 30, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore chore feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] #1 CI/CD 구축 및 Netflix Eureka Client(Gateway) 설정

3 participants