[CI/CD] #1 CI의 개념

keen.log·2024년 2월 8일
0

CI/CD

목록 보기
1/7
post-thumbnail
이 게시물은 [초보를 위한 젠킨스 2 활용 가이드 2/e]를 참고해서 작성한 내용임을 밝힙니다.

CI = Continuous Integration


1. CI가 발생된 이유

보다 빠르고 정확한 개발을 위해 CI가 탄생했다 🤓🤓

🔎 CI가 나오기 전 소프트웨어 개발 환경에 대해 먼저 알아보자.

- 소프트웨어 개발 주기(Software Development life Cycle, 이하 SDLC)

SDLC는 소프트웨어 개발의 계획, 개발, 테스트, 배포 단계를 총칭하는 말이다.

  1. 요구사항 분석
    해당 프로젝트에서 달성해야 하는 요구사항을 분석한 후 프로젝트의 목표를 설정
  2. 설계
    시스템 아키텍트와 설계자가 정교하게 구현해야 할 기능들 정리 및 전체 계획 수립
  3. 구현
    PM(Project Manager)가 개발자에게 일을 분배한 후 개발 진행
  4. 테스트
    소프트웨어의 모든 기능을 테스트
  5. 진화
    혹은 유지 보수. 소프트웨어를 계속해서 개선

- 소프트웨어 개발에서의 폭포수 모델

폭포수(Waterfall) 모델은 명확하게 정의된 절차가 한 방향으로 진행되는 소프트웨어 개발 방법이다.

Waterfall 모델의 특징은

  • [요구사항 분석 및 설계 단계] 이후 어떤 추가나 수정도 허용되지 않는다.
  • 개발 기간 동안 테스트 팀이 할 일이 생기는 경우는 드물다.
    개발 단계가 끝난 후 소스코드 통합 과정에서 다양한 통합 이슈가 발생된다.

❗수십 년 동안 훌륭히 작동했던 Waterfall 모델은 최근 소프트웨어 기술이 급속하게 발전하면서, 현재는 충분한 시간과 자원이 주어지지 않기에 Agile 방법론에게 밀리고 있다.

Waterfall 모델의 장단점은

장점단점
요구사항이 문서로 잘 정리되고 변하지 않음실제로 동작하는 소프트웨어가 SDLC의 마지막에 가서 완성
관리자, 테스트팀, 개발팀, 빌드, 릴리스 팀, 배포 팀을 유지할 자원이 충분히 주어짐불확실성이 매우 큼
기술이 고정돼 잘 변하지 않음새로운 요구 사항이 자주 발생하는 영역의 경우 적합하지 않음
모호한 요구 사항이 존재하지 않음전체 개발이 끝난 후에야 통합이 진행됨

- Agile 방법론의 대두(Waterfall -> Agile)

Agile은 "빠르고 쉬움"을 의미한다. 즉, Agile의 핵심은 빠르고 유연하며 계속해서 발전하는 소프트웨어 개발이다.

위 그림을 보면 요구 사항 분석/설계에 쓰이는 시간이 없다. 즉, 짧은 계획 후 iteration을 반복하며 프로젝트를 진행하고 덕분에 특정 기간에 할 일이 없어 놀고 있는 팀원이 생기지 않는다!!

하나의 iteration에서의 목표는 "기능의 개발, 테스트, 릴리스를 완료하는 것"이다.

다음은 Agile 12가지 원칙이다.
1. 고객을 만족시키기 위해 소프트웨어를 빠르고 지속적으로 배포한다.
2. 새로운 요구 사항은 개발 후기에도 기꺼이 받아들인다.
3. 동작 가능한 소프트웨어를 몇 달 주기가 아닌 몇 주 주기로 배포한다.
4. 업무 담당자와 개발자 간의 긴밀한 소통을 지향한다.
5. 믿을 수 있는 동기부여된 개인들로 구성된 팀이 소프트웨어를 개발한다.
6. 직접 만나 얼굴을 보며 이야기하는 것이 최선의 의사소통이다.
7. 동작하는 소프트웨어가 가장 중요한 진척의 척도다.
8. 일정한 속도를 유지함으로써 지속 가능한 개발을 추구한다.
9. 좋은 기술과 설계를 향해 지속적으로 관심을 기울인다.
10. 단순함(하지 않는 일을 늘리는 기법)을 중요시한다.
11. SOT(Self-Organized Team)을 추구한다.
12. 새로운 환경에 지속적으로 적응한다.

