Architecture 정리편 - Duaily/backend GitHub Wiki
시스템 아키텍처는 듀얼리
웹 시스템에 대한 아키텍처입니다. 해당 아키텍처는 사용자가 시스템을 이용하는 데 사용 되는 핵심 컴포넌트만을 담았습니다.
사용자는 HTTPS 프로토콜을 통해 요청과 응답을 주고 받으며, 프론트엔드는 버셀을 통해 배포하였습니다. 버셀은 REST API 서버인 Spring APP과 통신을 합니다.
API 서버를 비롯한 캐싱용 서버인 Redis, 데이터 로그 수집을 위한 Prometheus, 데이터 시각화를 위한 Grafana 가 Docker 컨테이너로 EC2 에서 구동 중입니다.
DB 서버는 AWS의 RDS를 통해 구축하였고, 외장 스토리지로 S3 버킷을 사용하였습니다.
현재 듀얼리 시스템의 인프라 아키텍처입니다. 해당 아키텍처는 프리티어 계정으로 제한된 리소스만을 가지고 구축했다는 점을 미리 양해바랍니다.
사용자는 Route 53 ( DNS )를 통해 "duaily.net"으로 접속합니다. 해당 도메인으로 들어오는 요청에 대해 ALB ( Application Load Balancing )이 HTTPS로 forwarding 합니다.
Public 서브넷에 존재하는 WAS 서버로 요청이 들어가면, 서버 내의 Spring boot ( 8080 ) 컨테이너가 요청을 받아 수행합니다. 해당 서버는 EC2 내부에서 도커 컨테이너 간의 네트워크로 Redis와 통신하며, RDS와는 별도의 보안 그룹을 형성하여 통신하도록 하였습니다.
S3 의 경우, 이미지 객체를 보관하는 용도로 구축하였습니다. 여기에 로깅 데이터를 추가로 담을 예정입니다.
해당 아키텍처는 앞으로 확장시켜 나갈 서비스를 위한 인프라 아키텍처입니다.
WEB/WAS/DB 3 Tier 형태로 구축하여 각 계층의 독립성을 보장하고, 보안성을 고려해 WAS, DB는 private 서브넷으로 구성할 예정입니다. 또한, 프리티어 계정인 점을 감안하여 Auto-scaling 옵션 대신 EC2 인스턴스를 1대 더 두어 WAS에 대해서 이중화를 할 예정입니다. RDS는 그대로 MySQL 인스턴스를 2대의 WAS가 같이 마주보는 식으로 구성할 예정입니다.
AS-IS에서 도커 컨테이너로 구축했던 Redis를 별도의 Elastic Cache for Redis 서비스를 이용할 예정입니다. ( 해당 서비스는 프리티어 기준 제한된 리소스를 제공한다는 점에서 처음부터 도입할 것인지에 대해 고민하였습니다. )
정리하면, EC2 인스턴스는 총 3개가 필요하며, RDS는 기존 그대로 유지하되 Redis만 별도의 서비스를 이용할 것입니다.
WEB 서버에 올라가는 엔진으로는 Ngnix를 선택할 예정이며 로드밸런싱, 리버스 프록시, 경량화 등의 이유로 선정하였습니다.
백엔드 기준 CI/CD 워크플로우를 설명드리겠습니다.
로컬 환경에서 개발을 한 뒤, 깃헙 feature 브랜치에 Push 합니다. ( feature 브랜치의 브랜치명은 Dual-# )으로 통일화하였습니다.
이후 origin의 develop으로 PR을 날립니다. 팀원 간의 코드리뷰를 거친 뒤 머지가 되면, main 브랜치로 PR을 날립니다.
이때, CI/CD가 이벤트를 발생시킵니다.
A. Java 11 버전 설치
B. Gradle 캐싱
C. Gradle 권한 부여
D. DB, Redis, aws 등 정보를 담은 application-secret.yml 파일 값 세팅
E. jar 파일 생성
F. Dockerfile 빌드 및 Docker hub 로 push
G. AWS EC2에 deploy
위와 같은 흐름으로 build 과정을 거칩니다.
백엔드 레포지토리 기준 패키지 뷰입니다.
크게 Security config, Controller, Service, Repository, Domain으로 구성하였습니다.
별도의 외부 라이브러리 혹은 같은 목적을 갖는 기능을 util 클래스로 분리하였습니다.
프론트와 주고 받는 데이터를 DTO로 미리 정의하였습니다.
Global Exception을 미리 정의하였습니다.
런타임 시점에서 사용자로 시작하여 DB까지의 일련의 흐름을 담은 그림입니다. 모든 컴포넌트 간의 통신 흐름을 call-return 형식으로 표기하였습니다. WAS 부분에서 사용된 프레임워크가 어떤 것이 있는지 간략히 그림으로 표현하였습니다.
인증/인가를 위해 Spring Security를 사용하였으며, AWS S3 버킷과의 API 통신을 위해 Spring Cloud를 사용했습니다.
CRUD 구현을 보다 편리하게 하기 위해 JPA ORM을 사용하였습니다.
Spring Rest Docs를 통한 API 문서화를 위해 JUnit을 사용하여 테스트 코드를 작성했습니다.