[17주차 Day3] Docker를 활용한 컨테이너화 실습

반 히·2024년 6월 21일

데브코스

목록 보기
51/58
post-thumbnail

📚 Part 5 인수 테스트 자동화


📁 이미지 레지스트리 구성

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

  • 요구사항 (requirement) 대로 기능이 구현되었는지를 확인하는 과정
    • 전체 시스템을 사용자 관점에서 시험하는 블랙박스 테스트를 포함
  • 이것을 자동화하는 것은 쉽지 않은 일이지만 CI/CD의 구축을 위해 반드시 필요
    • 전통적으로는 QA 담당자나 사용자의 수작업에 의존해 왔음
  • 사용자 인수 테스트를 자동화하는 것이 어려운 요인
    • 사용자 참여: 기술적 측면과 비기술적 측면에 대한 요구사항의 최종 확인은 실사용자여야 함
    • 의존성 통합: 테스트할 애플리케이션은 모든 의존성을 포함하여 실행되어야 함
    • 스테이징 환경: 프로덕션 환경과 동일한 스테이징 (테스트) 환경에서 이루어져야 함
    • 애플리케이션 동일성: 한 번만 빌드하여 프로덕션에서와 동일한 바이너리를 이용해야 함
    • 틸리스 준비: 인수 테스트를 통과한 애플리케이션은 즉시 릴리스 준비가 되어야 함

📌 학습 목표

  • 도커 레지스트리의 구성
    • 빌드한 이미지를 저장 및 관리할 수 있는 저장소를 셋업해 봄
    • 여러 가지의 다른 공개/상용 서비스를 이용할 수도 있으나, 이 과정을 통해 CI/CD의 과정과 k8s 클러스터의 운용에 대하여 좀 더 깊이 이해하는 것이 목표
  • 애플리케이션 패키지 빌드 및 이미지 푸시
    • 소스 수준에서 테스트 (UT)가 완료된 애플리케이션을 독립 및 통일된 환경에서 실행될 수 있도록 컨테이너화
    • 응용 소프트웨어를 (및 전체 의존성을) 컨테이너에 포함하여 이미지로 만들고 레지스트리에 저장
  • UAT 프레임워크 적용
    • 보다 체계적이고 완성도가 높은 인수 테스트를 위한 프레임워크 활용
      • 응용 소프트웨어의 개발 환경에 따라 크게 달라지는 부분이지만 예제를 중심으로 시나리오 이해

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

  • 버전 관리, 접근 제어 등의 기능을 가지는 소프트웨어 개발 산출물(예: 패키지)을 발행(푸시)하거나 인출 (풀) 할 수 있는 저장소 및 관리 기법이 필요
  • 파이프라인의 모든 단계에서 동일한 바이너리가 사용되는 것을 보장함으로써 지속적 인도 프로세스에서 매우 중요한 역할을 함

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

  • 컨테이너화된 소프트웨어의 산출물인 도커 이미지를 관리할 수 있는 리포지토리-
  • 클라우드 방식 레지스트리
    • Docker Hub (및 이와 유사한 기능을 제공하는 레지스트리 서비스들)
    • 상용 클라우드에서 제공하는 서비스 (예: AWS ECR, GCP Artifact Registry, Azure Container Registry, ...)
  • 자체 호스팅 방식 레지스트리
    • 사내 네트워크가 아닌 외부에 소프트웨어를 보관하는 것을 금지하는 정책을 갖고 있는 경우에는 유일한 해결 방법
    • 직접 관리해야 하는 부담이 있고 접근 제어 및 인증서 설정 등의 번거로운 작업이 수반됨

📌 데이터 볼륨과 SSL 인증서

  • 호스트의 디렉토리를 레지스트리에 볼륨으로 공유
    • 레지스트리에 저장된 데이터는 컨테이너 및 포드 등이 사멸하는 경우에도 유지할 수 있도록
    • 실제 개발 환경에서는 어딘가 저장 장소를 마련해 두고 주기적으로 백업하는 방법을 택할 것이겠으나, 우리 실습에서는 호스트의 파일시스템 내 특정 위치에 데이터가 저장되도록 설정
    • PV를 정의하고 PVC를 설정하여 레지스트리 서버 컨테이너에서 이용하도록 볼륨 마운트
  • 자가 서명된 (self-signed) 인증서 발급하여 레지스트리 서버에 설치
    • 실제 운용 환경에서는 CA (certificate authority) 로부터 발급받은 인증서를 설치하고 주기적으로 갱신하여 공인할 수 있는 인증을 이용할 것
    • 우리 실습에서는 간이로 자가 서명 인증서를 발급하고 이것을 레지스트리 서버에 설치
      • 다음 실습에서는 이 레지스트리를 이용하려는 쪽의 컨테이너에도 인증 설정

