Recording/멋쟁이사자처럼 BE 13기

[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_77일차_"빌드 자동화"

LEFT 2025. 4. 1. 18:00

🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - [77]일차

🚀77차에는 빌드 자동화를 다루는 Jenkins와 Github Actions 등에 대한 개념을 학습할 수 있었다.

학습 목표 : 빌드 자동화 도구 중 Jenkins에 프로젝트를 연결하여 설정을 구성해볼 수 있다.

학습 과정 : 회고를 통해 작성


쿠버네티스 애플리케이션 배포

  • 단순히 컨테이너를 생성하는 것보다 배포 전략을 잘 알아야함

 

배포 전략

  • 확장성 : 트래픽 증가에 따라 Pod 개수 늘리기
  • 고가용성 :
    하나의 Pod이 죽어도 서비스 중단을 최소화하기 위해 Deployment와 Service를 통한 로드밸런싱
    다수의 Pod을 여러 노드에 분산시켜 장애에 대한 내성 확보

  • 무중단 업데이트 (Rolling Update) :
    신규버전 배포 시 서비스를 완전히 끄지 않고 점진적 업데이트 이전버전 Pod, 새 버전 Pod을 교대로 교체하여 요청 장애시간을 최소화

  • 자동화 (CI/CD):
    이미지 빌드부터 쿠버네티스 배포까지 파이프라인을 구축하여 지속적 배포 실현

    CI (Continuous Integration, 지속적 통합)
    애플리케이션의 새로운 코드 변경 사항이 정기적으로 빌드 및 테스트되어 공유레포지토리에 통합되는 것
    (가능하다면 하루에 여러번도 가능)

    CD (Continuous Delivery or Continuous Deployment, 지속적인 서비스 제공 or, 지속적인 배포)
    - 공유레포지토리로 자동으로 Release 하는 Continuous Delivery
    - Production 레벨까지 자동으로 Deploy하는 Continuous Deployment

  • 개발자의 변경사항이 레포지토리를 넘어 고객의 프로덕션 환경까지 릴리즈 되는 전반적인 과정을 의미
  • AWS의 EC2를 이용할 것
  • EC2 인스턴스를 활용하여 필요에 따라 서버 스펙을 조정하여 확장성이 높게 운영 가능
  • 보안 그룹 → 인바운드 아웃바운드 트래픽을 간편하게 관리 가능

 

배포 과정

  • 이미지 빌드
    1) React 애플리케이션 → nginx로 서빙되는 정적 파일 이미지 빌드
    2) Spring Boot 애플리케이션 → JAR를 포함한 Docker이미지 빌드
    3) 테스트 완료 후 Docker Registry(ex. Docker hub)에 푸시

  • 쿠버네티스 매니페스트 작성
    - Deployment, Service, ConfigMap, Secret 등 YAML파일로 정의

  • 배포 (kubectl apply)

  • 스케일 업 / 다운 :
    트래픽 증가 시에는 kubectl scale deployment react-deployment --replicas=3
    동일한 이미지를 사용하는 Pod3개가 동시에 로드밸런싱 처리

  • 롤링 업데이트 새 버전 이미지를 Deployment에 적용하면 무중단 업데이트로 이전 버전의 Pod을 점진적으로 교체

  • 스케일 업 ➡️더 많은 트래픽이나 작업량을 처리하기 위해 Pod(컨테이너)개수를 늘리는 것
  • 스케일 다운 ➡️트래픽이 감소하거나 리소스를 절약하기 위해 Pod개수를 줄이는 것

  • 쿠버네티스에서는 Deployment리소스의 replicas 값을 변경함으로써 손쉽게 Pod개수를 늘리거나 줄일 수 있음

 

배포 자동화 도구

  • 대표적으로 Jenkins, Github Actions
  • 통합한거 깃에 올린거를 알아서 받아와서 AWS에 배포하는 작업까지 자동으로 일어나도록 하는 것
  • (=변경할 사항이 있으면 자동으로 체크해서 가져와서 빌드 후 AWS에 복사하고 새롭게 배포)
  • 개발자는 깃에 수정한 것을 업데이트해서 올리기만해도 자동 빌드 후 배포가 되는 것
  • Github Actions에서도 적절한 설정을 해주면
    "개발자가 특정 브랜치에 Commit하게되면" Trigger로 작동하여 자동으로 배포하는 것도 가능

