Day 53 - CI 파이프라인 기초, 인수 테스트

이유승·2025년 2월 25일

* 프로그래머스, 타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 5기 강의 수강 내용을 정리하는 포스팅.

* 원활한 내용 이해를 위해 수업에서 제시된 자료 이외에, 개인적으로 조사한 자료 등을 덧붙이고 있음.

📚 CI 파이프라인 구축

📁 CI 파이프라인 기초

📌 CI 파이프라인이란?

CI(Continuous Integration, 지속적 통합) 파이프라인은 코드 변경 사항이 자동으로 빌드, 테스트, 배포되는 과정을 자동화하는 시스템이다.
개발자가 새로운 기능을 추가하거나 버그를 수정하면, CI 시스템이 이를 검증한 후 코드베이스에 병합하는 방식으로 동작한다.

🚀 파이프라인(pipeline)의 개념

CI/CD에서 "파이프라인"은 하나의 프로세스가 완료되면 다음 단계로 자동 연결되는 일련의 절차를 의미한다.
예를 들어, 다음과 같은 순서로 진행될 수 있다.

docker build → docker push → kubectl create → kubectl expose

📌 CI 파이프라인의 동작 방식 (Jenkins 예시)

Jenkins를 활용한 기본 CI 파이프라인은 다음과 같은 단계로 이루어진다.
1. 코드 변경 감지: GitHub 등 코드 저장소에서 변경 사항을 감지
2. 빌드(Build) 수행: 소스를 컴파일 및 패키징
3. 테스트 수행: 단위 테스트 및 통합 테스트 자동 실행
4. 컨테이너 이미지 생성: Docker를 사용해 애플리케이션을 컨테이너화
5. 배포(Deployment) 수행: 쿠버네티스(k8s) 등에 배포


📌 간단한 파이프라인 구축 실습

간단한 웹 애플리케이션을 만들고 CI 파이프라인을 적용하는 실습을 진행한다.

🎯 실습 개요

  • 두 개의 숫자를 입력받아 덧셈 연산을 수행하는 간단한 웹 애플리케이션을 구현
  • 아직 기능을 완성하는 것이 아니라, CI 파이프라인 설정이 목적
  • 입력은 query string, 출력은 텍스트

🛠 실습 단계

  1. GitHub 저장소 생성 및 초기 코드 업로드
  2. Gradle을 이용한 빌드 환경 구성 (JDK 필요)
  3. Jenkins를 사용해 컨테이너 환경 구축
    • 애플리케이션 빌드 및 컨테이너 이미지 생성
    • 생성된 컨테이너 이미지를 Jenkins Agent에 적용
  4. 다음 단계: 테스트 자동화 및 테스트 리포트 발행

📌 GitHub 접근용 SSH Key 생성

🔑 SSH 인증 방식 개요

GitHub의 비공개(private) 저장소에 접근할 때는 HTTPS보다 SSH 프로토콜을 더 많이 사용한다.
SSH 인증은 username/password 방식보다 보안성이 높고, public-private key 기반으로 동작한다.

🛠 SSH Key 생성 및 등록 방법

  1. ssh-keygen을 사용하여 public-private keypair 생성
    (기존 키가 있으면 사용 가능)
  2. GitHub 로그인 후 설정 변경
    • SettingsSSH and GPG keysNew SSH Key
  3. id_xxxx.pub 파일의 공개 키를 GitHub에 등록
  4. 주의 사항: private key는 외부에 노출되지 않도록 관리해야 함

📌 빌드 에이전트의 개선

CI/CD 환경에서 빌드를 효율적으로 수행하기 위해 커스텀 에이전트 컨테이너를 제작하여 적용한다.

🎯 커스텀 빌드 에이전트란?

  • Jenkins CI 환경에서 일관된 빌드 환경을 유지하기 위한 Docker 컨테이너
  • 빌드에 필요한 도구들을 미리 설치하여 빌드 시간을 단축

🛠 빌드 에이전트 컨테이너 제작 과정

  1. Dockerfile 작성 (필요한 패키지 및 환경 포함)

  2. 컨테이너 이미지 빌드 및 푸시

    docker build -t my-custom-agent .
    docker push my-custom-agent
    
  3. Jenkins에서 해당 에이전트를 사용하도록 설정


📁 CI 파이프라인 - 단위 테스트

📌 단위 테스트란?

단위 테스트(Unit Testing)는 개별적인 코드 단위를 검증하는 테스트 기법이다.
주로 함수나 모듈 수준에서 실행되며, 코드의 잠재적 결함을 조기에 발견하는 데 중요한 역할을 한다.

✅ 단위 테스트의 필요성