앞서 말한 Waterfall과는 확연히 다른 부분이 많이 보이지만 가장 중요한 것은 가장 눈에 띄는 것은 아무래도 2번 "새로운 요구 사항은 개발 후기에도 기꺼이 받아들인다" 인 것 같다. 설계 단계 이후 어떤 요구 사항도 받지 않는 Waterfall에 비해 트렌드가 자주 바뀌는 최신에 Agile이 더 인기 있는 가장 큰 이유이다.

Agile의 장점은 다음과 같다.

  • 기능의 빠른 구현과 데모
    Agile 방법론에서는 소프트웨어 프로젝트가 기능으로 구분된다. 하나 혹은 그 이상의 기능을 한 주 혹은 한 달 동안 구체화하고 배포하는 것이 주요한 개념이다.
  • 적은 리소스 소요
    개발 팀과 테스트 팀, 빌드, 릴리스, 배포 팀이 따로 구분되지 않는다. 대신 하나의 팀이 약 8명으로 구성되며, 각각의 구성원은 모든 역할을 수행할 수 있다.
  • 팀워크 향상과 상호 교육
    하나의 팀에 8명 정도의 인원이 있기 때문에 각 팀원이 역할을 바꿔가며 프로젝트를 진행하고, 이 과정에서 서로가 모두의 경험을 공유하며 배운다(다양한 경험을 많이!! 나에게 꼭 필요한 좋은 방법론인 듯 하다🤓)
  • 요구 사항이 자주 변경되는 프로젝트에 적합
    짧은 시간에 한 번의 iteration이 진행되기에 기능을 변경하거나, 아예 제거해도 전체 프로젝트에 큰 영향을 주지 않는다.
  • 최소한의 문서
    방대한 문서 대신 동작하는 소프트웨어 전달을 목표로 한다. 문서는 있지만 전체 기능에 관한 문서만 있다.
  • 동시 개발
    하나 혹은 그 이상의 기능의 집합으로 구성된 iteration이 순차적, 혹은 동시에 진행된다.

- Scrum Framework

Scrum은 Agile 방법론에 기반을 둔 프레임워크로써, 정해진 역할과 임무, 팀으로 이루어져있다.

Scrum Framework의 주요 용어는

  • 스프린트(Sprint)
    유용하고 릴리스 가능한 결과를 생산하는 데 할당된 기간. 이전 스프린트가 끝나면 곧바로 새 스프린트가 시작된다. Agile의 iteration과 비슷한 개념이다.
  • 프로덕트 백로그(Product Backlog)
    개발할 소프트웨어에 필요한 모든 기능의 집합. 끊임없이 변동 가능하다.
  • 스프린트 백로그(Sprint Backlog)
    스프린트에서 진행하기로 결정된 기능의 집합
  • 인크리먼트(Increment)
    전체 프로덕트 백로그 중 이번 스프린트에서 완료된 기능과 이전 모든 스프린트에서 완료된 기능.
  • 개발 팀
    스프린트 마지막에 릴리스 가능한 인크리먼트를 개발하는 역할. 오직 개발 팀만이 인크리먼트를 개발한다.
  • 프로덕트 오너
    스크럼 팀과 그 외 사람들의 중재자. 스크럼 팀의 외부 담당자로서 고객사, 인프라스트럭처 팀, 관리자, 그 외 스크럼과 관계된 모든 사람과의 의사소통을 담당한다.
  • 스크럼 마스터(Scrum Master)
    사실상 리더 역할(스크럼은 리더가 없지만). 스크럼을 이해시키고 진행하는 역할.

스크럼 방법론의 절차

  • 스프린트 계획
    스크럼 팀이 이번 스프린트 주기에 포함시킬 기능을 결정하는 기회다. 스프린트 계획은 개발자들이 주도하며 계획을 세운 후 스크럼 마스터와 프로덕트 오너에게 보여준다. 스프린트 계획은 '정해진 시간 안에 이뤄지는 행위'이다.

    <스프린트 계획 시 개발 팀이 고려할 사항>
    - 기존 백로그의 기능이나 신규로 백로그에 추가된 기능 중 이번 스프린트에 작업될 기능 목록
    - 이전 스프린트 시 팀의 작업 실적
    - 개발 팀의 예상 능력

  • 스프린트 주기
    결정된 작업량에 따라 유동적으로 조절 가능하다.

  • 일간 스크럼 회의
    스크럼 회의는 '매일' 진행한다. 개발 팀이 어제 달성한 작업, 오늘 작업할 내용, 막히는 부분을 의논한다.

  • 스프린트 진척 관리
    일간 스크럼 회의에서 스프린트의 진척을 관리한다. 남은 작업량을 추적해 스프린트 목표 달성 가능성을 예측할 수 있다.

  • 스프린트 리뷰
    개발 팀이 작업을 끝낸 기능의 데모를 진행한다. 프로덕트 오너는 프로덕트 백로그를 최신으로 변경하며, 제품이 실제 사용되는 환경에서 리뷰한다.

  • 스프린트 회고
    잘된 점과 개선이 필요한 점을 논의해 다음 스프린트에서 개선할 점을 결정한다. 회고 회의는 주로 스프린트 리뷰와 스프린트 계획 사이에 한다.

🔎 정리하자면 최근 소프트웨어 개발이 급속도로 발전하면서 리소스를 충분히 지원하는 Waterfall 모델이 아닌 Agile 방식의 소프트웨어 개발 방식이 성행하고 있고, 그 중 scrum framework로 개발을 진행하면서 CI가 등장했다.

2. CI의 정의

- CI란?

CI = Continuous Integration
빠른 주기로 작업한 내용을 통합 브랜치에 통합하고 빌드하는 개발 방식

*통합(Integration): 개인이 작업한 코드를 공용 작업 환경에 올리는 것! 개인 브랜치를 중앙 브랜치에 병합(merge)하는 과정

CI가 필요한 가장 큰 이유는"통합 과정에서 발생하는 이슈를 가능한 빨리 발견하기 위함"이다.

위의 그림처럼 CI는 통합 과정에서 발생하는 이슈를 빨리 발견하게 해주고 개발자는 해당 코드를 수정해 문제를 해결한다.


- CI를 이용한 Agile

❓CI는 Agile에서 필요한 속도에 어떻게 도움을 줄까??

CI 환경이 아닐 때
코드 수정 -> 코드 반영 -> 버전 관리 시스템에서 변경 사항 가져오기 -> 소스코드 빌드 -> 단위 테스트 진행 -> 통합 -> 통합된 코드 빌드 -> 패키징 후 배포

CI 환경일 때
젠킨스 같은 도구를 이용해 모든 과정 빠르게 에러 없이 진행! 알람 추가 시 더욱 빨라짐

CI & Agile: 거의 모든 종류의 프로젝트, 거의 모든 종류의 프로그래밍 언어에서 사용 가능!!!

3. CI의 구성 요소

- 버전 관리 시스템(Version Control System)

코드의 이력을 관리하는 도구
CI를 구성하는 데 가장 기본이자 중요한 요소다.

"기본적으로 소프트웨어 빌드와 관련된 모든 것은 버전 관리가 되어야 한다" 버전 관리 도구는 태깅, 분기 등 많은 기능을 제공한다.

  • 비분산형: SVN, IBM Rational ClearCase
  • 분산형: Git, Mercurial

(버전 관리 시스템은 내용이 훨씬 더 많지만 이번 포스팅은 CI에 대한 내용이기에 더 적지는 않겠다)


- 브랜칭 전략

브랜치 최소화하는 것이 가장 좋다! 하나의 브랜치는 공동 작업 및 오래된 버전 등의 이슈가 발생할 수 있어서 대부분의 회사는 여러 브랜치를 사용한다.

위 그림은 일반적인 버전의 GitFlow를 보여주고 있다.

GitFlow: 여러 브랜치를 이용해 코드를 관리하는 방식

  • 마스터와 프로덕션 브랜치는 언제나 릴리스 가능한 깨끗한 코드만 있다.
  • 다른 개발 패치는 기능 브랜치와 기능을 통합할 통합 브랜치에 반영된다.

여기서 더 확장된다면

위와 같은 확장된 방식의 GitFlow가 만들어진다.

  • 기능 브랜치에는 모든 개발 내용이 들어간다.
  • 통합 브랜치에서 모든 코드를 통합하고 품질을 위해 테스트를 한다.
  • 통합 브랜치에서 안정적인 릴리스 버전이 생길 때 이 버전에 기반해 릴리스 브랜치를 생성한다.
  • 마스터나 프로덕션 브랜치에 핫픽스가 필요한 경우에도 각각의 브랜치를 기반으로 핫픽스 브랜치가 생성된다.

- CI 도구 = 지휘자 역할

CI 시스템의 중심에 위치해 모든 것을 연결하는 도구
파이프라인을 생성하는 방법을 제공한다.

*모든 것: 버전 관리 시스템, 빌드 도구, 바이너리 관리 도구(Binary Repository Manager tool), 테스트 및 프로덕션 환경, 소스코드 분석 도구 및 자동화 테스트 도구 등

