Docker, Nginx의 CI (지속적 통합)
Docker와 Nginx는 왜 CI에서 사용할까?
💁🏻♂️ 간략한 프로젝트 소개
Hot-Dealicious라는 이름으로 작은 프로젝트를 시작했다. 배, 쿠이츠, 모빌리티 서비스 등 위치 추적 기술 너무 신기했다. 주식이나 코인의 시세가 시도때도 없이 변동하는 기술도 너무 신기했는데 위치 기반 서비스를 구현해보면 WebSocket같은 네트워크 기술로 서버에서 계속 데이터를 push할 수 있을 거라 생각했다. 처음 백엔드 프로젝트를 시작하는만큼 아주 베이직한 이커머스적인 특징을 가지고 있는 배달 서비스를 첫 프로젝트로 삼았다.
🌱 프로젝트 초기 단계
프로젝트를 시작하면서 들었던 생각은 항상 팀 단위의 협업을 염두해두고 이 프로세스에 익숙해져야한다고 생각했다. 개인 프로젝트이지만 협업을 위한 스킬을 어떻게 기술로 녹일 수 있을까 고민해봤는데 과거 안드로이드 신입시절 신기하게 생각했던 CI/CD가 떠올랐다. 처음 구축할 때는 머리아팠지만… 그런데 구축한 이후의 편의성..도 사실 개인 프로젝트라 큰 변화는 없겠지만😂 그저 왜 이런 기술들을 현업에서 사용하는지 알고 싶었다.(관심도 매우 많이 갔다!!)
대략적인 프로세스는 이렇게 설계하였다. IDE에서 Github으로 코드를 push하면 Github가 Jenkins에 전달하여 빌드와 테스트를 담당한다. Jenkins에서 해당 프로세스를 완료하면 Docker Hub에 업데이트되고 이후 AWS같은 클라우드 서버에 반영되게 하는 것이 목표이다. 즉, IDE -> Github -> Jenkins -> Docker Hub -> Cloud Server 순으로 파이프라인을 구축할 예정이다.
🌱 그런데 왜 Docker, Jenkins일까?
Git은 당연히 개발자라면 주니어부터 중요하게 생각하는 형상관리 시스템이다. ‘1일 1커밋’, ‘잔디 심기’ 등 주니어가 성실성을 보여줄 수 있는 수단으로도 활용되지만, 현업에서는 기능에 따라 분업화하여 효율적인 업무가 가능하도록 하고 효율적인 코드 병합, 버전 관리 등을 가능하게 하는 중요한 기술이다. 그래서 주니어 때는 Git을 거의 필수적으로 사용했다고 해도 무방하다. 하지만 Docker, Jenkins 등은 이미 구축되어 있는 곳이 많아 쉽게 접할 수는 없는 것 같다. (물론 일당백해야하는 스타트업이라면 다 해보신 분들도 계시겠지만..ㅎ)
먼저 Docker는 사실 프론트 개발할 때는 중요성을 잘 인지하지 못했다. 그런데 백엔드를 공부하다보니 컨테이너 기반 기술은 꼭 익혀야하는 기술이라고 생각되었다. 프론트는 기본적으로 html, css, js같은 정적 파일을 클라이언트에게 응답하면 그것으로 마무리된다. 이후는 브라우저가 처리할 문제이다. 그런데 백엔드는 아니다. 다수의 클라이언트로부터 서버에 요청이 들어오면 서버는 그 많은 요청들을 처리해야한다. 여기서 포인트는 요청이 기하급수적으로 늘어나게 되면 하나의 서버로는 모든 요청을 감당 하기가 어렵다.🥲
Docker같은 컨테이너 기술은 이 때 빛을 발한다. 컨테이너 기술의 장점은 독립적인 개발환경을 빠르게 구축할 수 있다. 하나의 서버에서 독립적인 환경을 구축할 수 있기에 컴퓨팅 리소스를 최대한 끌어낼 수 있고, 같은 서버 어플리케이션을 Scale out 할 수도 있고, MSA(MicroService Architecture)같이 각 기능별로 서버를 나누어 개별적인 환경 관리가 가능하도록 한다.
Jenkins는 테스트와 빌드를 자동화하고 빌드된 코드를 배포 코드에 반영하기까지의 역할을 담당한다. 개발자가 일일히 테스트 코드를 돌리고 빌드하여 배포 코드에 업데이트하는 수고를 덜어주는 것이다. 여러가지 테스트, 빌드 자동화 툴이 있지만 그 중 Jenkins는 오픈소스이기 때문에 나같은 취준생이 사용하기 좋다. 물론 지원하는 플러그인도 많다고 한다!! ㅎㅎ
🌱 Nginx는 왜 사용할까?
Nginx는 보통 Reverse Proxy를 사용하여 클라이언트에서 서버로 들어오는 Request를 한번 필터링(?)하는 과정을 거치게 한다. Nginx를 사용할 때 당연히 자세한 분석과 프로젝트에 적합한지의 판단을 해야겠지만, 여기서는 Https 프로토콜을 사용하기 위해서라고 하고 싶다. Nginx를 사용하여 로드벨런싱을 하는 경우도 있지만, 현업에서는 Nginx를 사용하여 로드밸런싱을 하기보다 다른 상품들을 사용한다고 한다. (그래서 나는 HA Proxy를 사용해보려고 한다.) 그 이유는 Nginx는 Health Check 기능이 없기 때문!! Health Check란 로드밸런싱하는 서버에서 분선처리를 진행할 때 분산되는 컴퓨터의 부하를 모니터링하는 것을 의미한다. 이런 모니터링 기능이 있어야 우리 같은 개발자들이 어디에서 병목이 일어나고, 서버가 불안정하다는 등의 판단을 할 수 있는 근거를 가지게 되는 셈이다📝
그렇기 때문에 이 프로젝트에서 Nginx는 로드벨런싱보다 Https 프로토콜을 사용하도록 하는 관문의 역할을 맡기려한다.
🌱 Docker Hub에서 AWS까지의 여정
처음에 jar나 war같은 어플리케이션 파일을 Jenkins에서 빌드하여 자동으로 Docker Hub에 업로드하고 이어 AWS까지 자동화해야한다고 생각했다. 그게 “자.동.화”라고 생각했다. 모든 것을 자동화시켜 편리함의 끝을 봐야지라고 생각했다. 그런데 보통 빌드된 파일을 Docker Hub에 업로드하는 것까지는 괜찮은데 Docker Hub에서 AWS같은 운영 서버에 반영하는 것은 위험하다고 판단하게 되었다.
자동화되는 것은 어디까지나 우리가 안전하다고 생각하는 범위 내에서 하고 테스트와 테스트를 거쳐 운영서버에 배포되어야 한다고 생각되었다. 그래서 운영 서버에 반영할 때는 수동으로 Docker Hub에 업로드 된 최신 이미지를 업데이트하도록 해야할 것 같다. :)
🌱 이제 프로젝트 시작!
전체적인 서버 아키텍쳐를 설계해보았다. 하나부터 열까지 다 구현하기에는 “내가 왜 이 기술을 사용하지?”, “이 기술말고 다른 기술은 없을까?” 등 같이 기술에 대한 분석과 프로젝트에 필요한 것들을 적용할 수 있는 판단력을 길러야겠다고 판단했다. 먼저 어플리케이션 코드를 완성해보고 이후에 처음에 설계했던 서버 아키텍쳐를 반영하여 배포까지 해보는 것을 목표로 해보자!!!