Spring Cloud Gateway·Buildpack — 정문과 도시락 포장기

2026-05-02AWS SAA-C03 스터디

Spring Boot 3 핵심 정리 시리즈 11편. Spring Cloud Gateway로 마이크로서비스 앞단에 회사 정문 안내 데스크를 세우는 법, Maven/Gradle Plugin으로 빌드 자동화, Buildpack으로 Dockerfile 없이 컨테이너 이미지 만들기까지 — 라우팅·필터·자동 도시락 포장 비유로 친절하게 풀어쓴 11편.

📚 Spring Boot 3 핵심 정리 · 11편 / 14편 — 정문과 도시락 포장기

이 글은 Spring Boot 3 핵심 정리 시리즈의 열한 번째 편입니다. 10편까지는 한 애플리케이션 안에서 컨트롤러·리포지토리·클라이언트를 짜는 흐름이었어요. 이번 11편부터는 여러 애플리케이션을 묶는 인프라 단계로 한 칸 올라갑니다.

마이크로서비스로 앱을 쪼개면 자연스럽게 떠오르는 두 질문이 있어요. 첫째 — 클라이언트는 5개·10개의 서비스 주소를 다 알아야 하나? 둘째 — 이 많은 앱을 어떻게 일관되게 빌드·패키징·배포하나? 이 둘에 답해 주는 게 이번 글의 두 주연입니다 — Spring Cloud Gateway와 Build Tools(Maven/Gradle Plugin + Buildpack).

본문 흐름은 회사 비유를 따라 풀어 가요. Spring Cloud Gateway는 "회사 정문 안내 데스크" 입니다. 외부 손님이 회사를 찾아오면 정문 데스크가 부서 위치를 알려 주고 출입증을 발급해 주죠. 마이크로서비스 환경에서 클라이언트가 게이트웨이를 거쳐 백엔드로 흘러가는 게 정확히 이 그림이에요. 그리고 Buildpack은 "자동 도시락 포장기" — 재료(코드 + 의존성)만 넣으면 자동으로 균일한 도시락(컨테이너 이미지)을 싸 줍니다.

왜 Cloud Gateway·Build Tools가 처음엔 어렵게 느껴질까요

이유는 네 가지예요.

첫째, 마이크로서비스를 안 해 본 사람은 게이트웨이가 왜 따로 있어야 하는지가 안 보입니다. 단일 앱일 땐 클라이언트가 그냥 8080 포트로 호출하면 되니까요. 게이트웨이는 "여러 앱이 섞일 때" 진가를 보여 주는 부품이라 입문 단계엔 추상적으로 느껴져요.

둘째, Predicate·Filter·Route라는 단어가 한꺼번에 나옵니다. Spring Cloud Gateway 문서를 펼치면 이 셋이 줄지어 등장하는데, 각자 무슨 일을 하고 어떻게 조합되는지 한 번에 안 잡혀요.

셋째, Maven 플러그인과 Gradle 플러그인이 비슷한데 다릅니다. 같은 일(빌드)을 다른 방식(XML vs Groovy/Kotlin)으로 적어서 — 한쪽에 익숙해진 눈으로 다른 쪽을 보면 어색해요.

넷째, Buildpack이 "Dockerfile 없는 컨테이너 빌드"인데, 그게 어떻게 가능한지가 안 보여요. Dockerfile 없이 어떻게 베이스 이미지를 정하고 레이어를 쌓을까? 처음엔 마법처럼 느껴집니다.

해결법은 한 가지예요. Cloud Gateway = "회사 정문 안내 데스크" / Buildpack = "자동 도시락 포장기" 로 잡으면 갑자기 명확해집니다. 안내 데스크는 손님(요청)을 적절한 부서(서비스)로 안내하면서 출입증(인증·로깅)도 발급해 주고, 도시락 포장기는 재료(소스 코드)를 넣으면 어떤 도시락통(베이스 이미지)·뚜껑(JVM)·라벨(메타데이터)을 자동으로 골라서 균일한 도시락을 싸 줘요. 이 글은 그 비유를 따라 풀어 갑니다.

Spring Cloud Gateway — 회사 정문 안내 데스크