Build Forge, Bamboo, 팀TeamCity 등의 다양한 CI 도구 중
여기서는 ➡️Jenkins⬅️를 다룰 예정이다!!

파이프라인
각 파이프라인에는 고유한 목적이 있다.

파이프라인은 기술적으로 연속된 작업의 흐름이다. 각 작업은 연속해서 수행되는 소작업의 모음이다.

CI 도구 사용의 핵심: 스크립트 언어를 이용해 다양한 소작업을 수행하는 것
*소작업: 폴더/파일 복사 등의 간단한 작업부터 파일 수정을 담당하는 서버 모니터링과 같이 복잡한 펄 스크립트까지

하지만!! "젠킨스의 플러그인"이 스크립트를 대체하고 있다.
더 이상 자바 코드를 빌드하는 스크립트를 짤 필요 없이 플러그인을 설치한 후 설정해 원하는 작업을 실행시키면 된다!!
(기술적으로, 플러그인은 자바로 쓰여진 작은 모듈이지만 플러그인 사용으로 개발자가 스크립트 짜는 부담에서 자유로워짐은 분명한 사실이다.)


- 자동으로 시작되는 빌드

코드를 컴파일하고 실행 파일을 만들어내는 여러 단계를 자동화하는 것
CI 시스템에서 가장 중요한 부분이다.

빌드 자동화 시 충족 조건은 2가지이다.

  • 빠른 속도
  • 코드나 통합 이슈를 최대한 빨리 잡아내는 것

빌드 자동화 시 장점

  • 많은 시간이 절약된다.
  • SDLC Framework에서 에러(빌드 에러, 컴파일 에러, 통합 에러)를 발견할 확률이 높아지고 발견되는 시점도 빨라진다.

- 코드 커버리지(Code Coverage)

테스트 케이스가 커버하는 코드의 양을 백분율로 나타낸 값

다음은 소나큐브의 코드 커버리지 리포트이다.

커버리지 리포트에서 보게 될 지표는 아래 표의 내용과 유사하다.

커버리지 종류설명
함수(Function)작성된 모든 함수 중 테스트가 수행된 함수의 수
명령문(Statement)전체 명령문 개수 중 실제로 수행된 명령문의 수
브랜치(Branches)수행된 브랜치의 수
조건(Condition)true와 false 값이 모두 테스트된 조건문의 수
라인(Line)전체 코드 라인 중 테스트된 라인의 수

프로그래밍 언어에 따라 다양한 코드 커버리지 생성 도구를 찾을 수 있다!!

  • Java -> Atlassian Clover, Cobertura, JaCoCo
  • c#/닷넷 -> OpenCover, dotCover
  • C++ -> OpenCppCoverage, gcov
  • Python -> Coverage.py
  • Ruby -> SimpleCov

- 코드 정적 분석

코드의 구조적인 품질을 측정하는 소프트웨어로 코드가 얼마나 견고하고 지속 가능한지를 알려준다.
실제로 프로그램을 수행하지 않고 실행되는 분석으로, 동적 테스트와 달리 white-box test라고 부르기도 한다.

코드 정적 분석은 소프트웨어의 기능적인 부분이 아닌 "소프트웨어의 내부적인 구조"를 평가한다. 사용자 정의된 메트릭을 통해 분석 결과가 생성돼 유지 보수성에 대한 코드의 품질을 알려준다.
ex) 반복적으로 사용되는 코드, 주석 처리된 라인의 수, 코드의 복잡성 등

코드 정적 분석의 장점
코드 정적분석은 개발자가 개발한 코드를 올리기 전에 수행되도록 설정될 수 있기에, 낮은 품질의 코드가 merge되는 것을 미리 예방할 수 있다!!!


- 자동화된 테스트

테스트는 SDLC에서 중요한 역할을 한다! 소프트웨어의 품질을 유지하려면 다양한 테스트 시나리오를 통해 코드를 테스트해야 한다.

테스트 자동화의 장점

  • 소프트웨어 배포에 걸리는 시간 대폭 단축 가능

테스트 자동화의 어려운 점
"테스트 자동화는 빌드, 릴리스, 배포 자동화보다 훨씬 어렵다" 프로젝트에서 사용되는 모든 케이스를 자동화하는 것은 엄청난 노력과 시간이 걸리는 작업이다.
따라서, 처음 테스트를 자동화할 때 고려할 사항이 있다.

  • 모든 테스트 절차가 동일하지만 다양한 데이터를 통해 테스트되는 케이스가 좋다.
  • 소프트웨어의 기능 중 여러 플랫폼에서 테스트되는 케이스를 자동화하는 것이 좋다.
  • 다양한 설정이 적용돼 실행되는 소프트웨어의 테스트를 자동화하는 것이 좋다.

