아키텍쳐를 변경해야 하는 큰 이유 3가지 ⚙️
장애, 트래픽의 변화, 그리고 '조직의 구조의 변경'.
서비스가 성장하고, 규모가 커지게 되면 조직의 변화가 생기게 된다.
인프런은 매우 빠른 속도로 성장했고, 그와 더불어 조직의 구조가 변화되었다.😇.
회사의 매출이 늘어나면서 회사 내부 규모가 성장했다.
규모가 커지면서 커뮤니케이션 비용도 늘어나게 되었다.
인프랩의 선택
하나의 목적을 가진 'Cell' 이라는 목적 조직을 구성
전체의 모든 비지니스를 두고 회사 구성원이 고민하지 않고, Cell 단위에서 고민 후 즉시 실행 하도록 조직을 개편.
목적 조직의 구성의 목표는 '회사 규모가 커짐에도 비지니스 개발 속도를 유지하는 것' 이었다.
담당하고 있는 목적에 따라 담당 'cell' 내부에서 즉시 실행하게 되었고,
회사 규모가 커졌음에도 불구하고 비지니스 개발 속도감이 유지되었다.
단기적인 관점에서의 목표 실행력과, 가시적인 제품 개발 속도가 상당히 높아졌다.
하지만,
장기적 제품 속도, 조직 안정감이 저해되었다. 😫
무엇이 문제가 되었는가 ?
문제 #1. 내부 코드 개선 보다, 제품 지표 개선과 상향이 우선 됨
제품이 성장하는 것을 보고, 지표의 상승을 보니 이것에 집중하게 되었다.
코드 개선 보다 당장 평가가 되고 지표가 보이는 제품 개발에 더 집중하게 되었다.
문제 #2. 모든 Cell 마다 배정 할 수 없는 부족한 시니어의 숫자.
시니어의 절대적인 숫자 부족으로 Cell마다 기술적 편차가 생기게 된다.
문제 #3. Cell 에 PM, Designer 등 1명씩 존재하는 직군에서 퇴사자가 발생시 대체 불가
그 Cell 은 pm, designer 가 없는 조직이 되어 버린다.
이러한 이슈들로, 개발의 속도감을 선택하였지만 조직 안정감이 저해되었다.
목적 직군 (기존 Cell) + 기능 직군 편성
기능 직군 : 각 파트별 기능 직군을 만들게 되었다.
예> 한 명이 두가지 직군에 속하게 된다. 인프런 강의 Cell (목적 직군), 개발자 직군 (기능 직군)
이렇게 구조를 개편하면서 각각 Cell 조직간의 소통이 원할해 졌다.
문제 #2 와 문제 #3 은 잘 해결 되었다.
하지만 ...
1개의 거대한 레거시 프로젝트를 N 개의 조직이 공유하게 됨으로써,
이 단일 레거시 시스템의 개편은 '어느 조직의 목표'인지 모호해졌다.
각자의 조직이 맡고 있는 서비스가 모두 다르지만
분명 이 거대한 레거시에 베이스를 두고 있는데, 막상 어떤 조직이 도맡아서 개편을 해야할지 매우 애매했다.
"그거 MSA 하면 해결 되지 않나요? (긁적)" 🧐
많은 개발자들은 MSA 를 은탄환처럼 생각한다. 🔫
MSA 가 모든 문제의 해결이 될 것이라는 종교적인 믿음을 가지고 있다.
나 또한, 처음 MSA 라는 개념을 알게 되고 들었을 때 막연한 MSA 에 대한 환상을 가지고 있었다.
'하지만, 그렇지 않다!, 절대 그렇지 않다! '
인프런에서도 마찬가지였다.
MSA 는 만병 통치약이 아니다.
소규모 팀이 MSA 를 도입하면 비지니스 개발 속도를 낼 수 없다.
소규모 조직은 MSA 를 하면 절대 안된다.
분할 정복
거대한 시스템을 복제하여 작은 시스템 여러개로 분할 하여 해결하기로 했다.
이렇게 함으로써 조직별 레거시 시스템이 도출되게 된다.
이렇게 되면,
목적 조직 마다 레거시 시스템을 목적 조직의 성격에 맞게 분할되어 가지게 된다.
회색지대가 없이, 본인 팀의 레거시 시스템이 노출되고, 레거시 개편이 목적 조직의 목표가 된다.
그럼.. 프로젝트만 복제해서 각자 팀이 잘 개편해서 해결 되었답니다!
... 가 아니었다.
위에서 분할 정복 방법을 통해 1개의 서비스가 N개의 프로젝트로 분할되었다.
즉, 이 말은 N배로 증설해야할 인프라 문제가 생겼다는 것이다. 😳
코드복제뿐 아니라 인프라 계층 전체의 복제가 필요했다.
인프라를 코드로 관리하게 하는 방법론인 IaC
에 집중하게 되었다.
테라폼, 앤서블 등 여러가지 IaC
툴이 있지만 인프런은 Pulumi
를 도입했다.
왜 인프런은 Pulumi 를 선택했는가?
1.선언형 언어가 아니기에 IDE 활용, 추상화된 설계가 가능. 가장 훌륭한 문서 품질 (공식문서가 매우 좋아서 문서만 봐도 사용 가능하다고 한다.),
2.프로그램 언어로 구현하기에, 모노레포등으로 높은 품질 관리가 가능.
3.프로그래밍 개발하듯, IaC 를 관리할 수 있음.
4.딘일 테스트가 가능
pulumi 로 레거시 인프라를 언제든 쉽고, 바르고, 동일하게 복제가능한 인프라 환경을 구성하게 되었다.
1개의 서비스가 N개의 프로젝트로 분할이 되었으니,
클라이언트가 요청해서 들어오는 URL 도메인 하나를 여러개의 프로젝트가 공유하는 문제가 생겼다.
URL 도메인의 분기가 필요했다.
URL Path 에 맞춰 도메인을 라우팅한다고 생각하면 가장 먼저 떠오르는 것이 Load Balancer
다.
나 또한, 강의 현장에서 '오 저건 로드밸런스로 해결했겠구만!' 이라고 생각했다. 🙄
하지만, 인프런은 CloudFront 를 선택했다. (크흠)
인프런은 CloudFront 를 통해 path 에 맞춰 프로젝트를 분기했다.
왜 인프런은 CloudFront 를 선택했는가?
1. CloudFront는 Load Balancer 가 지원하지 않는, 다양한 서비스로 라우팅 가능하다.(S3, Api gateway 등... )
2. 계속해서 URL path 단위로 변화가 필요하기 때문에, 단일 EndPoint 를 사용하는 GraphQL을 도입할 수 없었던 상황이므로, CloudFront 를 사용했다.
1개의 레거시를 N개의 프로젝트로 분할 한다는 것은 내부 API 통신이 많다는 것을 의미한다.
내부에서 트래픽이 발생하는 것임에도 Public IP를 사용한 통신이 많아지게 된다.
네트워크 리소스, 트래픽 비용이 커지고, 사내 와이파이, VPN 기반의 내부망 구성이 어려워진다. 🙄
인프런은 Private VPC LB 를 통해 해결했다.
그래서 Public LB 와 Private LB 총 두개를 구성했다.
줄어든 네트워크 리소스, 트래픽 비용 감소, 내부망 구성이 쉬워지는 효과
내부 API 요청이 상당히 많아지면서, 내부 API 요청이 실패했을 시 많은 문제들이 생겼다.
고민되는 문제들
1. 다른 프로젝트 로직까지 매 요청마다 챙겨야 하는가?
2. 요청된 API 중 하나라도 실패하면 어떻게 해야하는가?
3. 모든 API가 성공할 때까지 대기해야하나?
나는 API 문제를 현장에서 들으면서 '메세지 큐잉을 사용하면 되려나?.. 카프카? 음..' 라는 생각을 했다.
인프런은 AWS 의 SNS-SQS
을 통해 비동기 아키텍쳐를 구축했다.
개인적으로 SNS-SQS
를 사용해본적이 없어서 매우 흥미로웠다.
메세지큐 아키텍처를 통해 도메인 의존성 분리한다.
SNS 에서 메세지 큐잉을 총괄하여 Subscibe 하는 서비스들에 붙은 SQS 에 전달한다.
API 통신 실패시 재시작도 가능하며, 최종적으로 SQS 를 통해 일관성을 보장한다.
SNS-SQS 비동기 아키텍처를 통해 얻은 효과
1. 이벤트만 발행하면, 메세지 큐를 통해 각각의 로직을 실행할 것이므로 API의 결과를 기다릴 필요가 없다.
2. 실패하더라도 재시작을 보장해준다.
2. 일관성을 보장한다.
주의할점
'트랜잭션'이 필요한 곳에는 사용하지 않는다.
여러 로직이 '비동기'로 실행되도 무방할 때만 적용한다.
즉, 꼭 동기화가 필요하지 않을 경우만 SNS-SQS 사용.
만약, 트랜잭션이 중요하면, 현재 아키텍처의 단일 DB의 장점을 살려서 연관 테이블에 직접 SQL 을 실행한다.
이런 점이 단일 DB를 사용하는 장점이다.
위에서 잠깐 이야기 했던 것 처럼 여러 프로젝트가 단일 DB 의 사용으로 얻는 이점도 있지만 여러가지 문제점도 존재한다.
문제점
1. 테이블 변경사항에 대한 전체 조직이 싱크를 맞춰야한다.
2. 문제가 되는 SQL 출처를 찾기가 어렵다.
3. 중복된 도메인 클래스 관리 (각각 매핑된 도메인 클래스.. -> 애매하게 겹치는 Entity들.. 이거는 진짜 어떻게 해야하나..🙄)
1.테이블 변경사항에 대한 싱크 문제
- 모든 DDL에 대해 단일 채널 알람
2.문제가 되는 SQL 출처 찾기 문제
- 프로젝트마다 다른 DB 게정 사용하도록하여 문제가 되는 프로젝트가 어떤 것인지 빠르게 파악 할 수 있도록 했다.
3.중복된 도메인 클래스 관리
'어설픈 추상화 / 공통화 보다 삭제하기 쉬운 중복이 더 낫다' 👍🏻
- 거대한 하나의 도메인 클래스보다는 각 조직마다 최소한의 로직만 있는 중복된 개별 도메인 클래스를 사용하는 방법을 채택.
- 정답이라기보다는 적정한 방법을 선택한것!
- 항상 기회비용과 저울질이 필요하다.
- 물론, 도메인에 종속적이지 않은 클래스들은
Github Registry
로 관리한다.
개인적으로, 이 부분에서 다시 한 번 '적정 소프트웨어' 에 대한 고찰과 고민은 정말 중요하다고 생각이 들었다.
개발에서 절대적으로 은탄환은 없다. 🔥
동욱님은 내가 개발자로 성장할 수 있도록 해준 가장 큰 원동력이었다. 🔥
전설적인(?) 동욱님의 EO 영상에 매우 깊은 감명과 용기를 얻고 개발을 시작했고, 지금까지도 계속 열정적으로 성장을 갈망하며 개발을 할수 있게 되었다.
작년으로부터 이어진 동욱님의 고민이 담긴 '인프런 아키텍쳐' 발표는 개발자가 어떤 고민을 어떤 방향으로 해야할지, 그리고 서비스를 어떤 시각으로 바라보며 개발을 해야할지를 진심으로 느끼게 해준다.
개발자를 넘어, 개발을 통해 세상에 선한 영향력을 끼치고, 그것을 위해 끊임없이 정진하는 멋진 동욱님과 같은 사람이 되고싶다.
다음 인프런의 아키텍처도 기대할게요 :)
세션에 다녀온 것 같네요. 정리된 글 잘 읽었습니다!