코드를 작성할 때 조기에 오류를 발견하여 유지보수 비용 절감
전체 애플리케이션의 품질과 안정성 향상
테스트 커버리지(Test Coverage) 확보: 작성된 코드가 테스트 코드에 의해 어느 정도 검증되는지를 나타내는 지표

🛠 단위 테스트 vs. 다른 테스트

테스트 종류 설명
단위 테스트 함수/클래스 단위의 최소 기능 검증
통합 테스트 여러 모듈이 함께 동작하는지 검증
인수 테스트 사용자 관점에서 기대한 기능이 정상 동작하는지 검증
👉 다음 실습에서는 테스트 커버리지까지 다룰 예정


📁 CI 파이프라인 - 코드 품질 확보

📌 코드 품질이란?

좋은 코드란 단순히 "잘 동작하는 코드"가 아니라, 가독성이 높고 유지보수가 쉬운 코드를 의미한다.

🎯 코드 품질의 주요 요소

기능성: 요구사항에 맞게 올바르게 동작하는가?
가독성: 다른 개발자가 쉽게 이해할 수 있는가?
재사용성: 중복을 최소화하고 유지보수가 쉬운가?
테스트 가능성: 단위 테스트가 충분히 적용될 수 있는가?

✅ 좋은 코드 vs. 나쁜 코드 예시

복사
편집
// ❌ 나쁜 코드: 가독성이 낮고, 의미 없는 변수명
int a = 10;
int b = 20;
int c = a + b;
System.out.println(c);

// ✅ 좋은 코드: 변수명을 명확하게 정의
int firstNumber = 10;
int secondNumber = 20;
int sum = firstNumber + secondNumber;
System.out.println(sum);

📌 코드 컨벤션 준수

모든 프로젝트에서 동일한 코드 스타일을 유지하는 것은 필수적이다.

🛠 코드 스타일 가이드 예시

Java: Google Java Style Guide
JavaScript/TypeScript: Airbnb 스타일 가이드, Prettier
Python: PEP8

🚀 코드 품질을 위한 도구

ESLint (JavaScript)
Checkstyle (Java)
Pylint (Python)

📌 결론 및 다음 단계

이번 강의에서는 CI 파이프라인의 기초 및 단위 테스트의 중요성을 다루었다.
다음 강의에서는 테스트 커버리지 확장 및 코드 품질 분석 도구 적용을 다룰 예정.

👉 지속적으로 테스트 자동화를 추가하여 CI/CD의 완성도를 높이는 것이 목표!







📚 인수 테스트 자동화

📁 이미지 레지스트리 구성

📌 인수 테스트 (UAT; User Acceptance Test)

인수 테스트는 요구사항대로 기능이 구현되었는지를 확인하는 과정이다.
사용자의 관점에서 애플리케이션이 정상적으로 동작하는지를 검증하는 블랙박스 테스트를 포함한다.

🎯 인수 테스트 자동화의 어려움

  • 사용자 참여: 실사용자가 최종적으로 기능을 검증해야 함
  • 의존성 통합: 모든 의존성을 포함하여 애플리케이션을 실행해야 함
  • 스테이징 환경: 프로덕션과 동일한 환경에서 테스트 수행 필요
  • 애플리케이션 동일성: 빌드한 바이너리가 프로덕션과 동일해야 함
  • 릴리스 준비: 인수 테스트를 통과한 애플리케이션은 즉시 배포 가능해야 함

📌 학습 목표

  1. 도커 레지스트리 구성

    • 빌드한 이미지를 저장하고 관리할 수 있는 저장소 구축
    • CI/CD 및 k8s 클러스터 운영의 이해
  2. 애플리케이션 패키지 빌드 및 이미지 푸시

    • 소스 코드에서 테스트 완료된 애플리케이션을 컨테이너화
    • 이미지 레지스트리에 저장 후 배포 가능하도록 구성
  3. UAT 프레임워크 적용

    • 자동화된 인수 테스트를 위한 프레임워크 활용
    • 다양한 개발 환경에서의 인수 테스트 시나리오 이해

📌 아티팩트 리포지토리 (Artifact Repository)

CI/CD 파이프라인에서 소프트웨어 개발 산출물(예: 패키지, 바이너리 등)을 관리하는 저장소이다.
파이프라인의 모든 단계에서 동일한 바이너리를 사용하여 일관된 빌드 및 배포 환경을 보장한다.


📌 도커 레지스트리 (Docker Registry)

도커 레지스트리는 컨테이너 이미지를 저장하고 관리하는 리포지토리이다.

