
"Good Bite" 라는 이름의 팀 프로젝트로, 식당과 손님 간의 테이블링 예약(웨이팅) 웹 애플리케이션을 만들고 있습니다.
우리 팀은 깃허브로 코드 형상관리를 하고 공유하고 있기 때문에, 연동과 접근성이 좋은 GitHub Actions을 사용하여 편리하게 웹 서버에 CI/CD를 구현하기로 결정!

백엔드 애플리케이션은 Spring Boot로, 위 그림을 보면 현재 백엔드 서버만 배포한 상태이고 프론트엔드는 React로 개발하였고 로컬 머신에서 테스트 단계 중입니다. 추후에 프론트엔드 서버를 추가 배포한 형태의 아키텍처를 들고 오겠습니다.
[프론트엔드 추가 배포 과정 페이지]
목표는 CSR (클라이언트 사이드 렌더링) 방식을 사용하여 사용자에게 뷰를 제공하고, 백엔드에서 서비스 API 처리를 하는 구조입니다. 😁
오류 상황과 스케일 아웃에 유연하게 대처할 수 있도록 프론트와 백엔드 서버를 독립적으로 배포하기로 하였고, 각 서버에서 Dockerfile을 기반으로 애플리케이션 이미지를 빌드하고, 빌드된 이미지를 컨테이너로 실행하여 서버를 운영하도록 하였습니다.
소규모 프로젝트로서 EC2 인스턴스는 현재 하나이지만 최종 아키텍처에서는 로드밸런싱을 추가한 오토 스케일링 전략을 수행하려고 합니다.
CSR은 동적 렌더링 방식으로, 사이트에 처음 접속할 때 로딩 소요시간이 정적 렌더링 방식보다는 조금 더 걸리지만 그 이후 페이지를 전환할 때는 필요한 데이터만 받아오기 때문에 클라이언트의 초기 로딩 속도를 줄이고 빠른 사용자 경험을 제공할 수 있습니다.
프로젝트의 특성을 고려했을 때 사용자 간의 웨이팅 서비스가 실시간으로 이루어져야 하는 것이 핵심이어서 페이지를 동적으로 생성했을 때 사용자 경험에 영향이 클 것으로 판단되어 클라이언트 사이드 렌더링을 채택하였습니다.
초기 로딩 속도가 지연되는 단점은 사용자에게 로딩바 화면을 제공하여 보완할 수 있다고 판단하였습니다.
이것은 헤드리스 아키텍처로, 백엔드와 프론트엔드가 명확히 분리된 구조를 가집니다. 각 사이드가 독립적으로 설계되면 역할이 분산되어 서버 부하를 낮출 수 있으며 확장성과 재사용성을 높일 수 있습니다.
백엔드 측면에서 API 서버로서의 역할에만 집중할 수 있어 개발 생산성이 향상되는 점과 다양한 클라이언트에 대응할 수 있기 때문에 헤드리스 아키텍처로 구성해보았습니다.
각 서버 간 통신은 REST API로 동작합니다. API에는 여러 종류가 있지만, REST API를 선택한 이유는 웹 브라우저 뿐만 아니라 모바일 앱 버전 확장을 고려했을 때 무리가 없을 것이라 판단했기 때문입니다.
Owner와 Customer 두 가지 유형의 클라이언트가 사용되며, 웹 또는 모바일 환경에서 다양한 장치를 통해 접근할 수 있는 서비스가 자연스럽다고 생각했습니다. REST API는 언어 및 플랫폼에 종속되지 않기 때문에 웹 브라우저뿐만 아니라 모바일 앱, IoT 기기 등 다양한 환경에서 API를 호출할 수 있습니다.
Docker를 사용함으로써 환경 일관성을 유지하고 배포를 간소화하여 개발 측면에서 편리함을 제공해주기 때문입니다. 더불어 확장성과 이식성도 높일 수 있습니다.
환경 일관성 유지: Docker를 사용하면 개발 환경, 테스트 환경, 배포 환경 모두에서 동일한 애플리케이션 구성을 사용할 수 있습니다. 이를 통해 로컬 환경과 서버 환경 간의 불일치를 줄일 수 있으며, 개발자가 사용하는 환경과 실제 운영 환경의 차이를 최소화할 수 있습니다.
배포 간편화: Docker 이미지를 사용하여 백엔드 애플리케이션을 일관된 방법으로 EC2 서버에 쉽게 배포할 수 있습니다. Docker는 해당 애플리케이션의 모든 종속성, 라이브러리 등을 포함하므로 서버 환경에 상관없이 애플리케이션을 실행할 수 있게 합니다.
CI/CD 파이프라인 통합: CI/CD 도구(GitHub Actions)와의 연계가 용이합니다. Docker 이미지를 자동으로 빌드하고 테스트하며, 새로운 버전을 EC2에 쉽게 배포할 수 있어 배포 프로세스가 자동화됩니다.
확장성: Docker는 컨테이너 기반이므로 애플리케이션을 빠르게 확장하거나 축소할 수 있습니다. 특히 EC2와 같은 클라우드 환경에서 Docker를 사용하면 여러 컨테이너를 쉽게 스케일링하여 유동적인 트래픽을 처리할 수 있습니다.
이식성: Docker를 사용하면 애플리케이션을 컨테이너화하여 어디서든지 실행할 수 있습니다. 로컬 개발 환경, 스테이징 서버, 프로덕션 서버 등 다양한 환경에서 동일하게 동작할 수 있는 것이 큰 장점입니다.
GitHub Actions 를 사용하기 전에는 수동으로 jar 파일로 빌드하고 EC2 배포 서버에 SSH 통신으로 직접 파일을 전달하고, 필요한 패키지를 설치했었습니다.
여러 배포 방법을 찾아보다가 CI/CD 를 적용하는 것이 매우 편하고 지속적으로 배포할 때 유리하다는 것을 깨닫고 별도의 계정 가입과 설치 과정이 필요 없는 GitHub Actions 를 채택하게 되었고,
workflows 파일 작성법을 공부한 뒤 코드만 작성해주니
이전의 불편한 과정들을 GitHub의 머신이 해결해주어 제가 EC2에 접근하지 않아도 배포가 되어버리는 매직이 발생했습니다.
내가 수동의 방법을 택하는 경우는 최대 성능을 위해 내가 상세한 설정을 컨트롤할 수 있을 경우에 많이 선택했었는데, CI/CD 또한 자동 배포가 되어 편할 뿐만 아니라 원하는 만큼의 과정을 직접 설정하는 것에 있어서 큰 차이를 느끼지 못했습니다.
자동 배포는 한 번 설정하고 난 뒤로 재배포부터는 간단한 경우 코드 몇 줄만 바꿔도 가능하기에 굉장한 편리함을 느꼈고 앞으로도 이 방법을 애용할 것 같습니다.
글의 내용이 길어 여러 포스트에 나누어 작성하도록 수정하였습니다. (2025-01-14)
잘 읽었습니다! 정리 정말 잘해두셨네요. 한수 배워갑니다!!