by Michael Keeling
생각보다 협업할 때 좋은 내용도 많아서 곱씹으면서 읽는 부분이 많았다.
-
- 모듈은 설계 시점에 의미 있고 파일 시스템 상의 어떤 형태로 표현할 수 있으며 소프트웨어가 동작하지 않아도 상관없다.
- 컴포넌트는 런타임 시점에 의미 있는 요소이고 시스템이 동작하지 않으면 사라진다.
- 용어는 정확하게 사용할수록 좋으니 참고하자.
- 디자인 마인드셋 장착하기,
이해 -> 탐색 -> 실현 -> 평가
- 소프트웨어 시스템을 만드는 데에 중단이란 없다. 릴리즈만 계속할 뿐이다.
- “모든 아키텍처는 설계지만, 모든 설계가 아키텍처는 아니다.” - 그래디 부치
- 어떤 기능 요구사항이 아키텍처의 의사결정을 주도할 정도로 중요하다면, 그것은 ‘영향력 있는 기능 요구사항’이다.
- 모든 세부적인 기능까지 고려하면서 구조를 잡지 말자
- 최대한 기획서 비즈니스 로직을 큰 가닥을 몇개 잡아놓고 구조 잡기
데이터 기반 웹 애플리케이션의 아키텍처 패턴
- 3계층
- [디스플레이 계층] - [비즈니스 계층] - [DB]
- 웹앱의 경우 각각 UI렌더링, 서버와 연관된 비즈니스 로직, 데이터 저장 역할이다.
- 발행/구독
- [디스플레이][룰 체커] - [이벤트버스] - [데이터 접근자] - [DB]
- 각 요소마다 메시지를 만들고 이벤트 버스로 보낸다.
- 컴포넌트는 관심있는 특정 메시지 타입을 구독한다.
- 서비스 지향
- [디스플레이][서비스 레지스트리] - [데이터 서비스][룰 서비스] - [DB]
- 중앙에 서비스 등록/관리하는 레지스트리가 있다.
- 컴포넌트는 서비스를 직접 호출하거나 정보 요청하고 받을 수 있다.
- 어떤 아키텍처든 각 구성 요소는 적어도 하나의 역할을 해야 한다.
- 즉, 목적이 없는 구성 요소는 없어야 한다.
결정은 미룰 수 있을 때까지 미루자
- 한번 결정하면 되돌리기 어렵다.
- 언제라도 쉽게 바꿀 수 있는 의사결정이라면 이미 아키텍처와는 별로 상관없을 것이다.
- 의사결정을 하기 위한 질문들
- 결정을 못해서 더 나아갈 수 없는가?
- 더는 기다릴 수 없이 당장 결정해야만 해결되는 문제인가?
- 의사결정이 더 많은 선택지나 기회를 만드는가?
- 결정은 미루면 위험이 매우 커지는가?
- 결정을 내릴 때의 영향력을 충분히 숙지하고 있는가?
- 지금 왜 결정을 내려야만 하는지 논리적 근거가 명확한가?
- 잘못되었을 경우 되돌릴 만한 시간은 있으며, 실수 감당할 수 있는가?
아키텍처 패턴
- 디자인 패턴은 프로그램의 재사용성, 유지 보수성을 높일 수 있는 다양한 구성에 대한 것이고 아키텍처 패턴은 좀더 품질에 관한 시나리오를 해결하는 데 목적이 있다.
- 레이어 패턴
- 코드를 나누고 관심사별로 독립적인 레이어를 구분한다.
- 어떤 모듈이든 반드시 하나의 레이어에만 존재해야 한다.
- 상위 레이어는 하위 레이어를 사용할 수 있고, 관계는 한 방향으로만 흘러야 한다.
- 순환 참조는 허용되지 않는다.
- 최상위와 최하위 레이어 간에는 별도 추상화 작업이 필요하며 복잡해질 수 있다.
- ex. 리액트로 따지면 redux와 같은 라이브러리가 필요해지는 이유랄까
- 포트와 어댑터 패턴
- 레이어는 도메인이나 비즈니스 로직을 의미한다.
- 포트는 레이어와 어댑터 사이의 인터페이스를 정의한다.
- 어댑터는 레이어가 데이터나 이벤트를 접근하는 데 사용하는 코드다.
- 레이어는 포틀르 노출하는데, 모든 레이어가 포트를 노출할 필요는 없다.
- 파이프와 필터 패턴
- 단방향으로 데이터를 변형하는 작업만 한다.
- 필터는 데이터를 읽고 변형한 후 결과 데이터를 내보낸다.
- 파이프는 필터에서 필터로 전달하는 커넥터이며 데이터 순서를 유지한다.
- ex. 유닉스 pipe 명령어, rxjs의 pipe도 궤를 같이하는 예시일듯
- 서비스 지향 아키텍처 패턴
- 특정 기능을 가진 컴포넌트를 독립적인 서비스로 구현한다.
- 시스템은 실행 중에 서비스를 조합한다.
- 즉, 서비스를 사용하는 측에서는 서비스가 어떻게 구현되었는지 몰라도 이를 호출/실행할 수 있어야 한다.
- 앱 전체의 코드가 하나의 배포에 구현되는 모놀리식 모델과 달리, 독립된 각 서비스를 결합한다.
- ex. 좀더 대규모 시스템 구축할 때 쓰는 패턴인듯
- 발행/구독 패턴, 공유 데이터 패턴, 멀티 계층 패턴, 오픈소스 공헌 패턴 …
이름 짓기 7단계 예시
- 모름: the thing that does the thing
- 넌센스: cranberry
- 정직: job starter process
- 정직하고 완전함: data fetcher, checker, transformer, job starter
- 올바름: data transformation job runner
- 의도를 담음: data preparer
- 도메인 추상화: data prepagation agent
=> 시스템 다른 부분에서 상호작용의 규칙을 지닌 요소가 agent라는 표현을 사용하므로 적절하다. 이름은 시스템을 얼마나 잘 이해하고 있는지 판별하는 리트머스 종이이다. 이름이 넌센스나 정직한 수준에 머물러 있다고 생각한다면 지금 설계하고 있는 시스템의 개념을 더 깊게 파보자.
좋은 비평 vs 나쁜 비평
비평은 설계의 장점을 드러낼 수 있도록 해야 하며, 나쁜 설계 속에 좋은 아이디어가 숨어 있기도 하고 최고의 설계에서도 발전할 구석은 있다. 어떤 설계든 긍정적인 피드백과 건설적인 비평을 받게 해야 한다.
- 설계목표와 설계자가 제안한 해결방식에 집중한다. <=> 비평을 받을 때 방어적인 자세를 취한다.
- 구체적으로 사실에 근거해 말한다. <=> 개인적인 취향을 말한다.
- 문제를 더 명확하게 파악하도록 질문한다. <=> 문제 해결의 주변만 짚는다.
- 위험 요소를 지적하고 설계로 발생할 문제에 대해 알려준다. <=> 악랄하게 군다(다음 희생양은 당신이 될 거다).
- 설계상 이점을 언급한다. <=> 단점만 파헤친다.
아키텍처 평가
- 어떤 리뷰어는 그 아키텍처를 걸작이라고 생각할 때 다른 리뷰어는 불타는 쓰레기라고 평가할 수 있다.
디자인 루브릭
은 리뷰어가 아키텍처의 적합성을 판단할 때 사용해야 하는 기준을 정의한다.- 기준(criteria): 설계의 산출물을 평가하는 데 사용할 특성. ex) 성능, 확장성
- 등급(rating): 특성을 해석하는 데 사용할 척도. ex) 1 ~ 4
- 기준에 따른 시나리오를 통해 등급을 매긴다.
ex1) 성능은 평균 부하에서 5초 이내에 응답해야 한다.
ex2) 시스템은 향후 7년간 데이터가 연평균 5% 늘어난다는 가정하에 확장 가능해야 한다!