Architecture

계기

어찌저찌 회사의 서비스가 출시되었다. 서비스의 개발에서 유지보수 국면으로 넘어가게 되었다. MSA 방식으로 구성해놓은 각 서비스끼리의 소통을 어떻게 해야할지, 로그를 어떻게 쌓아야 할지, HA 를 위해서 어떻게 해야할지 등의 아주아주 많은 과제들이 남아있지만, 일단은 기본적으로 유지보수를 할 수 있는 코드구조를 만들어야 한다는 생각이 들었다. 그리고, 일단은 피상적으로 나누었던 각 서비스들을 도메인(사업영역)에 맞게 나누어야 겠다는 생각 또한 들었다.

분업

그래서 나, 그리고 같이 일하는 분이 이 문제를 나누어 해결해보기로 했다. 같이 일하는 분께서는 도메인 주도 설계를, 나는 아키텍처를 공부하기로 하였다.

사실 시작은 아키텍처가 아니었다. 그러니까, 아키텍처 자체를 먼저 목적으로 공부한 것은 아니었다. 기능이 점점 더 복잡해지면서, 기능을 직접 API Call 을 날리는 식으로는 테스트하기가 어려워지는 상황이 되자, 테스트 코드를 붙여봐야겠다는 생각을 하였고, 자연스럽게 그 뒤의 고민인 어떻게 테스트를 붙여야할지, 어떤 테스트가 좋은 테스트인지를 고민하게 되었다.

Deep Dive

막상 테스트를 추가하려니, 쉽지 않았다. 어떻게 해야할지부터 너무 막막했다. 그래서 '테스트가 가능한 구조' 란 무엇인가에 대해서 고민을 해보기로했다. 그러자 마틴 파울러씨의 블로그가 나왔고, 거기서 unit test 에 대한 글을 읽어보게 되었으며, solitary test 를 하는 방향으로 가야겠다는 작은 결론을 내리게 되었다. solitary testing 이란, service layer 는 repository layer 와 무관하게, repository layer 가 맞다는 가정 하에 testing 을 진행하는 방식을 의미한다. 여태껏 나는 sqlite3 를 통한 in-memory testing 을 하려고 했었는데, 의존성 관계가 복잡해지고, 다양한 entity 들이 load 되어 context 가 만들어지는 상황에서 해당 testing 은 쉽지 않았다. 그래서 Mocking 을 통한 solitarity 의 확보를 하고, service layer 의 unit testing 은 service layer 의 unit testing 만을 담당하게 하였다.

Architecture

그 다음에 했던 고민은 'repository layer 와 service layer 의 책임은 어디까지일까?' 였다. 사실 thread-safe 를 보장하기 위해, singleton 방식으로 read/write connection 관리를 하기 위해 repository layer 를 만들어 놨던 터라, Nest 에서 사용하는 것처럼 @InjectRepository(RepositoryName) 과 같은 decorator 를 사용하진 않았다. 그래서 그 둘사이의 책임이 어디까지인지를 고민했던 거 같다. 고민하고, 찾아보고, 이야기 한 결과, database 에서 값을 빼 오고, 그걸 의미가 있는 class 로 변환해주는 과정까지만이 repository layer 의 책임이라고 결론을 내리게 되었고, Nest 를 사용하는 이상, Nest 스럽게 annotation(decorator)를 적극 사용하자는 생각에, 기존에 만들었었던 repository layer 라는 별도의 .ts 파일이 없이, TypeOrmModule 을 같은 Entity 를 사용하더라도, forRootAsync 에서부터 connection 단위로 아얘 분리하는 방법을 알아내 repository layer 를 아얘 없애게 되었다.

그러나 거기서 고민은 끝나지 않았다.

Clean Architecture

나는 좀 더 편하게 일하고 싶었다. 코드의 결합이 단단하지 않고 말랑말랑해서, 각각의 코드가 의존성은 느슨하되 붙어있는 응집도는 올라가는 구조를 원했다. 이 때가 클린 아키텍처를 꺼내 볼 때라고 생각해서 열심히 보았다. SOLID 란 무엇인지, Component 를 구성하는 좋은 방법은 무엇이 있는지, 책의 중간지점까지 엄청나게 재미있게 보았다. '좋은 아키텍처가 왜 필요한지 알기 위해선, 나쁜 아키텍처로 한 번 구성해보면 된다' 라고 하는 중간에 적힌 말처럼 나쁜 아키텍처를 통해 고생을 한 번 호되게 해 봤으니 좋은 아키텍처가 왜 필요한지를 너무 느껴 아주아주 적극적으로 보게 되었다.

