아키텍처 설계

leemiyeon·2023년 7월 18일

🗂️ 시스템 아키텍처의 구성 요소 설명

👥 Client Layer

TypeScript와 React를 기반으로 구축되었으며, Next.js를 사용하여 서버 사이드 렌더링을 지원합니다. React-Query와 Zustand를 이용하여 상태 관리를 처리하고, UI 디자인은 Tailwind CSS로 구성되었습니다. 클라이언트는 Vercel로 배포되어 사용자들에게 웹 애플리케이션을 제공합니다.

TypeScript: 정적 타입 언어로 개발하여 타입에러를 미리 방지하고 코드의 안정성을 향상시킵니다.
React: 컴포넌트 기반 UI 개발을 통해 재사용성과 유지보수를 용이하게 합니다.
Next.js: 서버 사이드 렌더링을 지원하여 초기 로딩 속도를 개선하고 SEO를 향상시킵니다.
React-Query: 데이터 요청과 관리를 간편하게 처리하며, 데이터 캐싱을 통해 성능을 최적화합니다.
Zustand: 상태 관리 라이브러리로, 간단하고 강력한 상태 관리를 제공합니다.
Tailwind CSS: 간편한 CSS 프레임워크로, 커스터마이징이 쉽고 반응형 디자인을 쉽게 구현할 수 있습니다.
Vercel: 정적 사이트 호스팅 서비스로, 배포 과정을 간소화하여 웹 애플리케이션을 빠르게 배포합니다.

💻 Server Layer

프로젝트의 서버 레이어는 Java 11을 기반으로 구축되었습니다. Spring Boot를 사용하여 서버를 개발하고, Spring Security를 통해 사용자 인증과 권한 관리를 처리합니다. Gradle을 이용하여 의존성을 관리하며, MySQL과 Redis 데이터베이스를 사용하여 데이터를 관리합니다. OAuth2와 JWT를 이용하여 보안 인증과 토큰 기반의 인증을 지원하며, Thymeleaf를 사용하여 서버 사이드 렌더링을 처리합니다.

Spring Boot: 빠른 개발과 설정을 제공하여 RESTful API를 쉽게 개발합니다.
Spring Security: 사용자 인증과 권한 관리를 처리하여 보안성을 강화합니다.
Gradle: 의존성 관리와 빌드 과정을 효율적으로 처리합니다.
MySQL: 관계형 데이터베이스로, 데이터를 테이블 형태로 구성하여 구조적인 관리를 제공합니다.
Redis: 인메모리 데이터베이스로, 캐싱을 통해 빠른 데이터 조회를 지원합니다.
OAuth2와 JWT: 보안 인증과 토큰 기반의 인증을 처리하여 보안성을 강화합니다.
Thymeleaf: 서버 사이드 렌더링을 위한 템플릿 엔진으로, 동적인 서버 페이지 생성을 지원합니다.

🛠️ DevOps Layer

프로젝트의 DevOps 레이어는 AWS EC2와 AWS RDS를 사용하여 서버 인프라를 구축하고, AWS S3를 사용하여 파일 업로드와 다운로드를 처리합니다. 또한, GitHub Actions를 통해 지속적인 배포를 자동화하고 버전 관리를 용이하게 합니다.

AWS EC2: 클라우드 인프라로, 서버를 호스팅하고 관리합니다.
AWS RDS: 클라우드 데이터베이스로, MySQL 데이터베이스를 호스팅하고 관리합니다.
AWS S3: 클라우드 파일 스토리지로, 파일 업로드와 다운로드를 안전하게 처리합니다.
GitHub Actions: 지속적인 통합과 배포를 자동화하여 개발과 배포를 효율적으로 관리합니다.

🗂️ 백엔드 개발에 대한 아키텍처 설계 고려 사항

🔗 데이터베이스 선택: 관계형 데이터베이스인 MySQL 을 선택했습니다.

AWS RDS 지원: AWS RDS에서 MySQL을 지원하는데, 이를 통해 데이터베이스 인프라의 관리를 AWS가 대신해줍니다. 이로써 운영에 소요되는 시간과 노력을 절감할 수 있습니다. MySQL은 AWS RDS를 통해 수평적 확장을 지원합니다. 따라서 트래픽이 증가해도 필요에 따라 데이터베이스를 확장할 수 있습니다.
표준 SQL 사용: MySQL은 표준 SQL(Structured Query Language)을 사용하여 데이터를 조작합니다. SQL은 강력하면서도 직관적인 쿼리 언어로, 데이터 조작 및 검색에 용이합니다.
데이터 관계 표현: 관계형 데이터베이스는 여러 테이블 간의 관계를 표현하는데 용이합니다. 이로 인해 데이터의 논리적 관계를 간편하게 나타낼 수 있고, 복잡한 쿼리를 사용하여 데이터를 효율적으로 추출할 수 있습니다.
구조화된 데이터 저장: MySQL은 테이블 형식으로 데이터를 저장합니다. 각 테이블은 고유한 스키마를 가지며, 각 컬럼은 데이터 유형과 제약 조건을 가질 수 있습니다. 이렇게 구조화된 데이터는 더 효과적인 데이터 관리를 가능하게 합니다.
관계 무결성 제약 조건: MySQL은 데이터베이스에 관계 무결성 제약 조건을 설정할 수 있습니다. 이는 데이터의 무결성과 일관성을 유지하고 데이터베이스 내의 유효하지 않은 데이터를 방지하는데 도움이 됩니다.

🔗 레이어드 아키텍처 구성: 레이어드 아키텍처를 사용하여 Presentation, Business, Data Access 레이어를 구분하고 역할과 책임을 분리하였습니다.

