Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save stophobia/66ce0afc29f3a9701cce31eb99b9a857 to your computer and use it in GitHub Desktop.
Save stophobia/66ce0afc29f3a9701cce31eb99b9a857 to your computer and use it in GitHub Desktop.

[DevOps] ZEXT - Infrastructure & CI/CD

이번 글에서는 초기 스타트업에서 서버 인프라 설계 및 배포 자동화 했던 경험을 정리하고, 개선 방향을 다룰 예정이다.

image [ 그림 1]

우선 간단히 프로젝트 환경에 대해서 소개하자면, 프로젝트 초기에 도커 (+ 도커 컴포즈)를 활용하여 모든 컴포넌트 (Nginx, FE, BE, DB) 가 하나의 인스턴스에서 구동되도록 했다. 비용적으로는 여러 스타트업 지원 사업으로 여러 인스턴스를 확보할 수 있었지만(NCP, AWS 등), 가장 간단한 구조 에서 의도한 기능이 동작하는 지 확인하기 위해 우선 위와 같은 환경을 구성하게 됐다.

image [ 그림 2 ]

인스턴스는 크게 3 가지 그룹으로 구분해서 CI Server (Jenkins, Docker Registry), 테스트 서버, 그리고 배포 서버로 구성 했다. Dev , Prod 인스턴스는 완전히 동일한 환경으로 구성 해서 초기에 Dev 인스턴스에서 테스트를 진행 한 뒤 Prod 에서 배포를 진행하는 식으로 활용했다.

위 과정에서 핵심으로 생각 했던 부분은, 가장 간단한 구조와 개발 환경의 유사성이었다. 서버 인프라 구축과 배포 자동화 등 경험이 거의 전무 했던 입장에서 Fail Point 를 최대한 줄이는 것이 가장 주요 하다고 판단 했었고 지금 생각해도 다른 팀에서 공개한 서비스 인프라 따라하려고 처음부터 무리 했으면 오히려 시작도 못했을 것이라고 생각한다.


Jenkins Pipeline + Docker + TestContainer

로컬 개발 환경에서 Dev 인스턴스 서버로 배포되는 과정을 확인해보자. 아래 과정은 Jenkins Server 를 통해 자동화되어 있다.

image [ 그림 3 ]

(백엔드 기준) 로컬 개발 환경에서 기능 구현이 끝난 뒤 새로 구현한 기능과 이전 개발 내역을 모두 테스트를 한 뒤 모든 테스트가 통과되면 (혹은 일정 기준 이상 충족) dev 브랜치로 PR 을 생성한 뒤 머지가 되면 webhook 을 통해 Jenkins Server 내 pipeline 이 시작시킨다.

pipeline 내 작업을 순차적으로 수행하는데, 가장 먼저 업데이트된 소스 코드 내역을 불러온 뒤 빌드 테스트, 테스트를 순차적으로 진행하고 모든 태스크가 완료 되면 도커 컴포즈 빌드를 진행한다. 도커 컴포즈 빌드를 통해 생성된 이미지들은 private docker registrypush 한다.

그 이후 빌드 스크립트를 실제 서비스를 배포할 서버에 ssh 를 통해 전송한 뒤 해당 파일을 실행시킨다. 그리고 마지막으로 빌드 스크립트에서 docker registry 로 부터 도커 이미지를 pull 받은 뒤 docker-compose up -d 를 통해서 서비스를 구동한다.

image [ 그림 4 ]

Testcontainers is a Java 8 library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

[ 그림 4 ] 에서 ② 과정에서 BE TestTestContainer 를 통해 수행하도록 했는데, 실제 배포 환경이 MySQL 컨테이너를 띄워서 서비스하는 형식이다 보니 배포 환경의 복제 형태인 개발서버에 배포 하는 과정에서도 동일한 환경을 구성하기 위해 로컬 DB, In-Memory DB 등을 사용하지 않고 도커 컨테이너 기반의 DB 방식을 사용했다.

image [ 그림 1 ]

반면, 로컬 개발 환경에서는 애플리케이션 내 테스트 항목이 많아 짐에 따라 In-Memory DB 인 H2를 사용해서 효율성을 높였다. 로컬 테스트 이후, CI 과정에서 수행하는 테스트까지 통과한 뒤에 개발서버에 반영되는 구조라서 로컬 환경에서 위와 같은 선택을 하게 됐다.

TestContainer 의 특징과 DB 초기화 및 시드 데이터 운영 등 활용 시 필요한 설정에 대해서는 별도의 토픽으로 다룰 예정이다.


개선 방향 및 희망 사항

image [ 그림 5 ]

개선 방향을 잡기 위해서는 객관적인 근거가 필요하다고 생각하는데, MVP 베타 런칭 후 10일 간 접속량을 봤을 때 당장 우선적으로 Nginx 로드 밸런싱 + WAS 스케일 업 또는 DB 고가용성 등의 성능을 끌어올리는 것 보다는 앞으로 많은 유입을 대비해 수평적 규모 확장에 용이한 구조로 변경하는 것이 필요하다고 생각했다.

[ 그림 1 ] 에서 Nginx 서버 (프록시 서버)와 FE, BE + DB 이렇게 세 개로 우선 분리한 뒤 그 이후에 성능을 끌어 올리기 위해 Nginx 로드 밸런싱 + Spring WAS 스케일 업 그리고 DB Replication 등을 고려하고 있다.

백엔드 자체적으로는 정적 분석 툴을 활용하여 코드 커버리지 등 객관적인 지표 값을 근거를 활용한 코드 관리 및 배포 과정에서 정적 분석 결과 기준에 부합하지 않은 경우 PR 머지가 안 되도록 함으로써 보다 안정적인 배포 자동화 과정을 구축 할 예정이다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment