Next.js 앱을 쿠버네티스에 배포하기 (feat. ArgoCD)
언젠가부터 프론트엔드 개발자의 세계는 브라우저라는 경계를 훌쩍 넘어섰습니다. HTML, CSS, 자바스크립트만으로 충분하던 시대는 지나갔고, 이제 우리는 서버사이드 렌더링(SSR), CI/CD 파이프라인, 그리고 컨테이너와 클라우드 인프라까지 고민해야 하는 시대를 맞이했습니다.
그렇게 인프라 관련 지식은 더는 선택이 아닌 성장을 위한 필수 역량이 되었습니다. 테크 리드, 아키텍트, CTO 등 상위 포지션으로 나아갈수록 시스템 전체를 바라보는 시야가 다른 개발자와 차이를 만드는 강력한 무기가 됩니다. 특히 스타트업과 같은 환경에서는 멀티 플레이어가 가치를 더 인정받습니다. 클라우드 네이티브가 새로운 표준으로 자리 잡은 지금, 쿠버네티스(Kubernetes)에 대한 이해와 역량을 갖춘 개발자의 수요가 점점 더 증가하고 있습니다. 이런 역량은 곧 더 많은 커리어의 기회로 이어집니다.
크게 겁먹을 필요는 없습니다. 인프라도 결국 코드로 작성하고 관리하기 때문입니다. 우리가 평소 package.json을 다루듯 Dockerfile과 deployment.yaml 파일을 작성할 뿐입니다. 인프라 구성 역시 개발자가 가장 잘 다루는 도구인 ‘코드’ 활용의 연장선상에 있습니다.
요즘처럼 AI가 개발 영역을 대체할수록 우리는 더욱더 ‘경계를 넘나드는 엔지니어’로 거듭나야 합니다. 그렇게 프론트엔드 측면만 고민하기보다는, “이 기능을 어떻게 하면 가장 빠르고 안정적으로 사용자에게 전달할 수 있을까?”라는 관점과 시야를 갖추는 것이 중요합니다.
그 시작으로 사내 인프라 개발자와 협력해 도커(Docker)부터 EKS, ArgoCD까지 구축하고 운영하는 상황을 가정하고 정리해 보았습니다. 이 글이 여러분의 시야를 브라우저 너머로 확장하며, Next.js 애플리케이션을 쿠버네티스 환경에 자신 있게 배포하는 그날을 향한 여정에서 훌륭한 첫걸음으로 쓰이기를 바랍니다.
왜 쿠버네티스인가?
비즈니스라는 관점에서는 ‘더 적게 실행하는 소프트웨어’가 매우 중요합니다. 이는 개발을 적게 하자는 뜻이 아니라, 이미 검증된 표준 기술을 적극적으로 활용해 핵심 비즈니스 로직에 집중하자는 뜻입니다. 그런 의미에서 우리는 사실상 컨테이너 오케스트레이션의 표준으로 거듭난 쿠버네티스를 알아야 합니다.

