[중요!] 이글은 강의 글이 아니에요! 아직 시행착오를 많이 겪는 중이라 틀린 내용이 있을 수 있습니다. 깊이 공부를 마친 후 글을 보완할 예정입니다.
이번에 팀 내에서 인증 리팩터링과 MSA를 적용해보는 업무를 맡았습니다.
MSA를 적용해보며 겪었던 고민 점 및 추후 코드에 보완할 부분을 스스로 피드백해보려고 합니다.
MSA란?
MicroService Achitecture의 준말입니다.
단일로 구동하던 애플리케이션을 여러 애플리케이션으로 나누는 것이 핵심인 설계입니다.
왜 나눠?
MSA로 나눠서 얻는 장점은, 모놀리식 아키텍처(단일 컨포넌트로 통합되어있는 설계)가 가지는 단점을 보면 알 수 있습니다.
모놀리식 vs 마이크로서비스
모놀리식 아키텍처의 단점
- 프로젝트 규모가 커졌을 때 각 코드가 서로 의존성을 가진다.
- 아주 일부 기능만 변경되도 애플리케이션을 다시 빌드하고 배포하여야 합니다.
- 기술과 언어가 종속됩니다.
- 코드의 양이 많아 개발자가 모든 코드를 이해하기 힙듭니다.
마이크로서비스 아키텍처의 장점
- 팀별로 각 애플리케이션을 담당을 나누기 쉽습니다.
- 각 애플리케이션 별도의 배포가 가능합니다.
- 애플리케이션마다 기술과 언어가 자유롭습니다.
- 본인의 팀/개발자가 담당하는 애플리케이션의 코드만 이해하면 됩니다.
감람스톤에서는..
- 서비스의 규모가 커지고,
- 빠르게 개발을 진행하며 생긴 기술부채 해결
하기 위하여 MSA와 리팩터링을 진행하게 되었습니다.
이제 이론은 알았으니 개발을 진행해봤습니다.
MSA Database 분리
가장 먼저 겪었던 고민은 DB 분리였습니다.
DB와 각 애플리케이션을 1:1로 분리하는 것은 알겠는데 어떻게 DB의 무결성을 관리하는 지, 어떤 구조로 설계하는 지 궁금했습니다.
제가 조사한 MSA에서의 DB 설계는 다음과 같습니다.
하나의 DBMS를 실행하고 해당 DBMS의 하나의 유저를 생성한 후, 여러개의 Database로 분리합니다.
여기서 각 DB는 해당모듈에서 사용하는 데이터만을 저장합니다.
DB를 분리했을때의 장점
- 각 애플리케이션의 DB를 변경해도 다른 애플리케이션에서는 영향을 미치지 않습니다.
- 각 애플리케이션의 비즈니스 로직에 가장 잘맞는 DBMS를 사용할 수 있습니다.
검색 기능을 수행하는 애플리케이션은 ElasticSearch를 사용할 수 있고,
시계열 값을 사용하는 애플리케이션은 TSDB를 사용할 수 있습니다.
DB를 분리했을때의 단점
- 여러 Database의 데이터를 join하는 쿼리를 구현하는 것이 어렵다.
- 여러 종류의 DBMS를 사용할 때 복잡성이 발생한다. (여러개의 SQL, NoSQL)
Two Phase Commit (2PC)
그렇다면 서로 JOIN되어 있는 두 테이블의 값을 변경해야하는 경우에는 어떻게 처리할까요?
예를들어 인증DB의 users라는 테이블과 협업의 videos 테이블을 업데이트한다면 어떻게 해야할까요?
그런 경우 2PC(Two Phase commit)이라는 기능을 사용합니다.
2PC는 각 DB에서 prepare라는 검증 단계를 추가함으로써 트랜잭션이 원자성을 가질 수 있도록 하는 것입니다.
쿼리 플로우로 보면 다음과 같습니다.
두 DB Node에서 commit을 받아야 승인처리합니다.
DB 조정자 DB 참가자
커밋하기 위한 쿼리
-------------------------------->
VOTE YES/NO prepare*/abort*
<-------------------------------
commit*/abort* COMMIT/ROLLBACK
-------------------------------->
승인 commit*/abort*
<--------------------------------
END
https://en.wikipedia.org/wiki/Two-phase_commit_protocol
Two Table Join
서로 다른 RDBMS에 존재하는 두 테이블을 조인하는 경우에는 이런 방식의 SQL을 사용할 수 있습니다.
SELECT <...>
FROM garamstone_auth.users ga_user
JOIN gamramstone_workspaces.videos gw_video
ON ga_user.id = gw_video.user_id;
gorm에서는 이렇게 작성합니다.
db.Table("employee")
.Select("department.id, employee.department_id, employeeContact.employee_id")
.Joins("JOIN department on department.id = employee.department_id")
.Joins("JOIN employeeContact on employeeContact.id = employee.id")
.Find(&results).Error
if err != nil {
return err, ""
}
'GO' 카테고리의 다른 글
[GO]클래스 없는 객체지향 언어 (0) | 2023.05.24 |
---|
취미로 쓰는 개발 블로그입니다. 문의: puleugo@gmail.com