📌 접근 제어

  • 보통은 login id와 passwd의 쌍으로 사용자 인증
    • 로그인하는 사용자에 따라 서로 다른 권한을 적용


📁 간단한 인수 테스트

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

  1. 개발자가 변경한 코드를 GitHub 에 푸시
  2. Jenkins 가 변경을 감지하고 코드를 인출해 빌드를 시작, 코드를 점검 (단위테스트 수행)
  3. Jenkins 가 빌드를 완료하여 도커 이미지를 생성
  4. Jenkins 가 생성한 이미지를 레지스트리로 푸시
  5. Jenkins 가 스테이징 환경을 구성하고 도커 컨테이너 실행
  6. 스테이징 환경의 도커 호스트가 이미지를 가져다가 (풀) 컨테이너를 실행
  7. Jenkins 가 스테이징 환경에서 실행 중인 애플리케이션을 대상으로 인수 테스트를 실행


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

📌 사용자-대면 테스트

  • REST API 의 경우에는 curl 에 의한 테스트로도 (기술적으로는) 어느 정도 블랙박스 테스트가 가능
  • 그러나, 일반적으로는 이런 테스트에 의존할 수 없음
    • 읽고 이해하기가 어려움 (특히 비기술 영역 사용자에게)
    • 유지보수에 불리함
  • 사용자와 함께 작성할 수 있고 사용자가 이해할 수 있는 테스트 작성 방법이 필요
    • 특정한 목적 (사업적 가치)을 반영하는 인수 테스트

📌 BDD (Behavior-Driven Development)

  • 사용자 (또는 프로덕트 오너) 가 인수 기준을 제시
  • 위 인수 기준으로부터 개발자는 픽스처 (fixture) 또는 스텝 정의 (step definitions) 라고
    부르는 사용자 친화적인 DSL (domain-specific language) 와 프로그래밍 언어를 통합해서
    테스트를 작성
  • 이를 도와주는 도구들
    • Cucumber (이 실습에서 이용)
    • Selenium (사용자 인터페이스를 포함하는 애플리케이션에 널리 이용, 여기에서는 다루지 않음)

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

  • 인수 기준 생성
    • 특정 파일에 비즈니스 사양을 명세
  • 스텝 정의 작성
    • 기능 사양을 실행할 수 있는 Java 바인딩을 생성
  • 자동 인수 테스트 실행
    • Gradle 설정에 라이브러리 의존성 명세 추가
    • Gradle 태스크와 Junit 테스트 러너를 추가
  • (중요) 여기에서는 Cucumber를 이용한 테스트가 아니라 인수 테스트 자동화에 관심과 중점

📌 파이프라인 설정 복원

  • 앞 페이지의 내용을 참고로 Jenkinsfile 을 완성
    • agent 에 총 세 개의 서로 다른 컨테이너를 포함하는 포드의 스펙 작성
    • environment 에 커스텀 레지스트리의 접근 URI 와 artifact (도커 이미지)에 붙일 태그를 지정
    • 총 9개의 스테이지 ("Compile" 부터 "Acceptance Test" 까지)를 포함
    • 후처리 (post) 작업으로 "docker stop" 을 통해 스테이징 환경을 정리
  • 원래 있었던 Jenkins 아이템 ("간단한 인수 테스트" 실습의 "작업용 임시 파이프라인 만들기" 참고)의 "Poll SCM" 설정을 복원
    • 매 5분 경과 후 GitHub repo에 변경사항 있었는지를 검사, 있는 경우 빌드 작업을 트리거
  • 위 Jenkinsfile 과 그 사이 신규 작성 또는 변경한 파일들을 GitHub repo에 push

📌 TDD (Test-Driven Development)

  • (중요) 인수 테스트는 기술보다 사람이 중심
    • 지속적 인도 프로세스의 다른 단계들도 마찬가지
  • 소프트웨어 개발 수명 주기 중 어느 시점에 테스트 작성?
    • 코딩 전에? 코딩 후에?
    • TDD는 특히 인수 테스트에 적합
  • 인수 기준 사양을 먼저 작성
    • 인수 테스트 통과를 기능 구현 완료로 간주
    • 이슈 추적 도구의 요청 티켓에 기능 사양을 첨부하는 방법도

0개의 댓글