쿠버네티스는 이런 일을 자동으로 처리해 줍니다.
- 수많은 컨테이너(애플리케이션)를 한 번에 배포하고 관리합니다.
- 트래픽에 따라 컨테이너 수를 자동으로 늘리거나 줄입니다(오토스케일링).
- 문제가 생긴 컨테이너를 감지하고 자동으로 재시작합니다(셀프 힐링).
프론트엔드 개발자에게 익숙한 도구로 비유하자면, Turborepo가 모노레포 안에서 빌드 의존성을 분석해 필요한 부분만 효율적으로 빌드하듯, 쿠버네티스는 수많은 애플리케이션 인스턴스를 가장 효율적인 방식으로 실행하고 관리합니다.
게다가 오토스케일링, 로드밸런싱 같은 필수 기능들은 AWS나 GCP 등 특정 클라우드 서비스에 종속되지 않고 쿠버네티스 자체에 내장되어 있어, 어떤 환경에서든 일관된 방식으로 인프라가 운영됩니다. 그 덕분에 우리는 복잡한 인프라에 시간을 쏟는 대신 오롯이 비즈니스 로직과 사용자 경험에 집중할 수 있습니다.
Next.js 앱을 쿠버네티스에 배포하는 5가지 단계
1단계: 애플리케이션 컨테이너화(Dockerfile 작성)
가장 먼저 할 일은 Next.js 프로젝트를 담을 컨테이너의 ‘설계도’, 즉 Dockerfile을 작성하는 것입니다. 이 파일로 운영체제나 라이브러리 버전에 구애받지 않고 항상 동일한 환경에서 애플리케이션을 실행할 도커 이미지를 만들 수 있습니다.
이때는 Next.js 12 버전부터 도입된 Standalone Output 설정을 활용하면 아주 가볍고 최적화된 이미지를 만들 수 있습니다. 설정 방법도 간단합니다. next.config.js에 output: ‘standalone’ 옵션을 추가하면, 애플리케이션 실행에 필요한 최소한의 파일만 생성해 줍니다.
# 1. 베이스 이미지 선택
FROM public.ecr.aws/docker/library/node:20-alpine
# 2. 작업 디렉토리 설정
WORKDIR /app
# 3. 운영 환경 설정
ENV NODE_ENV=production
# 4. 빌드 결과물 복사: standalone 모드로 생성된 최소한의 파일만 복사해 이미지 크기를 최적화합니다.
COPY .next/standalone ./
# 5. 정적 에셋(CSS, 이미지 등) 복사
COPY .next/static ./.next/static
# 6. public 폴더 에셋 복사
COPY public ./public
# 7. 외부에 노출할 포트 설정
EXPOSE 3000
# 8. 환경 변수 설정 (쿠버네티스에서 접근 가능하도록 0.0.0.0으로 설정)
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
# 9. 컨테이너 실행 명령어
CMD ["node", "server.js"]
2단계: 쿠버네티스를 위한 헬스 체크 API 구현
고가용성 서비스를 운영하려면, 시스템이 우리 애플리케이션의 ‘건강 상태’를 주기적으로 확인할 방법이 필요합니다. 쿠버네티스에서는 이를 ‘헬스 체크(Health Check)’라고 합니다. 시스템은 헬스 체크 API를 주기적으로 호출하여 응답이 없거나 비정상적인 경우, 해당 컨테이너에 문제가 있다고 판단하고 자동으로 재시작합니다.
구현은 크게 걱정하지 않아도 괜찮습니다. Next.js의 API Routes 기능을 사용하면 별도의 복잡한 서버 설정 없이 아주 간단하게 헬스 체크 엔드포인트를 만들 수 있습니다.
// /src/app/monitor/healthcheck/route.ts
import { NextResponse } from "next/server";
export function GET() {
// 복잡한 로직 없이, "저는 살아있어요!"라는 의미로
// 200 OK 상태와 간단한 메시지만 반환하면 충분합니다.
return NextResponse.json({ status: "ok" }, { status: 200 });
}
이렇게 /monitor/healthcheck
엔드포인트를 만들고, 이 경로를 인프라 담당자에게 알려주면 됩니다. 그러면 담당자는 쿠버네티스 Deployment
설정에 있는 readinessProbe
와 livenessProbe
의 경로를 이 주소로 지정해 줄 것입니다.
만약 이 경로가 잘못 설정되면 프로브(Probe)가 계속 실패하여 파드(Pod)가 Ready
상태로 가지 않거나 무한 재시작에 빠질 수 있습니다. 따라서 로컬 서버를 띄운 다음 http://localhost:3000/monitor/healthcheck
로 접속해 {"status":"ok"}
와 같은 응답이 오는지 확인해 보는 것이 좋습니다.
3단계: GitHub Actions로 CI/CD 파이프라인 구축
이제 GitHub Actions로 빌드, 테스트, 도커 이미지 생성, 그리고 배포까지 이어지는 CI/CD(지속적 통합/지속적 배포) 파이프라인을 구축할 차례입니다.
이때는 인프라팀으로부터 -EKS 클러스터와 ECR(컨테이너 이미지 저장소) 구축이 끝났다면- CI/CD 파이프라인 구축에 필요한 정보(ECR 주소, AWS 권한을 위한 Role 등)를 전달받아야 합니다. GitHub Actions 워크플로우는 이 정보로 작성하기 때문입니다.
아래는 OIDC(OpenID Connect)를 사용해 안전하게 AWS 권한을 얻고, 빌드된 이미지를 ECR에 푸시한 다음, GitOps 저장소의 배포 정보를 업데이트하는 워크플로우 예시입니다.
YAML
# .github/workflows/deploy.yaml
name: Deploy to EKS
on:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
# 아래 값들은 인프라 담당자에게 전달받습니다
ECR_URL: 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com
ECR_REPO: dev-frontend-app
AWS_ROLE: arn:aws:iam::123456789012:role/github-actions-oidc-role
jobs:
build-and-deploy:
name: Build and Deploy
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC 인증을 위해 필요
contents: read
steps:
# 1. 소스코드 체크아웃
- name: Checkout repository
uses: actions/checkout@v4
# 2. Git 커밋 해시를 이미지 태그로 사용하기 위해 짧은 해시 생성
- name: Generate image tag
id: vars
run: echo "sha=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_OUTPUT
# 3. PNPM 설치 및 의존성 설치, 빌드
- name: Setup pnpm and build
uses: pnpm/action-setup@v3
with:
version: 8
- run: pnpm install --frozen-lockfile
- run: pnpm build
# 4. OIDC를 사용해 AWS 자격 증명 구성
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_ROLE }}
aws-region: ap-northeast-2
# 5. AWS ECR에 로그인
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
# 6. Docker 이미지 빌드 및 ECR로 푸시
- name: Build and push image to ECR
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.ECR_URL }}/${{ env.ECR_REPO }}:${{ steps.vars.outputs.sha }}
# 7. GitOps 저장소의 이미지 태그 업데이트 (배포 트리거)
- name: Update GitOps repository
uses: my-company/gitops-image-updater@main # 사내 커스텀 액션 예시
with:
repository: my-company/gitops-repo
branch: main
file_path: apps/frontend/deployment.yaml
image_url: ${{ env.ECR_URL }}/${{ env.ECR_REPO }}:${{ steps.vars.outputs.sha }}
워크플로우를 처음 보면 다소 낯설게 느껴질 수 있지만, 실제로는 간단합니다. 이렇게 요약할 수 있습니다.
- 소스코드 체크아웃: 빌드할 소스코드를 가져옵니다.
- 빌드:
pnpm build
명령으로 Next.js 앱을 빌드합니다. - AWS 인증(OIDC):
role-to-assume
으로 비밀번호 없이 안전하게 AWS 임시 권한을 획득합니다. - ECR 로그인 및 이미지 푸시: 빌드한 도커 이미지를 버전 태그(Git 커밋 해시)와 함께 ECR 저장소에 업로드합니다.
- GitOps 트리거: 마지막 단계인
gitops-image-updater
액션이 핵심입니다. 이 액션은 배포 설정 파일이 있는 별도의 GitOps 저장소로 이동하여, 방금 ECR에 푸시한 새 이미지 주소로deployment.yaml
파일의 이미지 태그를 자동으로 수정하고 커밋합니다. 이 커밋이 바로 ArgoCD에게 “새 버전으로 배포해!”라고 알리는 신호탄 역할을 할 것입니다.
4단계: CI/CD 파이프라인 검증과 GitOps 트리거 확인
GitHub Actions 워크플로우 작성을 마쳤다면 이제 파이프라인이 의도한 대로 잘 작동하는지 검증할 차례입니다. 이 단계는 우리가 만든 자동화 파이프라인에서 CI(지속적 통합) 부분이 성공적으로 완료되었는지, 그리고 CD(지속적 배포)를 위한 ‘신호’가 정확히 전달되었는지 확인하는 과정입니다.
워크플로우를 트리거하고 아래의 세 가지 포인트를 순서대로 확인해 보세요.
GitHub Actions 실행 결과 확인
우선 레포지토리의[Actions] 탭으로 이동하여 방금 실행된 워크플로우가 녹색 체크 표시와 함께 성공적으로 끝났는지 확인합니다. 만약 실패했다면(붉은 X 표시), 오류가 발생한 스텝의 로그를 클릭해 그 원인(오타, 권한 문제, 빌드 실패 등)을 확인하고 수정해야 합니다.
ECR 이미지 푸시 확인
워크플로우가 성공했다면, 다음으로 AWS 콘솔에 접속해 ECR(Elastic Container Registry) 페이지로 이동합니다. 그곳에서 우리 프로젝트의 레포지토리를 선택했을 때, 방금 푸시된 새로운 도커 이미지가 나타났는지 확인합니다. 또, 이미지의 태그(Tag)가 GitHub Actions 워크플로우에서 생성한 Git 커밋 해시(예: a1b2c3d
)와 정확히 일치하는지도 봐야 합니다. 문제가 없다면, 우리 코드가 성공적으로 컨테이너 이미지로 빌드되었고, OIDC 인증을 거쳐 ECR에 안전하게 저장되었음을 의미합니다.
GitOps 레포지토리 커밋 확인
마지막 확인 단계입니다. CI/CD 파이프라인의 마지막 스텝(gitops-image-updater
)에 따라 실제 배포용 GitOps 레포지토리에 변경 사항이 만들어졌는지 봐야 합니다.
해당 GitOps 레포지토리로 이동해 커밋 히스토리를 확인해 보세요. GitHub Actions가 자동으로 생성한 새로운 커밋이 보일 것입니다. 이 커밋의 변경 내용(diff
)을 보면, deployment.yaml
과 같은 매니페스트 파일에 쓰인 이미지 주소가 이전 버전에서 방금 ECR에 푸시한 새로운 이미지 주소로 변경된 것을 확인할 수 있습니다.
이 커밋은 이제 ArgoCD에게 "클러스터를 이 새로운 버전으로 업데이트해!"라고 알려주는 신호(Trigger)의 역할을 합니다.
5단계: ArgoCD 연동과 클러스터 모니터링