EC2 인스턴스

  • 키 페어 생성

  • openSSH를 사용하도록 .pem방식으로 생성

보안그룹 설정

  • 인스턴스의 세부정보를봤을때 퍼블릭 IPv4주소를 확인해보면 이 주소를 통해서 내 애플리케이션에는
    누구나 접근할 수 있게될 것이다. ➡️이 주소가 배포 주소

인바운드 규칙 추가

  • 만든 인스턴스의 보안 탭클릭 → 인바운드 하이퍼링크 클릭 후
  • 인바운드 규칙 편집 → 규칙 추가
  • SSH 로는 사용자 지정의 IP/32 형식
  • HTTP 로 Anyone IPv4 설정
  • 사용자 지정으로 8080과 Anyone IPv4 설정

SSH 접근

ssh -i juunb-keypair-likelion.pem ec2-user@퍼블릭IP주소

  • ⚠️명령어 오류발생
    ➡️윈도우에서 pem 권한 변경 시 이러한 오류가 발생할 수 있음
  • ✅icacls 명령어를 활용하여 권한을 변경해준다.

  • ssh -i juunb-keypair-likelion.pem ec2-user@[퍼블릭IPv4주소]
    ➡️다시 ssh로 접속 확인 

  • 서버에 git 설치 후 config로 유저이름과 유저이메일 설정 ➡️ec2의 서버에 적용완료

프로젝트 DB 설정 변경

  • todoApp의 build.gradle
    compileOnly 'org.projectlombok:lombok'
//    runtimeOnly 'com.mysql:mysql-connector-j'
    runtimeOnly 'com.h2database:h2'
  • mysql을 주석처리 후 h2 DB를 사용하고자 추가 (Gradle 적용)

 

application.yml 수정

spring:
  datasource:
#    url: jdbc:mysql://localhost:3308/testdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
#    username: testuser
#    password: testpass
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    hikari:
#      maximum-pool-size: 10
#      minimum-idle: 10
    url: jdbc:h2:file:./data/testdb;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
    driver-class-name: org.h2.Driver
    username: sa
    password:
  h2:
    console:
      enabled: true
      path: /h2-console
  • 기존의 DB 관련 설정은 주석 처리 후 h2 DB관련 설정을 추가
  • H2 DB 사용으로 내부적으로 H2 DB가 프로젝트 내에 생기게되는 것

 

gitignore로 H2 디렉토리 제외

data

HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
  • data 라는 디렉토리에는 H2 DB에서 저장되는 데이터들이 들어간다.
  • data들은 빌드 업로드 시 git에 포함되는 것을 원치 않으므로
    gitignore 설정으로 data디렉토리를 포함하지 않도록 설정하는 것

  • localhost:8080 에 접속하여 접속이 잘되는지 테스트 후 새 할일도 추가해볼 수 있다.

H2 DB 테이블 확인

  •  application.yml 설정의 /h2-console을 localhost:8080에 붙여넣으면

  • application.yml 에 H2 관련 설정을 추가해주었던 URL부분을 활용하여
    Test Connection과 Connect를 수행해볼 수 있음

  • Connect로 들어와서 생성되어있는 TODOS 테이블을 RUN을 클릭하여 확인해보면
    아까 넣어놨던 “jenkins를 이용하여 CI/CD 배우기” 를 확인 가능

프로젝트 EC2 서버에 업로드

  • 프로젝트 빌드 진행
  • 빌드를 완료 시 빌드된 파일을 ec2서버에 업로드 가능
scp -i /c/workspace/AWS/juunb-keypair-likelion.pem /c/workspace/docker/docker-mysql/todoApp/build/libs/todoApp-0.0.1-SNAPSHOT.jar ec2-user@퍼블릭IPv4주소:/home/ec2-user/
  • scp : cp (복사) 원격에 있는 것에 복사하겠다는 것
  • pem 파일의 위치 명시 ➡️ ec2 접속 시 pem파일이 필요
  • 이 후 cmd에서 java -jar로 빌드한 파일을 실행해서 서버를 열어주면

  • 이처럼 IPv4 퍼블릭주소:8080 형태로 접속하여 데이터를 넣어볼 수도 있다.