Talk is cheap, show me the code

절반까지 본 다음엔 바로 내 코드를 바라보았다. 말로만, 생각으로만 끝내고 싶진 않았다. component 간의 하중 분배, fan-in, fan-out 을 통한 dependency index 계산, abstract class, interface 와 concrete class 를 통한 abstract index 계산, 그리고 그 둘을 통해 만든 그래프와 그 그래프의 main sequence 간의 거리를 통한 내 class 의 적절성 평가 등등을 해 보았고, Jetbrain 에서 지원하는 class diagram 을 그리는 기능을 통해 내 class 의 관계를 볼 수 있었다.

Abstraction with Nest and TypeScript

가장 먼저 보였던 건 추상화의 부재였다. 각각의 controller, service, repository 가 abstract class, interface 가 아닌 concrete class 에 의존하고 있었다. 특히 개발 초기라 developability 를 높여야 하는 와중에 더더욱 신경써야 하는 과정이 전혀 이뤄져 있지 않다는 걸 깨달았다.

그래서 interface 를 사용하려 했으나, TypeScript 의 transpiler 가 돌아간 이후 interface 는 사라져버리고, Nest 팀에서도 그런 이유로 abstraction 에서 interface 를 통한 abstraction 은 지원하지 않는다고 하였다. 다만, abstract class 를 통한 abstraction 은 transpiler 가 작동한 이후에도 class 형태로 존재하여, provider 를 통한 abstraction 을 진행하려면

@Module({
	...
	providers: [
		{
			provide: AbstractClass,
			useClass: ConcreteClassThatExtendsAbstractClass,
		}
	],
	...
];

와 같은 방식으로 추상화를 진행하는 것을 권장하였다.

이번 기간동안은 제품 개발, 그리고 이런 것들에 대한 공부와 고민이 많이 이뤄졌었다. velog 에는 거의 올리지 않았고, notion 에다가 열심히 작성 중이다.


Docker

도커라는 건 이제 '모르면 안 되는' 게 되었다고 생각한다. 지금 진행중인 사이드프로젝트를 100만 credit 을 받아 NCP(Naver Cloud Platform)에 migration 하고 있는데, 100만 credit 이 생긴 기념으로 비싸서 사용하지 못 했던 aws 의 codepipeline 같은 걸로 ci/cd platform 을 구축하려고 했다.

그러나, NCP CodeBuild 에서 제공하는 nodejs runtime 의 version 은 11버전대였고, 내가 원하는 다른 build runtime 을 위해서는 네이버의 Docker 기반 container 를 통해 나만의 환경을 구성한 다음 끌어다 쓸 수 있다고 한다.

현재 HA 확보를 하고싶은 욕심에 K8S, Docker 스터디를 하고 있는데, 마침 잘 되었다고 생각한다.


MQTT, SK ThingPlug

사이드프로젝트의 infrastructure 를 The Things Network 에서, SK 의 LoRa based infrastructure 인 ThingPlug 로 변경하였다. 이유는 국내에서 서비스 하는 걸 고려했을 때 SK 인프라가 가장 괜찮았기 때문이다. TestBed 를 진행중이고, MQTT 기반의 protocol 로 server application 을 또 구성하고 있다.


Algorithm

알고리즘도 따로 풀고있다. 신체건강을 위해 웨이트를 하면서, 뇌지컬(?)을 위한 기초체력 단련인 알고리즘은 하지 않았단게 뭔가 허전해서 그런 듯 하다. 일단 leetcode easy 문제들을 쭉 풀어보고 있는데, 하면서 많이 배운다. medium 도 한 주에 두어 개씩은 도전해보려고 한다.


기타

이런저런 이유로 심경이 좀 복잡미묘하다.

profile
правда и красота, truth and beauty

0개의 댓글