이제 마지막 단계입니다. 인프라 담당자에게 요청해 ArgoCD 웹 대시보드에 접속해 보세요. ArgoCD는 GitOps의 철학을 구현한 도구로, GitOps 저장소의 상태를 ‘진실의 원천(Single Source of Truth)’으로 삼아 실제 EKS 클러스터의 상태를 그와 동일하게 유지하는 역할을 합니다. 개발자는 이 대시보드로 애플리케이션 상태를 직관적으로 확인하며, 몇 가지 중요한 작업을 수행할 수 있습니다.
ArgoCD의 애플리케이션 상태 확인: 계층(Hierarchy) 이해
ArgoCD 대시보드 UI를 보면, 리소스들이 마치 나무처럼 연결되어 있습니다. 이는 쿠버네티스의 추상화 계층을 시각적으로 나타낸 것입니다. 여기서 사용하는 리소스의 계층은 이렇습니다.
- Deployment: 가장 상위에 있는 리소스로, 원하는 배포 상태(예: “이 앱을 3개 실행해줘”)를 정의합니다.
- ReplicaSet(rs): Deployment의 지시를 받는 중간 관리자입니다. Pod의 개수를 항상 원하는 상태로 유지합니다. ArgoCD를 사용하다 보면 이전 버전의 ReplicaSet이 비활성화된 채 남아있는 것을 볼 수 있는데요. 이는 빠른 롤백을 위해 남겨둔 일종의 안전장치입니다.
- Pod: 쿠버네티스에서 실행되는 가장 작은 단위입니다. 우리가 만든 Next.js 컨테이너가 바로 이 Pod 안에서 동작합니다. Pod의 상태가
Healthy
로 나오며, 하트 아이콘이 보인다면 정상입니다.
ArgoCD에서 자주 사용하는 기능
- 새로고침(Refresh) 버튼: ArgoCD는 성능 문제로 기본적으로 3분마다 GitOps 저장소의 변경 사항을 감지합니다. 따라서 CI/CD 파이프라인이 방금 동작했다면 아직 ArgoCD가 변경 내역을 감지하지 못했을 수도 있습니다. 이때 Refresh 버튼을 누르면 “지금 당장 Git과 클러스터의 상태를 비교해봐!”라고 ArgoCD에게 명령해 최신 상태를 바로 확인할 수 있습니다.
- 히스토리 및 롤백(History and Rollback) 버튼: 이 버튼은 GitOps의 강력함을 가장 잘 보여주는 기능 중 하나입니다. 여기서 History는 배포 이력, 즉 GitOps 저장소의 과거 커밋 목록을 보여주고, Rollback은 이력 목록에서 특정 버전을 선택하면, ArgoCD가 클러스터의 상태를 그 커밋 시점의 모습으로 되돌립니다.
마치며: 브라우저를 넘어, ‘엔지니어’로
이제 프론트엔드 개발의 역할은 단순히 UI를 만드는 것을 넘어, ‘어디에 어떻게 띄우느냐’를 책임지는 영역까지 확장되었습니다. 인프라 담당자가 따로 있더라도, Docker 이미지 빌드, GitHub Actions 파이프라인 설정, ArgoCD를 통한 배포 상태 확인과 롤백 같은 작업은, 결국 애플리케이션을 가장 잘 아는 프론트엔드 개발자가 직접 관여해야 하는 영역입니다.
오늘 살펴본 과정이 다소 복잡해 보일 수 있지만, 각 단계의 ‘왜’를 이해하면 모든 단계가 서로 연결되어 있음을 알게 됩니다. 결국 이 모든 기술은 더 좋은 기능을 더 빠르고 안정적으로 사용자에게 전달하기 위한 도구일 뿐이니까요.
클라우드 네이티브 시대의 프론트엔드 개발자는 시스템 전반을 이해하고 능동적으로 문제를 해결할 역량을 갖춰야 합니다. UI를 넘어 인프라, 배포, 모니터링까지 아우르는 전체적인 흐름을 이해할 때, 비로소 복잡한 문제를 ‘기술로 풀어가는’ 더 나은 엔지니어로 성장할 수 있기 때문입니다. 이 글이 바로 그 성장 여정에 좋은 나침반이 되기를 바랍니다.
©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.