Skip to content

Deployment and Operations

SANGMIN PARK edited this page Jul 18, 2026 · 6 revisions

Deployment and Operations

전환 안내. 아래의 엄격한 prod 버전 검증, metadata 선보존, tag·Release 복구 절차는 backend issue #306의 workflow가 main에 반영된 뒤 적용됩니다. 반영 전에는 main의 실제 workflow를 기준으로 판단합니다.

배포 흐름

dev와 prod Lambda 배포는 수동 workflow_dispatch입니다. dev는 Lambda Version과 Alias만 갱신하며 버전 릴리즈를 게시하지 않습니다. prod는 배포 전 preflight를 거치고 Alias 검증 후 Summary와 metadata artifact를 보존한 다음 Git 태그와 GitHub Release를 게시합니다.

flowchart TB
    subgraph Dev["dev 배포"]
        DevTrigger["workflow_dispatch"] --> DevMigration["Flyway info + migrate"]
        DevMigration --> DevDeploy["Test → Build → S3 → Lambda Version"]
        DevDeploy --> DevAlias["Alias 이동·검증"] --> DevDone["배포 완료<br/>버전 릴리즈 없음"]
    end

    subgraph Prod["prod 배포"]
        ProdTrigger["main workflow_dispatch<br/>MAJOR.MINOR.PATCH 입력"] --> Preflight["preflight<br/>main·버전 형식·중복 태그 검증"]
        Preflight --> ProdMigration["Flyway info + migrate<br/>이전 코드 호환 migration"]
        ProdMigration --> ProdDeploy["Test → Build → S3 → Lambda Version"]
        ProdDeploy --> ProdAlias["Alias 이동·검증"] --> Summary["Actions Summary 작성"]
        Summary --> Metadata["deployment metadata<br/>artifact 업로드"]
        Metadata --> Tag["be-v{버전}<br/>annotated tag push"] --> Release["GitHub Release<br/>추적 본문 포함"]
    end
Loading

사용하는 Workflow입니다.

Workflow 용도
CI (Gradle) dev, main push·PR에서 ./gradlew check
Flyway Migration for DB schema dev·prod DB 마이그레이션 단독 실행
Deploy to Dev Lambda dev 마이그레이션 후 Lambda 배포
Deploy to Prod Lambda prod 마이그레이션 후 Lambda 배포

필요한 GitHub 설정

Repository Variables입니다.

  • dev는 DEV_AWS_REGION, DEV_LAMBDA_FUNCTION_NAME, DEV_LAMBDA_ALIAS, DEV_LAMBDA_ARTIFACT_BUCKET을 사용합니다.
  • prod는 PROD_AWS_REGION, PROD_LAMBDA_FUNCTION_NAME, PROD_LAMBDA_ALIAS, PROD_LAMBDA_ARTIFACT_BUCKET을 사용합니다.

Secrets입니다.

  • AWS 배포는 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY를 사용합니다.
  • Flyway dev는 DEV_FLYWAY_DB_URL, DEV_FLYWAY_DB_USER, DEV_FLYWAY_DB_PASSWORD를 사용합니다.
  • Flyway prod는 PROD_FLYWAY_DB_URL, PROD_FLYWAY_DB_USER, PROD_FLYWAY_DB_PASSWORD를 사용합니다.

값을 Wiki나 Actions 로그에 출력하지 않습니다.

dev 배포

  1. 대상 변경이 dev에 포함됐는지 확인합니다.
  2. Actions에서 Deploy to Dev Lambda를 선택합니다.
  3. 실행할 ref를 확인하고 Workflow를 시작합니다.
  4. Migrate dev DB schema가 성공했는지 확인합니다.
  5. 테스트, ZIP 생성, S3 업로드, Lambda Version 게시를 확인합니다.
  6. Summary의 Published Version과 Alias Version이 같은지 확인합니다.
  7. dev Health, Swagger, 변경 endpoint를 smoke test합니다.

dev 배포 Workflow는 Lambda 코드와 Alias만 갱신합니다. 런타임 환경 변수, IAM, Layer, Extension은 관리하지 않습니다. dev 배포 전에도 대상 Lambda의 SPRING_PROFILES_ACTIVE, DB, SQS, HMAC, S3 설정을 별도로 확인합니다.

prod 배포

prod Workflow는 main에서만 실행합니다. Actions 실행 ref가 다르면 preflight에서 실패하며 Migration을 시작하지 않습니다. Workflow 안의 마이그레이션은 prod GitHub Environment의 승인 규칙을 따릅니다.

실행할 때 각 숫자가 0 또는 선행 0 없는 양의 정수인 최종 MAJOR.MINOR.PATCH를 입력합니다. 01.2.3 같은 선행 0, 축약 버전, prerelease와 build suffix는 허용하지 않습니다. preflight는 버전 형식과 기존 be-v{버전} 태그 중복을 Migration 전에 검사합니다.

