단잠이 궁금하시다면 ?
https://ryudain.tistory.com/33
[단잠] 대학교 기숙사 메이트 매칭 및 대학 생활 커뮤니티 서비스 회고
✨ 단잠 / 각기 다른 사람들이 모여 단잠에 들다 ✨ 단잠은 대학교 기숙사 메이트 매칭 및 대학 생활 커뮤니티 서비스입니다. 기숙사 메이트 매칭 외에도사용자의 성향에 맞는다양한 운동, 산
ryudain.tistory.com
💭 서론
단잠의 마이그레이션을 위해 모놀리식에서 MSA로 변환하는 과정에서
먼저 팀원들 개인이 각자 MSA 아키텍처를 구상해보고자 포스팅을 작성하게 되었습니다.
제가 작성한 아키텍처가 채택되지 않을 수도 있겠지만,
이러한 과정들로 저희 서비스와 MSA의 구조에 대해서 더 상세하게 이해할 수 있는 좋은 시간이 될 것 같습니다.
그리고 포스팅 작성이 늦으면 벌금이 만원입니다ㅠ
💭 현재 단잠의 문제점
먼저 단잠을 MSA로 마이그레션하게 된 이유 입니다.
현재 단잠은 모놀리식 아키텍처로 구현되어 있습니다.
단잠의 도메인은 크게
- user
- mate
- room
- food
- study
- walk
- work
- chat
- chatroom
- noti
- admin
- home
- coomon
- security
로 나뉘어져 있습니다. 안에 자잘한 기능들도 많이 있는데요.
단잠 초기에 코드 컨벤션이 따로 정해져 있지않고, 개발자분들이 바뀌기도 하면서 기존의 코드들과 새로운 개발자분들의 코드가 합쳐지면서 스파게티코드가 생성되었습니다. 그 외에도 스파게티 코드가 된 이유는 다분합니다.
기본적으로 모든 기능들이 유저와 메이트, 두가지 도메인과 연관지어 있다보니 기능을 하나 추가하려고만 해도 벌써 3개의 도메인에 접근해야하는 사태가 발생합니다. 항상 쿼리 최적화를 해주지 않으면 성능의 저하가 심하게 생겨났는 데요. 몇 개의 기능에선 요청 하나의 10 ~ 30초 이상 잡아먹는 기능도 존재했습니다.
그리고 문제가 또 있습니다. 저희는 팀원분들이 구축한 2개의 서버를 사용하고 있습니다. 하지만 두 개의 서버에 대한 요청 처리(Gateway)와 네트워크 대역대를 따로 처리하지 않고, Nginx만을 사용하고 있습니다.
팀장님께서 쉽게 비유하자면 ,, , request(요청)에 대해서 두 개의 서버를 매장 직원이 매장을 돌면서 재고를 찾는 것과 비슷하게 동작한다고 했는데요... Nginx가 있지만,, 요청의 세분화가 없이 서버에 요청함으로서 request는 매장에 그냥 들어와서 재고를 찾게 되고, 로드밸런싱의 의미가 사라지게 되었다고 합니다.... (세분화 없이 두 개의 서버 모두에게 요청을 보내고 있음으로)
자체 서버가 두개나 존재하는 데 이를 제대로 활용하지 못하고 있었습니다.
-
아직 붙지 않은 기능들이 많은 데 벌써부터 이렇게 스파게티 코드가 되면
나중에 겉잡을 수가 없을 것 같아서 앞선 이유들로 단잠의 마이그레이션을 결심하게 되었습니다.
💭MSA 아키텍처 설계를 위한 개념 학습
우선 MSA 아키텍처를 설계하기 전에 기본적으로 다시 복기해야할 개념들이 있었습니다.
먼저 앞서 얘기한 문제들을 해결할 수 있는 Spring Cloud Gateway, Srping Cloud Eureka, Discovery Service 에 대해서 알아보겠습니다.
✔️ Spring Cloud Gateway
Spring Cloud Gateway는 스프링 프레임워크 기반의 API Gateway 솔루션 입니다.
API Gateway(Gateway Service) 란?
클라이언트가 MSA와 같이 여러개로 나뉘어진 서비스를 모두 직접 호출하게 된다면, 해당 서비스 마다 인증/인가 로직을 구현해야하고, 번거로운 호출을 하게 됩니다.
이때 APiI Gateway는 API 서버 앞단에서 모든 서버들의 엔드포인트를 단일화 해주는 또다른 서비스 입니다. API에 대한 인증/인가 기능을 가지고 있으며, 메시지의 내용에 따라 Application 내부에 있는 MSA로 라우팅하는 역할을 담당합니다.
주요 기능
1. 인증 및 인가
2. 요청 절차 단순화
3. 라우팅 및 로드밸런싱 (API 호출을 적절한 서비스에 라우팅할 수 있습니다.)
4. 서비스 디스커버리(MSA와 같이 동적인 서비스의 위치(IP, Port Number)를 찾는 것)
Spring Cloud Gateway는 가볍고, 확장이 가능하며 Spring 생태계에서 API Gateway 역할을 수행하는 프레임워크입니다.
주요기능
1. 라우팅
2. 필터링: 사전필터(Pre-filter)와 사후 필터(Post-Filter)를 통해서 요청 전후로 다양한 작업 수행 가능
3. 부하 분산(Load Balancing)
4. 보안 (Spring Security 통합 가능, SSL/TLS 지원)
5. 모니터링 및 로깅
✔️ Discovery Service
다음으론 Discovery Service 입니다. Service Discovery를 위해 구축하는 서버입니다.
Service Discovery 란?
서비스의 위치(IP, Port 등)을 저장 및 관리하는 서비스의 주소록 역할을 합니다.
서비스를 호출하는 쪽에서는 서비스의 위치를 알지 못하더라도 Service Discovery를 구현한 구현체에게 서비스의 위치를 물어봄으로서 요청을 전달할 수 있습니다. 연결체의 역할을 수행합니다.
Service Registry(일종의 데이터베이스)가 아닌 앞단의 로드 밸런서를 통해
다른 서비스를 호출하는 방식인 Server-Side Discovery 방식과
Service Registry를 통해 서비스를 호출하는 Client-Side Discovery 방식 두가지가 있습니다.
Discovery Service의 역할
앞선 서비스 디스커버리를 담당하는 역할을 수행합니다. 서비스 디스커버리는 마이크로서비스 환경에서 각 서비스가 동적으로 변화하는 환경에서 다른 서비스의 위치를 찾아내는 것을 의미하며, 이를 통해 각 서비스는 특정 IP 주소나 포트를 하드코딩하지 않고도 다른 서비스와 통신 할 수 있습니다.
주요기능
1. 서비스 등록
2. 서비스 조회
✔️API Gateway와 디스커버리 서비스의 상호작용
클라우드 환경에서 API Gateway는 디스커버리 서비스와 협력하여 동적인 서비스 위치를 관리합니다.
API Gateway는 Discovery Service를 통해서 서비스의 최신 위치를 얻어내고, 이를 기반으로 요청을 라우팅하게 됩니다.
이렇게 디스커버리 서비스를 기반으로 라우팅을 하게 되면서의 이점이 있습니다.
1. 중앙화된 서비스 등록과 조회 가능: 디스커버리 서비스를 통해 모든 서비스의 위치 정보를 중앙에서 관리할 수 있습니다.
2. 동적 스케일링 지원: 클라우드 환경에서 서비스 인스턴스가 동적으로 추가/삭제 될때 실시간 반영을 할 수 있습니다.
3. 단순화된 클라이언트 코드: 클라이언트가 서비스의 위치를 직접 관리할 필요가 없이, API Gateway를 통해서 서비스 호출이 가능합니다.
API Gateway가 서비스 디스커버리 기능을 수행할 때, Discovery Service와 상호작용하여 동작합니다.
Discovery Service가 서비스의 위치 정보를 중앙에서 관리하고 제공하며, API Gate way는 이러한 중앙관리 정보를 사용하여 요청을 라우팅함으로서 더 효율적이고 동적인 서비스 관리가 가능해집니다.
✔️Spring Cloud Eureka
넷플릭스 오픈 소스 프로젝트인 Netfix Eureka를 기반으로 한 Servcie Discovery Server입니다.
앞서 얘기한 디스커버리 서버 기능을 수행합니다. 동적으로 인스턴스를 생성하고 종료합니다.
주요 기능
1. Eureka Server (서비스 레지스트리 역할)
2. Eureka Client (Eureka 서버에 마이크로서비스 등록 및 다른 서비스와의 위치 정보 조회를 위한 Eureka 서버와 통신)
💭MSA 아키텍처 설계
앞선 Spring Cloud Gateway와 Spring Cloud Eureka 를 사용하여 MSA 아키텍처를 설계하고자 합니다.
MSA 아키텍처 설계도
초기 설계도이기 때문에 부족한 점이 있다는 점을 감안하고 봐주시면 좋겠습니다.
아직 도커를 사용하여 컴포넌트를 어떻게 묶을 지에 대해서는 팀원들과 상의를 해봐야하기 때문에, 전체적으로 묶여있는 컴포넌트가 아닌 도커에서 동작한다 정도로 보시면 될 것 같습니다.
해당 아키텍처의 흐름은 아래와 같습니다.
- 모든 비동기 이벤트는 Kafka를 통해서 이루어집니다.
- 동기 요청에 대해서는 OpenFeign을 통해서 이루어집니다.
- 채팅은 WebSocket, 알림은 SSE, 나머지 모든 요청에 대해선 HTTP를 사용합니다.
- 유레카 서버를 통해서 서비스들을 동적으로 할당하고, 게이트웨이에서 이를 통해 서비스 디스커버리를 수행합니다.
- Spring Security는 사용하지 않습니다. 인증/인가 서버를 통해서 게이트웨이에 보내기 전에 요청이 유효한지 확인합니다.
- 모든 에러가 발생하면 Error 서버에 보내고, 해당 서버에서 관리합니다.
- Nginx 웹 서버를 통해서 클라이언트와 소통합니다.
아직 수정사항이 있어보이지만, 초기 설계이기 때문에 팀원분들과 상의를 진행 후 최종 아키텍처를 추가하도록 하겠습니다. 이번 아키텍처 설계는 여기에서 마치겠습니다.
REFERENCE.
'개발 > 프로젝트' 카테고리의 다른 글
[단잠] Git Branch 전략 (5) | 2024.12.18 |
---|---|
[단잠] 팀 컨벤션을 위한 Wiki 스타일 지정 (3) | 2024.12.17 |
[단잠] SSE와 RabbitMQ를 이용한 알림 도입기 [2편] (0) | 2024.11.27 |
[단잠] 트러블슈팅: SSE(Server-Sent-Events) 첫 연결 이후 바로 Connection closed가 되는 현상 (0) | 2024.11.26 |
[단잠] 알림 도입기 (feat. AMQP, RabbitMQ, SSE) [1편] (4) | 2024.11.19 |