코드가 빌드, 패키징, 배포를 거친 후 소프트웨어를 검증하려면 반드시 테스트를 거쳐야 하는데 이때 몇 가지가 필요하다.
1. 릴리스된 코드는 SIT(System Integration Test)를 거쳐 통합된 코드가 기능적으로 잘 작동하는지 검증
2. 통합 테스트를 통과한 후, 코드는 다음 단계인 UAT(User Acceptance Test)를 거침
3. 마지막으로 PT(Performance Test)를 거쳐 성능을 확인

▶ 테스트 자동화 시 가장 중요한 것은 가능한 많은 부분을 자동화하는 것이다


- 바이너리 관리 도구

바이너리 파일의 버전 관리 시스템
빌드된 바이너리 파일 관리 및 빌드에 필요한 서드파티 바이너리 파일도 함께 관리

SDLC의 일부로써 소스코드는 CI를 통해 주기적으로 빌드 -> 바이너리 파일이 생성된다. 빌드된 바이너리를 저장할 공간이 필요한데 .rar, .war, .exe, .msi 등의 파일을 관리한다.

위 그림을 보면 바이너리 관리 도구가 어떻게 작동하는지 알 수 있다.

바이너리 관리 도구 작동 흐름
1. 빌드 수행
2. 검증 진행
3. 빌드된 바이너리 파일들 바이너리 관리 도구로 복사
4-1. 자동화된 테스트가 구성되어 있다면? -> 빌드된 바이너리 파일은 자동으로 적합한 테스트 환경에 배포된다.
4-2. 자동화된 테스트가 구성되어 있지 않다면? -> 개발자나 테스터가 수동으로 필요한 바이너리 파일을 골라 배포 및 테스트를 한다.

바이너리 관리 도구의 역할

  • 필요 시 쉽게 접근 가능
    빌드된 바이너리가 생성될 때마다 저장한다. 결과물이 중앙 서버에 저장돼 필요할 때마다 쉽게 접근 가능해지는 것이다.
  • 플러그인들을 항상 최신 버전으로 유지
    빌드 시 필요한 서드파티의 바이너리 플러그인이나 모듈을 저장한다. 빌드 도구가 빌드 시 플러그인을 다운로드할 필요가 없어진다. 바이너리 관리 도구가 온라인에 연결돼 플러그인들을 항상 최신 버전으로 유지하는 역할
  • 기록
    누가, 언제, 어떤 바이너리를 만들었는지 기록한다.
  • 환경 제공 및 속도 향상에 도움
    릴리스를 더 쉽게 관리할 수 있게 스테이징 환경을 제공하고, CI 절차의 속도 향상에 도움을 준다.
  • 패키지 생성
    빌드의 주기가 빠른 CI 환경에서는 매 빌드 시 패키지가 만들어진다. 이렇게 만들어진 모든 패키지가 한 장소에 존재하기에, 개발자가 다음 단계에 적용시킬 바이너리를 쉽게 고를 수 있다.

- 패키징 자동화

패키징이란?
빌드 후 여러 종류의 결과물을 가지게 되는 경우가 있는데 이 모든 결과물을 하나로 묶는 작업을 "패키징"이라고 부른다.

CI 도구를 이용해 패키징 자동화 시, 많은 시간 단축이 가능하다!


4. CI 사용의 장점(결론)

  • 복잡하고 어려운 통합으로부터 해방
    merge 지옥을 겪지 않아도 된다. waterfall 모델과 달리 기능 브랜치에 올려진 모든 커밋을 통합 브랜치에 통합하고 테스트하면, CI 도구가 통합 이슈를 즉시 알려준다!

  • 메트릭
    작업 기간 동안의 추세를 기록하고 보여준다. 젠킨스, 깃허브, 소나큐브, 아티팩토리 같은 도구를 통해 프로젝트의 진행 방향 및 속도를 확인할 수 있다.

  • 이슈의 조기 발견(가장 큰 이득😯)
    모든 merge 이슈나 통합 이슈가 바로 발견되고, CI 시스템이 빌드 실패 즉시 알람을 통해 이를 알려준다.

  • 빠른 개발
    기술적 관점에서 CI는 팀원들이 좀 더 효율적으로 일할 수 있게 도와준다. 빌드, 테스트, 소스코드 통합을 자동으로 하는 환경이 구축되면 이는 빠른 개발로 이어진다. 이 특징은 지리적으로 떨어져서 일하는 조직에도 적합하다!

0개의 댓글