유지보수성 향상: 레이어드 아키텍처는 각 레이어를 분리하여 역할과 책임을 명확히 분담하기 때문에 유지보수가 용이합니다. 한 레이어의 변경이 다른 레이어에 영향을 미치지 않고 독립적으로 개발할 수 있습니다.
확장성 제고: 각 레이어는 독립적으로 확장 가능하므로 프로젝트의 규모가 커질 때 확장성을 높일 수 있습니다. 예를 들어, 데이터베이스 변경이 필요할 때도, Data Access 레이어만 수정하면 되므로 전체 시스템의 변경이 최소화됩니다.
테스트 용이성: 레이어를 분리하면 단위 테스트 및 모듈 테스트를 용이하게 수행할 수 있습니다. 각 레이어를 독립적으로 테스트하여 개발자들이 높은 테스트 커버리지를 유지할 수 있습니다.

🔒 보안: 인증 정보를 저장하기 위해 JWT token 방식을 사용했습니다.

상태 정보를 포함: JWT는 클라이언트의 상태 정보를 토큰에 포함하므로, 서버에서 상태를 관리할 필요가 없어집니다. 이로써 서버의 부담을 줄일 수 있습니다.
분산 아키텍처 지원: JWT는 서버에서 발급되므로 다양한 서버 간에도 유효성을 검사하여 통신이 가능합니다. 분산 환경에서 유용합니다.
클라이언트 측 인증: 서버가 사용자 정보를 기억하지 않기 때문에 클라이언트의 인증을 간단하게 처리할 수 있습니다.

🛠️ 성능 최적화: 자주 사용하는 데이터를 Redis에 캐시하여 데이터베이스의 부하를 줄이고, 응답 시간을 단축하였습니다.

로그인 처리: 리프레시 토큰 저장
사용자가 로그인을 하면, 해당 사용자의 Refresh Token과 Member ID를 유효기간 동안 Redis에 저장합니다. 이때, Refresh Token은 Access Token의 만료와 관계없이 별도의 유효기간을 가지며, 일반적으로 Access Token보다 유효기간이 길게 설정됩니다. 이로 인해 Access Token이 만료되더라도 Redis에 저장된 Refresh Token이 유효하다면, 새로운 Access Token을 발급받을 수 있어서 사용자의 로그인 상태를 유지할 수 있습니다.

로그아웃 처리: 리프레시 토큰 제거, 액세스 토큰 저장
사용자가 로그아웃을 하면, Redis에 저장된 해당 사용자의 리프레시 토큰을 제거합니다. 이로써 해당 사용자의 리프레시 토큰은 더 이상 사용되지 않게 됩니다. 동시에 Redis에 로그아웃한 사용자의 액세스 토큰을 저장합니다. 액세스 토큰은 실제로 서비스에 접근할 때 사용되는 토큰으로, 이를 Redis에 저장함으로써 로그아웃한 사용자는 액세스 토큰을 통해 서비스에 접근할 수 없도록 합니다. 이로 인해 로그아웃한 사용자는 토큰이 만료되지 않았더라도 서비스 접근이 차단되어 보안적인 측면에서 안전성을 확보하였습니다.

💻 모니터링과 로깅: @Slf4j 어노테이션을 활용하여 로깅을 간편하게 구현하였습니다.

API 설계: HTTPS를 사용하여 RESTful API를 설계하였습니다. HTTPS를 사용함으로써 통신이 암호화되어 데이터의 안전한 전송이 가능해졌습니다. 또한, URI 구조, HTTP 메서드 사용, 응답 포맷 등의 요소를 고려하여 사용자 친화적이고 일관된 API를 제공하였습니다.

💻 인프라스트럭처 선택: Amazon Web Services(AWS)를 통해 클라우드 환경을 구축하였습니다.

EC2 (Elastic Compute Cloud): 클라우드 상에서 가상 서버를 생성하고 관리할 수 있는 서비스입니다. EC2를 사용하여 프로젝트의 백엔드 서버를 구성하였습니다.
S3 (Simple Storage Service): 객체 스토리지 서비스로, 파일과 데이터를 안전하고 확장 가능하게 저장할 수 있습니다. S3를 활용하여 클라이언트의 업로드한 파일을 저장하고, 정적 컨텐츠를 제공하였습니다.
RDS (Relational Database Service): 클라우드에서 관계형 데이터베이스를 쉽게 운영할 수 있는 서비스입니다. RDS를 사용하여 MySQL 데이터베이스를 호스팅하고, 백엔드와 데이터베이스 간의 상호작용을 지원하였습니다.
CodeDeploy: 애플리케이션 배포 서비스로, 소스 코드를 자동으로 배포하는데 사용됩니다. CodeDeploy를 활용하여 애플리케이션의 지속적인 배포를 자동화하고 안정성을 확보하였습니다.
Route53: DNS(Domain Name System) 웹 서비스로, 도메인 이름 관리와 DNS 라우팅을 제공합니다. Route53을 사용하여 도메인 이름을 연결하고, 사용자가 웹 서비스에 접속할 수 있도록 지원하였습니다.

🛠️ 테스트와 QA: Postman 을 활용하여 API 엔드포인트들을 직접 테스트하고 결과를 확인하였습니다.

Postman: 다양한 요청 메서드(GET, POST, PUT, DELETE 등)를 지원하며, 다양한 헤더와 바디 파라미터를 설정하여 테스트할 수 있습니다. 하지만 포스트맨을 사용하면서 아쉬움을 느낀 부분도 있었습니다. 특히, 수많은 API 엔드포인트가 있을 경우 테스트 케이스를 관리하기가 어려웠습니다. 또한, 수동으로 테스트를 수행하다보니 반복적인 작업과 실수가 발생할 수 있었습니다.

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

아주 유익한 내용이네요!

답글 달기