재빌드

  • 수정한 내용이 있을 경우 재빌드할때는 cmd로 ssh접속한 것을 끊어준 후
  • ./gradlew clean build -xtest 빌드를 진행하고
  • scp -i /c/workspace/AWS/juunb-keypair-likelion.pem /c/workspace/docker/docker-mysql/todoApp/build/libs/todoApp-0.0.1-SNAPSHOT.jar ec2-user@[퍼블릭IPv4주소]:/home/ec2-user/
    ➡️
    재빌드된 것을 업로드하고
  • cmd에서 java -jar로 빌드된 파일을 다시 실행하면 재빌드 성공

H2 DB의 데이터 유지

  • testdb.mv.db 파일을 삭제하지 않는 이상 지금까지 계속 쌓아놓는 할일들은 그대로 유지
  • 이는 서버가 내려간 경우에도 파일이 유지되고 있다는 것

빌드 자동화

  • 자동화 이전에는 ./gradlew 빌드 후 scp로 복사하여 업로드 후 다시 서버 수동으로 올렸다면
  • jenkins나 git action 과 같은 빌드 자동화 도구로 이러한 모든 과정을 자동화할 수 있다.

docker-compose.yml

services:
  jenkins:
    image: jenkins/jenkins:latest-jdk21
    container_name: jenkins-server
    ports:
      - "9231:8080" # Jenkins 웹 UI 접근 포트
      - "50000:50000" # Jenkins 에이전트 포트(필요 시 사용)
    environment:
      - TZ=Asia/Seoul
    volumes:
      - ./jenkins_home:/var/jenkins_home
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped

  • 설정파일 적용
  • restart: unless-stopped 옵션➡️ 오류발생 시 자동으로 restart해주는 옵션
  • 설정파일을 docker-compose up -d로 백그라운드로 올리고 localhost:9231 에 접속해보면

 

  • 명령어를 통해 암호화된 비밀번호를 받고 이 비밀번호를 Administrator password에 넣기

 

  • 이처럼 new Item 을 추가해주고 Jenkins관리에서 New Credentials로 추가

 

  • Password부분에 Lion_git용 토큰 발급받았던 것을 넣어준다.
  • username부분은 github의 username을 넣어주어야한다.
  • ID로는 이 credentials이 어떤것을 의미하는지 간단한 요약설명

  • Configuration 설정으로 소스코드관리를 들어가서 Git으로 설정 후 만들어놓은 Credentials과 저장소 주소를 넣는다.
  • branch로는 */main 처럼 넣는다.
  • 어떤 브랜치에 변경점이 있을때 이 Jenkins를 수행할 것인지를 넣어줄 수 있음
    (main 브랜치 변경 시 수행할 것임을 설정하는것)
  • 그 후 save를 눌러 변경사항을 저장해준다.

 

  • 대시보드에서 “지금 빌드”를 클릭하여 빌드를 수행하고 빌드의 넘버를 클릭하면
    이처럼 빌드에 대한 정보를 확인할 수 있고 Console Output을 눌러서 확인해보면
    이처럼 콘솔출력으로 Finished:SUCCESS 잘 된 것을 확인할 수 있다.

CI/CD 도구

  • Jenkins :
    ➡️로컬/별도 호스팅 환경에 직접 설치
    ➡️플러그인이 풍부하고 커스터마이징이 자유롭다는 특징

    1) Jenkins가 소스 레포지토리를 모니터링 → 코드 변경(Push or PR)이 감지되면 자동 빌드 및 테스트
    2) EC2로 결과물 전송 → 배포 스크립트 실행

  • Github Actions :
    ➡️Github에 통합되어있으므로 별도 서버 구축이 불필요함

    1) Github 레포지토리에 코드가 푸시되면 워크플로우 자동실행
    2) Gradle 빌드, Docker 이미지 빌드 등 다양한 작업단계를 설정할 수 있음
    3) SSH, 기타 방법으로 EC2에 접근 및 애플리케이션 배포 가능

🚀회고 결과 :

빌드 자동화 도구인 Jenkins에 대해서 개념을 정리한 후 기존에 만들어놨던 프로젝트를 연동하여 자동빌드를 구축하는 

과정이 신기하면서 설정이 다소 많이 필요하다는 것을 느꼈다.

보안 설정관련하여 Github Token과 pem파일 관리의 중요성에 대해서도 느낄 수 있었다.

향후 계획 : 

- Todo프로젝트를 조금씩 수정해본 후 재빌드로 적용이 바로되는지 실습