🎯 레지스트리 유형

  1. 클라우드 레지스트리

    • Docker Hub (기본적인 퍼블릭 레지스트리)
    • AWS ECR, GCP Artifact Registry, Azure Container Registry
  2. 자체 호스팅 레지스트리

    • 외부 저장이 금지된 환경에서 필수적
    • 직접 관리해야 하며, 접근 제어 및 인증 설정 필요

📌 데이터 볼륨과 SSL 인증서

  1. 데이터 볼륨 관리

    • 레지스트리 데이터를 호스트의 특정 디렉토리에 저장
    • 컨테이너가 삭제되어도 데이터 유지 가능
  2. SSL 인증서 적용

    • 실제 환경에서는 CA(Certificate Authority)에서 발급받은 인증서 사용
    • 실습에서는 자가 서명된 SSL 인증서를 레지스트리 서버에 설치
    • 이후 컨테이너에서도 인증서 설정 적용

📌 접근 제어

  • 보통 로그인 ID와 비밀번호 기반 인증
  • 사용자별로 다른 권한을 적용하여 보안 유지

📁 간단한 인수 테스트

📌 Jenkins 파이프라인에서의 인수 테스트

  1. GitHub에 코드 푸시 (개발자가 코드 변경)
  2. Jenkins가 변경 감지 및 빌드 수행
    • 코드를 가져와 단위 테스트 실행
  3. 도커 이미지 생성 및 레지스트리로 푸시
  4. 스테이징 환경에서 컨테이너 실행
    • Jenkins가 스테이징 환경을 구성하고 컨테이너 실행
  5. 스테이징 환경에서 인수 테스트 실행
    • 애플리케이션이 정상 동작하는지 검증

📁 인수 테스트 프레임워크 적용

📌 사용자-대면 테스트

REST API의 경우 curl 등을 이용해 테스트할 수 있지만,
비기술적 사용자에게는 이해하기 어렵고 유지보수에 불리하다.

👉 해결책: 사용자가 직접 읽고 이해할 수 있는 인수 테스트 작성


📌 BDD (Behavior-Driven Development)

BDD(행동 주도 개발)는 사용자의 요구사항을 코드에 반영하기 위한 방법론이다.

🎯 BDD 개요

  1. 사용자(또는 PO)가 인수 기준(기능 요구사항) 정의
  2. 개발자가 픽스처(Fixture) 또는 스텝 정의(Step Definitions) 작성
  3. DSL(Domain-Specific Language)을 이용해 테스트 코드 작성

🛠 BDD 지원 도구

도구설명
Cucumber인수 테스트 자동화를 위한 대표적인 BDD 도구
SeleniumUI 테스트 자동화에 주로 사용

👉 실습에서는 Cucumber를 이용한 인수 테스트를 다룸


📌 Cucumber를 이용한 인수 테스트 생성

🎯 테스트 과정

  1. 인수 기준 정의
    • 비즈니스 요구사항을 기반으로 .feature 파일 작성
  2. 스텝 정의 작성
    • Java 또는 다른 언어로 기능 사양을 실행할 수 있는 코드 작성
  3. 자동 인수 테스트 실행
    • Gradle을 사용하여 Cucumber 실행

🛠 Gradle 설정 예시

dependencies {
    testImplementation 'io.cucumber:cucumber-java:7.0.0'
    testImplementation 'io.cucumber:cucumber-spring:7.0.0'
}

📌 파이프라인 설정 복원

🎯 Jenkinsfile 설정

총 3개의 컨테이너를 포함하는 Pod 스펙 작성
커스텀 레지스트리의 접근 URI 및 태그 설정
총 9개 스테이지 설정 (Compile부터 Acceptance Test까지)
후처리(Post-Stage) 작업
docker stop을 사용해 스테이징 환경 정리
GitHub Poll SCM 설정 복원
매 5분마다 변경 사항 확인 및 자동 빌드 실행

📌 TDD (Test-Driven Development)

TDD는 코드 작성 전에 테스트를 먼저 작성하는 방식이다.
인수 테스트는 기술보다 사람 중심이므로 TDD가 적합하다.


🎯 TDD 기반 인수 테스트

인수 기준 사양을 먼저 작성
인수 테스트가 통과되면 기능 구현 완료
이슈 추적 도구와 연동하여 기능 명세 관리


📌 결론 및 다음 단계

이번 강의에서는 인수 테스트 자동화 및 도커 레지스트리 구성을 다루었다.
다음 강의에서는 CI/CD 파이프라인을 개선하고 TDD 적용을 진행할 예정.
👉 CI/CD 파이프라인을 고도화하고 자동화를 강화하는 것이 목표!

profile
프론트엔드 개발자를 준비하고 있습니다.

0개의 댓글