마이크로서비스가 5개·10개로 늘어나면 클라이언트가 모든 서비스 주소를 알 수가 없어요. 또 인증·로깅·rate limit 같은 공통 처리를 모든 서비스에 따로 박는 것도 비효율이고요. Spring Cloud Gateway는 이 모든 요청을 한 군데에서 받아 백엔드로 라우팅·필터링하는 단일 진입점입니다.

회사 비유로 — 본관에 부서가 30개 흩어져 있다고 칩시다. 손님이 매번 30개 부서 위치를 외워서 직접 찾아갈 순 없죠. 그래서 정문에 안내 데스크가 있어요. 손님이 "회계부 가려고요" 하면 안내 데스크가 위치를 알려 주고, 출입증 발급·신원 확인·방문 기록까지 처리합니다. 게이트웨이가 정확히 이 역할이에요.

핵심 구성 요소 세 가지

구성 요소역할
Route"이 패턴 요청은 저 서비스로" 매핑 단위
Predicate요청이 라우트와 일치하는지 판단 (경로·헤더·메서드 등)
Filter매칭된 요청을 가공 (헤더 추가·경로 재작성·인증 등)

요청이 들어오면 게이트웨이가 Predicate로 어느 Route에 해당하는지 판단하고, 매칭되면 Filter 체인을 거쳐 백엔드 서비스로 전달돼요.

의존성 — WebFlux 기반

Spring Cloud Gateway는 WebFlux 위에서 동작합니다. 그래서 같은 앱에 Spring MVC와 같이 쓰면 충돌해요 — 게이트웨이 전용 앱으로 따로 빼야 합니다.

<!-- spring-cloud-starter-gateway는 WebFlux를 가져옴 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!-- BOM으로 Spring Cloud 버전 관리 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2023.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

여기서 시험 함정이 하나 있어요. Spring Cloud Gateway는 spring-boot-starter-web(MVC)과 같이 쓰면 부팅이 안 됩니다. WebFlux와 MVC가 같은 컨텍스트에서 충돌해요. 게이트웨이는 항상 별도 앱으로.

YAML로 라우팅 선언

가장 흔한 패턴은 application.yml에 라우팅 규칙을 선언하는 방식이에요.

spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: http://localhost:8081
          predicates:
            - Path=/api/v3/product/**
          filters:
            - AddRequestHeader=X-Source, gateway

        - id: order-service
          uri: http://localhost:8082
          predicates:
            - Path=/api/v3/order/**
            - Method=GET,POST
          filters:
            - StripPrefix=2
            - AddResponseHeader=X-Powered-By, spring-gateway

        - id: legacy-redirect
          uri: http://legacy.example.com
          predicates:
            - Path=/old/**
          filters:
            - RewritePath=/old/(?<segment>.*), /v2/${segment}

읽는 흐름은 단순해요. predicates에 매칭 조건을 적고, 매칭되면 filters로 가공한 뒤 uri로 보내는 거죠.

Predicate 자주 쓰이는 8가지

Predicate매칭 조건
Path=/api/**경로 패턴 매칭
Method=GET,POSTHTTP 메서드
Header=X-Request-Id, \\d+헤더 이름 + 정규식
Query=foo, ba.쿼리 파라미터 + 정규식
Host=*.example.com호스트 헤더
Cookie=session, ^abc쿠키 이름 + 정규식
After=2026-01-01T00:00:00+09:00[Asia/Seoul]특정 시각 이후
RemoteAddr=192.168.0.0/16클라이언트 IP 대역

여러 Predicate를 한 Route에 넣으면 AND 조건이에요. 즉, 모두 매칭돼야 그 Route로 흘러갑니다.

Filter 자주 쓰이는 패턴

게이트웨이 필터는 둘로 나뉘어요 — Pre-Filter(요청을 백엔드로 보내기 전)와 Post-Filter(응답을 클라이언트로 돌려주기 전).

Filter역할
AddRequestHeader=X-Source, gateway요청에 헤더 추가
AddResponseHeader=...응답에 헤더 추가
StripPrefix=N경로 앞 N개 세그먼트 제거
PrefixPath=/api/v1경로 앞에 prefix 붙이기
RewritePath=...경로를 정규식으로 다시 작성
Retry=35xx 응답에 재시도
RequestRateLimiter=...rate limit
CircuitBreaker=...서킷 브레이커

여기서 시험 함정이 하나 있어요. StripPrefix=N은 경로의 앞 N개 세그먼트를 제거합니다. /api/v3/product/123을 백엔드에 그냥 /product/123으로 보내고 싶으면 StripPrefix=2. 자주 헷갈려서 라우팅이 깨지는 1순위 함정이에요.

자바 DSL로 라우팅

YAML이 아닌 자바 코드로 라우팅을 정의할 수도 있어요. 동적 조건이 있을 때 유리합니다.

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("product-service", r -> r
                        .path("/api/v3/product/**")
                        .filters(f -> f.addRequestHeader("X-Source", "gateway"))
                        .uri("http://localhost:8081"))
                .route("order-service", r -> r
                        .path("/api/v3/order/**")
                        .and()
                        .method(HttpMethod.GET, HttpMethod.POST)
                        .filters(f -> f
                                .stripPrefix(2)
                                .addResponseHeader("X-Powered-By", "spring-gateway"))
                        .uri("http://localhost:8082"))
                .build();
    }
}

자바 DSL은 IDE 자동완성과 컴파일 타임 검증이 가능해서, 라우팅이 복잡할 때 유지보수가 더 편해요.

인증·로깅·서킷 브레이커 — 횡단 관심사 한 곳에

게이트웨이 진가는 횡단 관심사(cross-cutting concerns)를 한 군데에 모으는 데 있어요. 인증·로깅·rate limit·재시도·서킷 브레이커를 모든 마이크로서비스에 따로 박지 않고, 게이트웨이에 한 번만 박으면 끝입니다.

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=X-Gateway-Trace, ${random.uuid}
        - AddResponseHeader=X-Server, gateway
      routes:
        - id: protected-api
          uri: http://localhost:8081
          predicates:
            - Path=/api/v3/**
          filters:
            - name: CircuitBreaker
              args:
                name: backendCircuitBreaker
                fallbackUri: forward:/fallback
            - name: Retry
              args:
                retries: 3
                statuses: BAD_GATEWAY,SERVICE_UNAVAILABLE
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20

default-filters모든 Route에 자동 적용되는 필터예요. 공통 추적 헤더 박기 같은 데 유용해요.

여기까지 따라오셨다면 한 가지 의문이 들 거예요 — "게이트웨이가 단일 장애점(SPOF)이 되지 않을까?" 답은 — 그렇습니다, 그래서 게이트웨이 자체를 여러 인스턴스로 띄우고 그 앞에 로드밸런서(또는 K8s Service)를 둡니다. 게이트웨이는 stateless라 수평 확장이 자연스러워요.

외부 문서 — 사양 자세히 보기

라우팅·Predicate·Filter의 모든 옵션은 Spring Cloud Gateway 공식 문서에 정리돼 있어요. Buildpack 기본 동작은 Paketo Buildpacks 공식 사이트에서 볼 수 있고요.

> 한 줄 정리 — Cloud Gateway = WebFlux 기반 정문 데스크. Predicate(매칭) + Filter(가공) + URI(목적지) 셋의 조합이 한 Route.

Spring Boot Maven Plugin — 빌드 자동화의 정석

마이크로서비스 5개를 다 직접 mvn package 하고 일일이 클래스패스 챙겨서 실행하면 손이 너무 갑니다. Spring Boot Maven Plugin이 여기서 등장해요. 이 플러그인이 하는 핵심 일은 — 실행 가능한 fat JAR을 만들고, 컨테이너 이미지까지 빌드하는 거예요.

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!-- spring-boot-starter-parent에서 버전 자동 관리 -->
        </plugin>
    </plugins>
</build>

기본 명령어 모음.

# 패키징 — fat JAR을 target/에 생성
mvn package

# 실행 — Spring Boot 앱을 직접 실행 (개발 시)
mvn spring-boot:run

# 컨테이너 이미지 빌드 (Buildpack 사용, Docker 데몬 필요)
mvn spring-boot:build-image

# 이미지 이름 직접 지정
mvn spring-boot:build-image -Dspring-boot.build-image.imageName=acme/myapp:1.0.0

Goals 자주 쓰이는 5가지

Goal역할
repackagefat JAR 생성 (기본)
run앱 실행
build-imageBuildpack으로 컨테이너 이미지 빌드
build-info빌드 정보(/actuator/info용) 생성
process-aotGraalVM AOT 컴파일 준비

여기서 시험 함정이 하나 있어요. spring-boot:run은 개발용이지 프로덕션 실행 도구가 아닙니다. 프로덕션에선 java -jar app.jar 또는 컨테이너 이미지로 실행해요.

Layered JAR — Docker 빌드 캐시 최적화

Spring Boot 2.3+부터 fat JAR을 레이어로 나눠 패키징합니다. 의존성·스냅샷·애플리케이션 클래스가 별도 레이어로 분리돼서 — Docker로 이미지 빌드할 때 변경된 레이어만 다시 빌드되니 빌드 시간이 크게 줄어요.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <layers>
            <enabled>true</enabled>
        </layers>
    </configuration>
</plugin>

기본 4개 레이어:

  1. dependencies — 외부 의존성 (가장 적게 변경)
  2. spring-boot-loader — Spring Boot 로더
  3. snapshot-dependencies — SNAPSHOT 의존성
  4. application — 앱 클래스 (가장 자주 변경)

> 한 줄 정리 — Maven Plugin = mvn package로 fat JAR / mvn spring-boot:build-image로 컨테이너 이미지 / 레이어드 JAR로 Docker 빌드 캐시 최적화.

Spring Boot Gradle Plugin — Maven의 Gradle 사촌

같은 일을 Gradle로 할 때 쓰는 게 Spring Boot Gradle Plugin이에요. Maven Plugin과 거의 1:1 매핑이라 흐름은 똑같아요.

// build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    runtimeOnly 'com.h2database:h2'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

Gradle 명령어 모음.

# 빌드 + 테스트
./gradlew build

# 클린 + 빌드
./gradlew clean build

# 앱 실행
./gradlew bootRun

# 실행 가능 JAR 생성 (build/libs/에)
./gradlew bootJar

# 컨테이너 이미지 빌드
./gradlew bootBuildImage

# 의존성 트리 확인
./gradlew dependencies

요구사항 — Gradle 7.5 이상 필수예요. 그 이전 버전에선 Spring Boot 3.x Gradle Plugin이 동작 안 합니다.

Gradle Wrapper — 팀 전체가 같은 Gradle 버전

./gradlew (또는 Windows에서 gradlew.bat)는 Gradle Wrapper예요. 프로젝트에 포함된 스크립트로, 별도 Gradle 설치 없이 정해진 버전을 자동으로 다운로드해 사용합니다. 팀 전체가 같은 빌드 결과를 보장받는 핵심 도구.

# gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip

여기서 시험 함정이 하나 있어요. Maven은 결과물이 target/에, Gradle은 build/libs/에 생성됩니다. CI 스크립트에서 경로를 잘못 적으면 아티팩트를 못 찾아요.

Maven vs Gradle — 어느 쪽?

특성MavenGradle
설정 형식XML (pom.xml)Groovy/Kotlin (build.gradle)
빌드 단위Goal/Phase (라이프사이클)Task (유연한 그래프)
결과물target/build/libs/
유연성낮음 (XML 제한)높음 (스크립트 기반)
빌드 속도보통빠름 (캐싱 최적화)
학습 곡선낮음중간
시장 점유율높음 (레거시 많음)증가 중

회사·프로젝트 컨벤션에 따르되, 새 프로젝트라면 Gradle 8 이상이 빌드 속도·캐싱·플러그인 생태계 면에서 우위예요.

Buildpack — 자동 도시락 포장기

여기서 컨테이너 이미지 빌드의 새 패러다임이 등장해요. Cloud Native Buildpacks(CNB)는 Heroku와 Pivotal이 시작한 표준으로, Dockerfile 없이 소스 코드만으로 컨테이너 이미지를 자동 빌드합니다.

회사 비유로 — Dockerfile이 "어떤 통에 어떤 재료를 어느 순서로 담을지" 직접 적는 수제 도시락 레시피라면, Buildpack은 "재료(소스 코드)만 넣으면 알아서 통·뚜껑·라벨까지 정해 주는 자동 도시락 포장기"예요. 통일된 패턴으로 균일한 도시락이 나오니 운영팀도 편하고, 보안 패치도 도시락통(베이스 이미지) 한 번 바꾸면 모든 도시락에 일괄 적용돼요.

Spring Boot의 Buildpack 통합

Spring Boot 2.3+부터 Maven/Gradle Plugin에 Paketo Buildpacks 통합이 들어 있어요. 한 줄 명령으로 컨테이너 이미지가 만들어집니다.

# Maven
mvn spring-boot:build-image

# Gradle
./gradlew bootBuildImage

이 명령이 하는 일:

  1. 소스 코드를 컴파일·패키징
  2. Paketo Buildpack이 자바 버전 자동 감지
  3. JRE 베이스 이미지 선택
  4. Layered JAR을 적절히 분리해 레이어로 쌓기
  5. 메타데이터(빌드 시각·소스 버전 등) 라벨 추가
  6. 로컬 Docker 데몬에 이미지 push

결과 — docker images에서 바로 보이는 OCI 컨테이너 이미지가 나와요.

Dockerfile vs Buildpack 비교

특성DockerfileBuildpack
작성 필요있음 (Dockerfile)없음 (자동)
베이스 이미지 선택직접자동 (Paketo)
보안 패치매번 수동베이스 한 번만 갱신
빌드 일관성팀마다 다를 수 있음자동 표준화
레이어 최적화수동 설계자동 (Layered JAR 활용)
커스터마이징자유롭게제한적 (그러나 충분)
학습 곡선높음낮음

Buildpack 옵션 — 자주 쓰이는 설정

<!-- pom.xml -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <name>acme/${project.artifactId}:${project.version}</name>
            <env>
                <BP_JVM_VERSION>17</BP_JVM_VERSION>
            </env>
            <publish>false</publish>
        </image>
    </configuration>
</plugin>

또는 명령줄로:

mvn spring-boot:build-image \
  -Dspring-boot.build-image.imageName=acme/myapp:1.0.0 \
  -Dspring-boot.build-image.publish=false

여기서 시험 함정이 하나 있어요. Buildpack 빌드는 로컬 Docker 데몬이 동작 중이어야 합니다. Docker Desktop·colima·Rancher Desktop 같은 도구가 켜져 있지 않으면 "Docker context not found" 에러가 떨어져요.

일반 JAR vs 실행 가능 JAR

Spring Boot Maven/Gradle Plugin이 만드는 fat JAR(실행 가능 JAR)은 모든 의존성을 포함해 java -jar 한 줄로 실행할 수 있어요. 일반 JAR은 의존성이 빠져 있어 클래스패스를 따로 챙겨야 합니다.

# 실행 가능 JAR (Spring Boot Plugin 결과물)
java -jar target/myapp-1.0.0.jar

# 일반 JAR — 클래스패스 직접 명시
java -cp target/classes:lib/* com.example.MyApplication

여기서 시험 함정 — fat JAR 안에는 다른 JAR이 그대로 들어가 있습니다(중첩 JAR). 일반 JAR 표준 형식이 아니에요. 그래서 일반 자바 도구(예: 일부 정적 분석기)가 fat JAR을 못 읽을 수 있어요.

> 한 줄 정리 — Maven/Gradle Plugin = 빌드 + 실행 + 이미지 빌드 통합 / Buildpack = Dockerfile 없는 자동 컨테이너 이미지.

비교표 — 한 번 더 한눈에

Spring Cloud Gateway 핵심 3종

요소역할
Route경로·서비스 매핑 단위
Predicate라우트 매칭 조건 (AND 결합)
Filter요청·응답 가공 (Pre/Post 시점)

Maven Plugin Goals vs Gradle Plugin Tasks

작업MavenGradle
패키징mvn package./gradlew bootJar
실행mvn spring-boot:run./gradlew bootRun
이미지 빌드mvn spring-boot:build-image./gradlew bootBuildImage
클린 빌드mvn clean package./gradlew clean build
결과물 위치target/build/libs/

Dockerfile vs Buildpack

특성DockerfileBuildpack
정의 방식수동 작성자동 감지
보안 패치매 이미지마다 직접베이스 한 번에 일괄
학습 곡선높음낮음
커스터마이징무제한제한적 (대부분 충분)
표준화팀별 다름자동

자주 만나는 함정 8가지

1. Cloud Gateway에 spring-boot-starter-web 같이 박음

WebFlux와 MVC가 한 컨텍스트에서 충돌. 게이트웨이는 별도 앱으로.

2. StripPrefix 값 잘못 계산

/api/v3/product/123을 백엔드에 /product/123으로 보내려면 StripPrefix=2. 자주 헷갈려 라우팅이 깨집니다.

3. Predicate AND 조건 오해

한 Route에 여러 Predicate를 넣으면 모두 매칭돼야 흘러갑니다. OR 조건이 필요하면 Route를 두 개로 나눠요.

4. 게이트웨이 단일 장애점 무시

게이트웨이 자체를 여러 인스턴스로 띄우고 앞단에 LB. K8s Service·Ingress가 자연스러운 해법.

5. mvn spring-boot:run을 프로덕션에 사용

개발용 도구. 프로덕션은 java -jar 또는 컨테이너.

6. Maven target/ ↔ Gradle build/libs/ 경로 혼동

CI 스크립트에서 아티팩트 경로 틀리면 빌드 후 푸시가 실패해요.

7. Buildpack 빌드에 Docker 데몬 미실행

Docker Desktop·colima 같은 데몬이 떠 있어야 build-image가 동작.

8. fat JAR을 일반 자바 도구로 처리

중첩 JAR 형식이라 표준 ZIP 도구가 내부를 못 풀 때 있어요. Spring Boot 전용 도구나 jarmode=tools 옵션 사용.

핵심 압축 노트 — 시험 직전 한 번 더

여기까지가 11편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • Spring Cloud Gateway = WebFlux 기반 단일 진입점
  • 게이트웨이는 spring-boot-starter-web(MVC)와 같이 못 씀 — 충돌
  • Spring Cloud Gateway 핵심 3종 = Route + Predicate + Filter
  • Predicate 자주 = Path·Method·Header·Host·Query
  • Filter 자주 = AddRequestHeader·StripPrefix·RewritePath·Retry·CircuitBreaker·RequestRateLimiter
  • 한 Route 안 여러 Predicate = AND 조건 (OR 필요하면 Route 분리)
  • default-filters는 모든 Route에 자동 적용 (공통 추적 헤더 등)
  • 게이트웨이는 stateless — 수평 확장 자연스러움
  • 단일 장애점 방지 — 여러 인스턴스 + 앞단 LB
  • Spring Boot Maven Plugin 핵심 goals = repackage·run·build-image
  • mvn package = fat JAR 생성, target/에 결과물
  • mvn spring-boot:run = 개발 전용, 프로덕션 실행 X
  • Layered JAR — Spring Boot 2.3+ 기본, Docker 빌드 캐시 최적화
  • 4개 레이어 = dependencies / loader / snapshot-deps / application
  • Spring Boot Gradle Plugin = Maven Plugin의 Gradle 사촌
  • Gradle 7.5+ 필수 (Spring Boot 3.x 사용 시)
  • Gradle 명령 = bootJar·bootRun·bootBuildImage·clean build
  • ./gradlew Wrapper — 팀 전체 같은 Gradle 버전 보장
  • Maven target/ ↔ Gradle build/libs/ 경로 다름
  • Buildpack (Cloud Native Buildpacks) = Dockerfile 없는 자동 컨테이너 빌드
  • Spring Boot 2.3+가 Paketo Buildpack 통합
  • mvn spring-boot:build-image 또는 ./gradlew bootBuildImage
  • Buildpack 빌드 → 로컬 Docker 데몬 필요
  • Buildpack 장점 = 자동 표준화 + 베이스 이미지 일괄 보안 패치
  • Buildpack 옵션 = -Dspring-boot.build-image.imageName=...
  • fat JAR(실행 가능 JAR) = 모든 의존성 포함, java -jar로 실행
  • fat JAR은 중첩 JAR 형식 — 표준 ZIP 도구로 못 읽을 수 있음

시리즈 다른 편

같은 시리즈의 다른 글들도 같은 친절 톤으로 묶어 정리되어 있어요.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!