Workflow dispatch 시점의 main commit SHA를 배포 단위로 고정합니다. Migration, Lambda build, S3 Object, Git 태그와 GitHub Release가 모두 같은 commit SHA를 사용합니다.

정식 release 사전 조건

  • dev에서 만든 release/v{버전}의 QA와 fix/* 반영을 끝내고 해당 버전을 확정합니다.
  • release 브랜치를 main에 병합한 뒤 확정한 버전과 같은 값을 prod Workflow에 입력합니다.
  • 운영 배포가 끝나면 maindev에 역병합해 release QA 수정이 다음 릴리즈에서 사라지지 않게 합니다.

hotfix 사전 조건

  • hotfix/*main에서 생성하고 prod Workflow 실행 전에 반드시 main에 병합합니다.
  • 마지막으로 성공한 be-v* 릴리즈의 PATCH를 증가한 버전을 확인하고 승인합니다. 예를 들어 마지막 성공 버전이 be-v1.2.3이면 1.2.4를 사용합니다.
  • 운영 배포가 끝나면 maindev와 진행 중인 모든 release/* 브랜치에 역병합합니다.

prod Flyway migration은 배포 직전까지 트래픽을 처리하는 이전 Lambda 코드와 backward compatible해야 합니다. Migration 성공 뒤 테스트·빌드·Lambda 게시가 실패하면 이전 Alias가 계속 트래픽을 처리하므로 새 schema에서 이전 코드가 정상 동작해야 합니다.

확인 순서입니다.

  1. 정식 release 또는 hotfix의 사전 조건을 충족했고 대상 변경이 main에 포함됐는지 확인합니다.
  2. Actions에서 Deploy to Prod Lambda의 ref를 main으로 선택하고 승인한 버전을 입력해 수동 실행합니다.
  3. preflight에서 main, 엄격한 버전 형식, be-v{버전} 태그 중복 검증이 성공했는지 확인합니다.
  4. Flyway info에서 예상한 버전만 Pending이고 이전 Lambda 코드와 호환되는지 확인합니다.
  5. Migration, Test, Build, Publish가 모두 성공했는지 확인합니다.
  6. Alias가 새 Version을 가리키는지 확인합니다.
  7. Alias 검증 뒤 Actions Summary와 deployment metadata artifact가 생성됐는지 확인합니다.
  8. 같은 commit SHA에 be-v{버전} annotated tag와 GitHub Release가 생성됐는지 확인합니다. Release 본문의 제품 버전, commit SHA, Lambda published version과 alias version도 대조합니다.
  9. /health, /actuator/health, 핵심 인증 API를 확인합니다.
  10. Sentry와 CloudWatch에서 새 오류가 증가하지 않는지 확인합니다.

prod Lambda에는 다음 런타임 설정이 외부 인프라에서 명시돼야 합니다.

  • SPRING_PROFILES_ACTIVE=prod.
  • prod DB와 OIDC·JWT 설정.
  • prod SQS Queue URL과 HMAC Secret.
  • prod S3 Bucket, Prefix, Region.

application.yml의 S3 기본값은 develop-shadow용입니다. prod에서 SCRAPING_RESULT_BUCKETSCRAPING_RESULT_PREFIX를 생략하면 잘못된 환경의 결과를 보게 될 수 있습니다.

배포 산출물

lambdaZip은 다음 파일을 만듭니다.

build/distributions/haksa-lambda.zip

Workflow는 commit SHA를 포함한 S3 Key로 ZIP을 올리고 새 Lambda Version을 게시합니다. Alias 검증이 성공하면 태그와 Release를 게시하기 전에 Actions Summary와 deployment metadata artifact에 release version, release tag, commit SHA, function, alias, S3 key, published version, alias version을 기록합니다. GitHub Release 본문에도 제품 버전, commit SHA, Lambda published version과 alias version을 기록하고 자동 생성 릴리즈 노트를 함께 유지합니다.

prod 릴리즈 부분 실패 복구

Alias 검증 전에 실패하면 배포 실패이며 태그와 GitHub Release가 생기지 않습니다. Alias 검증 뒤 태그 또는 Release 게시가 실패하면 Lambda 배포는 성공했지만 릴리즈 기록 게시가 실패한 부분 성공입니다.

태그 push는 성공했지만 GitHub Release 생성만 실패했다면 다음 값이 모두 일치할 때 같은 태그에 Release만 복구합니다. 이미 게시한 태그는 삭제하거나 다른 commit으로 이동하지 않습니다.

  1. 실패한 Actions run의 headSha.
  2. annotated tag를 역참조한 commit SHA.
  3. metadata artifact의 commit_sha, published_version, alias_version.
  4. 현재 Lambda Alias가 가리키는 Version.

다음 명령은 실패한 run과 artifact를 조회해 Release만 복구하는 예시입니다.

RUN_ID="<실패한 Actions run ID>"
artifact_dir="$(mktemp -d)"

gh run download "$RUN_ID" \
  --name prod-lambda-deployment-metadata \
  --dir "$artifact_dir"

metadata_file="$artifact_dir/prod-lambda-deployment.txt"
metadata_value() {
  awk -F= -v key="$1" '$1 == key { sub(/^[^=]*=/, ""); print; exit }' "$metadata_file"
}

release_version="$(metadata_value release_version)"
release_tag="$(metadata_value release_tag)"
commit_sha="$(metadata_value commit_sha)"
function_name="$(metadata_value function_name)"
alias_name="$(metadata_value alias)"
published_version="$(metadata_value published_version)"
alias_version="$(metadata_value alias_version)"
run_sha="$(gh run view "$RUN_ID" --json headSha --jq '.headSha')"

git fetch origin "refs/tags/$release_tag:refs/tags/$release_tag"
tag_sha="$(git rev-parse "$release_tag^{commit}")"
live_alias_version="$(aws lambda get-alias \
  --function-name "$function_name" \
  --name "$alias_name" \
  --query 'FunctionVersion' \
  --output text)"

test "$run_sha" = "$commit_sha"
test "$tag_sha" = "$commit_sha"
test "$published_version" = "$alias_version"
test "$live_alias_version" = "$alias_version"

release_notes=$(printf -- '- Product version: `%s`\n- Commit SHA: `%s`\n- Lambda published version: `%s`\n- Lambda alias version: `%s`\n' \
  "$release_version" \
  "$commit_sha" \
  "$published_version" \
  "$alias_version")

gh release create "$release_tag" \
  --verify-tag \
  --target "$commit_sha" \
  --title "$release_tag" \
  --generate-notes \
  --notes "$release_notes"

값이 다르거나 이미 Release가 있으면 중단하고 후속 배포 또는 수동 변경 여부를 먼저 확인합니다. 부분 성공을 복구하려고 prod Workflow를 다시 실행하거나 태그를 다시 만들지 않습니다.

롤백

애플리케이션 롤백은 직전 정상 Lambda Version으로 Alias를 되돌리는 방식입니다. 이전 Version은 Actions Summary와 deployment metadata artifact에서 확인합니다.

aws lambda update-alias \
  --function-name "$LAMBDA_FUNCTION_NAME" \
  --name "$LAMBDA_ALIAS" \
  --function-version "$PREVIOUS_VERSION"

aws lambda get-alias \
  --function-name "$LAMBDA_FUNCTION_NAME" \
  --name "$LAMBDA_ALIAS" \
  --query 'FunctionVersion' \
  --output text

DB 마이그레이션은 Lambda Alias와 함께 자동 롤백되지 않습니다. 적용된 Migration 파일도 되돌려 수정하지 않습니다. 스키마 보정은 데이터 보존과 이전 애플리케이션 호환성을 확인한 다음 version의 forward migration으로 수행합니다.

운영 확인 지점

Maintenance Event

같은 Lambda Handler는 HTTP API 외에 EventBridge Scheduler event도 처리합니다. source=eventbridge.scheduler이고 task가 있으면 다음 작업을 실행합니다.

  • SCRAPE_JOB_RECONCILE_STALE은 오래된 포털 작업을 callback timeout으로 종료합니다.
  • REFRESH_TOKEN_CLEANUP은 만료된 Refresh Token을 정리합니다.

Scheduler 리소스 정의는 이 저장소에 없습니다. 유지보수 작업이 실행되는지는 배포된 EventBridge Scheduler target과 Lambda invoke 권한을 확인해야 합니다.

Health와 API

curl -sS https://api.cchaksa.com/health
curl -sS https://api.cchaksa.com/actuator/health
curl -sS https://api.cchaksa.com/v3/api-docs

로그 상관관계

포털 장애는 jobId를 시작점으로 찾습니다. 다음 값을 함께 연결합니다.

  • jobId.
  • outboxId.
  • queueMessageId.
  • workerRequestId.
  • operationType.

관측 도구의 역할

도구 우선 확인할 내용
GitHub Actions Migration, Test, Build, Alias 변경
CloudWatch Logs Lambda platform 로그와 stdout·stderr. prod file 로그 수집 여부는 외부 설정 확인
Sentry 예외 Stack Trace와 MDC tag
Grafana Cloud 활성화된 OTLP Metric과 외부 전달 로그. 현재 앱의 OTLP Trace exporter는 제외됨
PostgreSQL 작업·Outbox 상태와 학사 데이터 반영 결과

Grafana metric이나 Sentry event가 없다는 사실만으로 요청이 없었다고 단정하지 않습니다. 수집 설정과 Lambda 로그를 먼저 확인합니다.

prod Logback은 기본적으로 /var/log/app 파일과 Sentry에 기록하며 Console appender가 없습니다. Lambda에서 file 로그를 수집하려면 쓰기 가능한 LOG_PATH와 Telemetry Extension 또는 별도 전달 설정이 필요합니다. 해당 인프라 정의는 이 저장소에 없으므로 실제 Lambda 설정을 확인해야 합니다.

Clone this wiki locally