Loading the catalog…
Loading the catalog…
기존 프로젝트의 CI/CD 파일을 볼 때는 설정이 너무 많아서 어디서부터 이해해야 할지 막막했다. 이번에는 구조가 단순한 todo-app 에서 CI부터 직접 구성하고, Docker 이미지를 만들어 GitHub Container Registry(GHCR)에 게시하는 데까지 진행했다. 아직 서버 배포는 하지 않았다. 지금까지 확인한 범위는 PR 테스트 자동화 → 로컬 Docker 실행 → GHCR 이미지 수동 게시 다. 1. 먼저 CI가 언제 무엇을 할지 정했다 todo-app 은 Java 17을 사용하는 단일 Gradle 프로젝트다. 처음부터 여러 작업을 넣기보다, PR을 올렸을 때 테스트가 통과하는지만 확인하기로 했다. name: CI on: pull_request: branches: [main, develop] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/setup-java@v6 with: distribution: temurin java-version: '17' cache: gradle - run: ./gradlew test 여기서 branches: [main, develop] 은 PR의 대상 브랜치 를 뜻한다. develop 이나 main 에 직접 푸시했을 때 실행한다는 뜻은 아니다. 기능 브랜치에서 작업한 뒤 develop 을 대상으로 PR을 만들면 CI가 실행된다. main 은 나중에 실제 배포할 변경을 병합하는 브랜치로 사용할 계획이다. GitHub Actions 워크플로 문법 (https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax) ./gradlew test 를 사용한 이유는 저장소에 포함된 Gradle Wrapper로 이 프로젝트의 테스트를 실행하기 위해서다. gradlew 만 실행하면 어떤 작업을 할지 지정되지 않는다. 현재 워크플로는 저장소 루트에서 실행되므로 별도의 프로젝트 경로도 필요하지 않다. 처음에는 PR이 저절로 생성되는 줄 알았는데, 푸시와 PR 생성은 별개였다. 작업 브랜치를 푸시하고 develop 으로 PR을 만들어야 이 흐름을 확인할 수 있었다. 2. 테스트가 느려서 Gradle 캐시를 추가했다 처음 CI를 실행했을 때는 테스트 코드가 간단한데도 시간이 꽤 걸렸다. CI는 내 컴퓨터가 아닌 새 실행 환경에서 시작하므로, Gradle 실행 준비와 의존성 다운로드에도 시간이 든다. 그래서 actions/setup-java 에 cache: gradle 을 추가했다. 관찰한 실행 기록에서는 첫 실행보다 캐시를 복원한 재실행이 빨랐다. 다만 캐시를 추가했다고 모든 PR이 항상 같은 속도로 빨라지는 것은 아니다. PR에서 만든 캐시는 해당 PR의 merge ref에 묶여 다른 PR에서 그대로 재사용되지 않을 수 있다. GitHub Actions 캐시 범위 설명 (https://docs.github.com/en/actions/reference/workflows-and-actions/dependency-caching#restrictions-for-accessing-a-cache) 관찰한 실행 대략적인 전체 시간 해석 캐시 추가 전 PR 실행 82초 Gradle 준비와 테스트를 처음부터 수행 캐시 추가 후 첫 실행 비슷한 수준 저장된 캐시가 없어 즉시 빨라지지는 않음 같은 PR 재실행 43초 캐시 복원 효과를 확인 새로운 PR 실행 100초 PR이 바뀌면 캐시를 다시 받지 못할 수 있음 develop 에 푸시할 때도 CI를 실행해 공유 캐시를 만드는 방법을 검토했지만, 지금은 PR마다 테스트한다는 원래 목적을 유지하기로 했다. 캐시를 넣었다는 사실과 실제 실행시간 개선은 구분해서 봐야 한다는 점을 배웠다. 3. Docker 이미지로 로컬 실행을 확인했다 다음으로 Dockerfile 과 .dockerignore 를 만들었다. Dockerfile은 두 단계로 구성했다. 단계 하는 일 빌드 단계 JDK 17 환경에서 ./gradlew bootJar 로 실행 가능한 JAR 생성 실행 단계 JRE 17 환경에 생성된 JAR만 복사해 애플리케이션 실행 WORKDIR /app 은 컨테이너 내부 에서 이후 명령을 실행할 작업 폴더다. 내 Mac의 /app 폴더를 뜻하지 않는다. COPY 로 빌드에 필요한 파일을 컨테이너에 가져오는 이유는 이미지 빌드가 내 로컬 프로젝트 폴더에서 직접 실행되는 방식이 아니기 때문이다. 처음에는 Docker 엔진이 실행되지 않아 소켓 연결 오류가 났다. Docker Desktop을 실행한 뒤 다음 명령으로 이미지 빌드와 접속을 확인했다. docker build -t todo-app:local . docker run --rm -p 127.0.0.1:18080:8080 todo-app:local 브라우저에서는 http://127.0.0.1:18080 으로 접속했다. 18080 은 내 컴퓨터에서 접속하는 포트, 8080 은 컨테이너 안의 애플리케이션 포트다. 127.0.0.1 을 붙여 내 컴퓨터에서만 접근하도록 했다. IntelliJ에서 애플리케이션을 실행하는 것과 비슷하게 로컬에서 접속하지만, 이번에는 컨테이너 안에서 실행된 앱 에 접속한 것이다. 4. GHCR에 이미지를 게시했다 로컬에서 이미지를 실행한 다음에는 GitHub Actions가 이미지를 빌드해 GHCR에 게시하는 워크플로를 추가했다. on: workflow_dispatch: permissions: contents: read packages: write workflow_dispatch 를 사용했으므로 PR 병합만으로 이미지를 게시하지는 않는다. GitHub Actions 화면에서 직접 실행해야 한다. 워크플로는 GitHub 실행 환경에서 저장소의 Dockerfile로 새 이미지를 빌드 하고, ghcr.io 에 게시한다. 로컬에서 만들었던 todo-app:local 이미지를 그대로 업로드하는 것은 아니다. 이미지 태그에는 커밋 SHA를 사용해 어느 코드로 만든 이미지인지 구분한다. 게시 워크플로의 성공을 확인했고, GitHub의 Packages 화면에서도 이미지가 보이는 것을 확인했다. 여기까지는 이미지 저장소에 게시한 것 이지, EC2 서버에 배포한 것은 아니다. GitHub Container Registry 문서 (https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) 기존 프로젝트와 무엇이 달랐나 프로젝트 CI 구성 이미지와 배포 구성 todo-app 단일 Gradle 프로젝트에서 PR 대상이 develop / main 일 때 ./gradlew test Docker 이미지 로컬 실행 확인, GHCR에 수동 게시까지 완료. 서버 배포는 아직 없음 PARUT 여러 서비스 중 변경된 서비스를 감지해 빌드, 테스트용 PostgreSQL/Redis도 사용 워크플로 설정상 ECR에 이미지를 저장하고 SSM 명령으로 EC2 배포 bonae-dream-logistics 여러 모듈을 빌드하고 지정된 모듈의 테스트를 실행 워크플로 설정상 GHCR에 이미지를 저장하고 SSH/SCP로 EC2 배포 두 기존 프로젝트는 서비스나 모듈이 여러 개라 변경 감지, matrix, 서비스별 경로, 테스트용 외부 서비스가 필요하다. 반면 todo-app 은 단일 애플리케이션이라 처음부터 그 구조를 가져올 이유가 없었다. 기존 프로젝트의 설정을 복사하기보다 현재 프로젝트에서 필요한 단계가 무엇인지 판단하는 연습 이 되었다. 위 비교는 각 저장소의 워크플로 설정을 기준으로 한 것이다. 기존 프로젝트의 실제 서버 배포 성공 여부까지 이번에 검증한 것은 아니다. 다음 작업: 같은 앱을 두 방식으로 배포해보기 다음에는 EC2에 실제로 배포해볼 예정이다. 비교하려는 방식은 두 가지다. 방식 이미지 저장소 서버에서 배포 명령을 실행하는 방법 배우려는 점 1안 GHCR SSH 이미 게시한 이미지를 서버에서 받아 실행하는 전체 흐름 2안 AWS ECR AWS Systems Manager(SSM) AWS의 이미지 저장소와 원격 명령 방식, 권한 설정 이는 Todo 앱을 두 버전으로 개발한다는 뜻이 아니다. 같은 앱과 같은 서버를 기준으로 이미지 저장소와 원격 실행 방식만 바꿔 비교 해보려는 것이다. 그래야 어떤 설정과 권한이 추가되는지, 운영 방식이 어떻게 달라지는지 직접 이해할 수 있다. 먼저 GHCR + SSH로 배포를 완성하고, 이후 ECR + SSM을 실습할 계획이다. 두 배포 워크플로를 동시에 자동 실행해 같은 서버의 컨테이너를 서로 덮어쓰게 하지는 않을 것이다. 실제 배포 전에는 EC2 비용과 보안 설정, 이미지 접근 권한부터 확인해야 한다. 최종적으로는 develop 에서 개발하고, 검증한 변경을 main 에 병합할 때 배포하는 흐름을 목표로 한다. 이번 실습에서 가장 크게 배운 점은 CI 성공, Docker 실행, 이미지 게시, 서버 배포는 각각 다른 완료 단계 라는 것이다. 지금은 앞의 세 단계까지 확인했다. 다음 TIL에는 실제 EC2 배포 결과와 두 방식의 차이를 기록해보려 한다.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
[TIL] 작은 Todo 앱으로 CI부터 Docker 이미지 게시까지 직접 연결해보기. 기존 프로젝트의 CI/CD 파일을 볼 때는 설정이 너무 많아서 어디서부터 이해해야 할지 막막했다. 이번에는 구조가 단순한 todo-app 에서 CI부터 직접 구성하고, Docker 이미지를 만들어 GitHub Container Registry(GHCR)에 게시하는 데까지 진행했다. 아직 서버 배포는 하지 않았다. 지금까지 확인한 범위는 PR 테스트 자동화 → 로컬 Docker 실행 → GHCR 이미지 수동 게시 다. 1. 먼저 CI가 언제 무엇을 할지 정했다 todo-app 은 Java 17을 사용하는 단일 Gradle 프로젝트다. 처음부터 여러 작업을 넣기보다, PR을 올렸을 때 테스트가 통과하는지만 확인하기로 했다.…
Open source