Spring 개발일지

[팀프로젝트] MSA 기반 티켓팅 프로그램 - 개발 환경 세팅

김둘리 2026. 4. 27. 09:45

설계가 마무리되고 드디어 구현 단계에 들어갔다. 멀티레포 방식으로 진행하는 만큼 각 서비스별로 레포를 만들고 초기 세팅을 해야 했다. 이번 편에서는 기술 스택 선택 이유부터 GitHub 세팅까지 정리해보려 한다.


1. 기술 스택

Java 21

Java 21을 선택한 가장 큰 이유는 가상 스레드(Virtual Thread) 지원이다.

가상 스레드는 JVM 위에서 생성 및 실행되는 경량 스레드로 플랫폼 스레드보다 훨씬 가볍고 더 적은 리소스를 사용한다. 티켓팅 서비스 특성상 오픈 순간 대량의 동시 요청이 몰리는데, 가상 스레드를 활용하면 더 적은 리소스로 더 많은 요청을 처리할 수 있다.

Spring Boot 3.5.13

Java 21 가상 스레드를 지원하는 최신 버전이다.

Spring Cloud 2025.0.1

Config Server, Eureka, OpenFeign 등 MSA 구성에 필요한 컴포넌트들을 제공한다.

PostgreSQL

추후 PGVector 사용 가능성을 고려해서 선택했다.

Flyway

DB 마이그레이션 도구로 스키마 변경 이력을 코드로 관리할 수 있다.

Rest Docs

테스트 코드 기반으로 문서를 생성해서 실제 동작하는 코드와 문서 간의 일관성을 100% 보장하고, 운영 코드에 문서화 어노테이션이 남지 않아 코드 순수성을 유지할 수 있다.


2. 멀티레포 방식

이번 프로젝트는 멀티레포 방식으로 진행한다. 각 서비스가 독립적인 레포를 가지는 구조다.

first-ticket/
├── common-module       ← 공통 모듈 (별도 레포)
├── config-server       ← 설정 서버 (별도 레포)
├── eureka-server       ← 서비스 디스커버리 (별도 레포)
├── gateway-server      ← API Gateway (별도 레포)
├── user-service        ← 사용자 도메인 (별도 레포)
├── payment-service     ← 결제 도메인 (별도 레포)
├── booking-service     ← 예매 도메인 (별도 레포)
├── program-service     ← 프로그램 도메인 (별도 레포)
└── queue-service       ← 대기열 도메인 (별도 레포)

모노레포 방식과 달리 각 레포가 독립적인 프로젝트라 실행에 필요한 파일이 모두 있어야 한다.


3. build.gradle 의존성 구성

groovy
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.5.13'
    id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.first-ticket'
version = '0.0.1-SNAPSHOT'
description = 'payment-service'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', '2025.0.1')
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

dependencies {
    // Web
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // JPA
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

    // PostgreSQL
    runtimeOnly 'org.postgresql:postgresql'

    // Flyway
    implementation 'org.flywaydb:flyway-core'
    implementation 'org.flywaydb:flyway-database-postgresql'

    // Validation
    implementation 'org.springframework.boot:spring-boot-starter-validation'

    // Actuator
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

    // Kafka
    implementation 'org.springframework.kafka:spring-kafka'

    // Spring Cloud Config Client
    implementation 'org.springframework.cloud:spring-cloud-starter-config'

    // Eureka Client
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'

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

    // Test
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.kafka:spring-kafka-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

dependencyManagement 블록이 필요한 이유

Spring Cloud는 여러 라이브러리들이 BOM(Bill of Materials) 방식으로 묶음 관리된다. BOM을 import하면 각 라이브러리 버전을 직접 명시하지 않아도 Spring Cloud 버전에 맞는 버전이 자동으로 맞춰진다. 없으면 버전 충돌이 날 수 있다.


4. .editorconfig 설정

운영체제 간 줄바꿈 규칙 통일과 코드 스타일 충돌 방지를 위해 추가한다.

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4

[*.java]
max_line_length = 120

5. .gitattributes 설정

Windows는 줄바꿈이 CRLF, Mac/Linux는 LF라서 Git에서 파일이 변경된 것처럼 보이는 문제를 방지한다.

# 텍스트 파일 기본: LF 정규화
* text=auto eol=lf

# gradlew는 반드시 LF (Unix 실행 파일)
gradlew text eol=lf

# Windows 배치 파일
*.bat text eol=crlf
*.cmd text eol=crlf

# 바이너리 (변환 금지)
*.jar binary
*.class binary
*.png binary
*.jpg binary
*.gif binary

6. GitHub 레포 세팅

브랜치 전략

main    ← 배포 브랜치 (Protected)
dev     ← 개발 통합 브랜치 (Protected)
feat/*  ← 기능 개발 브랜치

브랜치 보호 규칙 (main, dev)

  • 직접 push 금지
  • PR 필수
  • CI 통과 필수
  • 승인 1명 이상 필수
  • 삭제 금지

브랜치 네이밍 규칙

feat/{이슈번호}-{간단한-기능명}

예시)
feat/1-domain-setup
feat/5-payment-create
feat/7-payment-confirm

커밋 메시지 규칙

bash
<type>: <subject>

<body>

<footer>
type설명
feat 새 기능
fix 버그 수정
refactor 리팩토링
docs 문서 변경
style 코드 스타일
test 테스트 코드
chore 빌드, 설정

예시

bash
feat: 결제 생성 API 구현

- POST /internal/v1/payments 엔드포인트 구현
- orderId UUID 기반 생성
- 결제 레코드 PENDING 상태로 초기화

Closes #5

이슈 제목 형식

[feat][payment] 도메인 엔티티 구현
[fix][payment] 중복 결제 방지 로직 수정

PR 흐름

feat/* → dev (PR)
dev → main (배포 시점에 PR)

 

설계만 할 때는 몰랐는데 실제로 레포 만들고 세팅하다 보니 팀원들이랑 맞춰야 할 것들이 생각보다 많았다. 브랜치 전략, 커밋 메시지 규칙, .editorconfig까지 전부 통일해두지 않으면 나중에 코드 리뷰할 때 스타일 충돌로 시간 낭비가 생긴다.

다음 편에서는 패키지 구조 설계와 개발 계획을 정리할 예정이다.