Claude와 함께 배포 및 DevOps
배포는 개인 프로젝트에서 가장 간과되는 단계인 경우가 많지만 필수적입니다. 코드를 작동하는 제품으로 변환합니다. 클로드가 설정을 도와드릴 수 있습니다 컨테이너화, CI/CD, 모니터링 및 로깅 전문적인 방법으로.
이 기사에서는 Claude를 사용하여 프로젝트 제작을 준비하는 방법을 살펴보겠습니다. 자동화된 배포 파이프라인을 생성하고 인프라를 구성합니다.
무엇을 배울 것인가
- Docker를 사용한 컨테이너화(다단계 빌드)
- 로컬 개발을 위한 Docker Compose
- GitHub Actions를 사용한 CI/CD
- 클라우드 배포(AWS, Railway, Fly.io)
- 기본 로깅 및 모니터링
Docker를 사용한 컨테이너화
Spring Boot를 위한 다단계 빌드
# Stage 1: Build
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
# Cache dependencies
COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN ./mvnw dependency:go-offline -B
# Build application
COPY src src
RUN ./mvnw package -DskipTests -B
# Extract layers for better caching
RUN java -Djarmode=layertools -jar target/*.jar extract
# Stage 2: Runtime
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
# Security: non-root user
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
USER appuser
# Copy layers in order of change frequency
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD wget -q --spider http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
Angular를 위한 다단계 빌드
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
# Cache dependencies
COPY package*.json ./
RUN npm ci
# Build application
COPY . .
RUN npm run build -- --configuration=production
# Stage 2: Serve
FROM nginx:alpine
COPY --from=builder /app/dist/*/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
server {{ '{' }}
listen 80;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# SPA routing
location / {{ '{' }}
try_files $uri $uri/ /index.html;
{{ '}' }}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {{ '{' }}
expires 1y;
add_header Cache-Control "public, immutable";
{{ '}' }}
# API proxy (development)
location /api/ {{ '{' }}
proxy_pass http://backend:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
{{ '}' }}
{{ '}' }}
개발용 Docker Compose
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DATABASE_URL=jdbc:postgresql://postgres:5432/orders
- DATABASE_USER=postgres
- DATABASE_PASSWORD=postgres
- KAFKA_BOOTSTRAP_SERVERS=kafka:9092
depends_on:
postgres:
condition: service_healthy
kafka:
condition: service_started
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 5s
retries: 3
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "4200:80"
depends_on:
- backend
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_DB=orders
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
kafka:
image: confluentinc/cp-kafka:7.5.0
environment:
KAFKA_NODE_ID: 1
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
KAFKA_LISTENERS: PLAINTEXT://kafka:9092,CONTROLLER://kafka:9093
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk
ports:
- "9092:9092"
volumes:
postgres_data:
GitHub Actions를 사용한 CI/CD
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ '{{' }} github.repository {{ '}}' }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Run tests
run: ./mvnw verify
working-directory: ./backend
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: ./backend/target/site/jacoco/jacoco.xml
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ '{{' }} env.REGISTRY {{ '}}' }}
username: ${{ '{{' }} github.actor {{ '}}' }}
password: ${{ '{{' }} secrets.GITHUB_TOKEN {{ '}}' }}
- name: Build and push Backend
uses: docker/build-push-action@v5
with:
context: ./backend
push: true
tags: ${{ '{{' }} env.REGISTRY {{ '}}' }}/${{ '{{' }} env.IMAGE_NAME {{ '}}' }}-backend:${{ '{{' }} github.sha {{ '}}' }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to Railway
uses: berviantoleo/railway-deploy@main
with:
railway_token: ${{ '{{' }} secrets.RAILWAY_TOKEN {{ '}}' }}
service: order-service
로깅 및 모니터링
logging:
level:
root: INFO
com.company.orders: DEBUG
pattern:
console: "%d{{ '{' }}yyyy-MM-dd HH:mm:ss{{ '}' }} [%thread] %-5level %logger{{ '{' }}36{{ '}' }} - %msg%n"
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when_authorized
metrics:
tags:
application: order-service
# Structured logging for production
---
spring:
config:
activate:
on-profile: prod
logging:
pattern:
console: '{{ '{' }}"timestamp":"%d{{ '{' }}ISO8601{{ '}' }}","level":"%level","logger":"%logger","message":"%msg","thread":"%thread"{{ '}' }}%n'
배포 체크리스트
배포 전 체크리스트
- 최적화된 다단계 Dockerfile
- 로컬 개발을 위한 Docker Compose
- 상태 확인이 구성됨
- CI/CD 파이프라인 작동 중
- 비밀이 올바르게 처리됨(git에서는 아님)
- 프로덕션을 위한 구조화된 로깅
- 노출된 측정항목(Prometheus/Actuator)
- 자동화된 데이터베이스 백업
결론
이 기사에서는 배포를 위해 프로젝트를 준비하는 방법을 살펴보았습니다. 생산 중. 에서 다음 기사와 마지막 기사, 우리는 탐구할 것입니다 는프로젝트의 진화: 확장성, 유지보수 및 새로운 기능 추가.
기억해야 할 핵심 사항
- 다단계 빌드: 작고 안전한 이미지
- 도커 작성: 재현 가능한 로컬 환경
- 자동화된 CI/CD: 일관되고 안정적인 배포
- 상태 확인: 오케스트레이터를 위한 기본 사항
- 구조화된 로깅: 프로덕션 환경에서 간편한 디버깅







