멍청한 개발자의 일대기

Clean Architecture(옮기는 중) 본문

Study

Clean Architecture(옮기는 중)

멍청한 개발자 2020. 10. 20. 18:28

<!doctype html>

Lab Day - Clean Architecture


Software Engineer 의 책임

 

원래 책에서 나온 제목은 "소개"인데, 임의로 이렇게 한번 작성해보았다. 그 이유는 소개에서 나온 한 문단이 나에게 매우 와닿았기 때문이다. 이 문서는 이 책을 한번 읽고 그 다음 복기하면서 작성하는 문서이다. 그렇기에 중간중간 내 과거에 작성했던 테스크와 겹쳐서 작성해 보려고 한다.

 

이 문서 초기에는 안좋은 회사의 예를 드는 그래프가 여러개의 기준으로 나온다. 그 내용을 간출이면 즉,

 

"Software Engineer 수 가 생산성을 올리는데 대해서 큰 영향을 줄 수 없다."

 

라는 내용이였다. 그 그래프에서 나온 내용은 회사의 첫 제품이 출시되고 2차, 3차 업데이트를 할 때마다 필요로 하는 Software Engineer에 숫자는 늘어가지만 생산성은 오히려 떨어진다는 것이였다. 저자는 이 상황에 대해서 잘못된 설계에 따른 악순환 이라고 서술했다. 그 이유는 간단하다. 기능을 추가하고 변경하는데 필요한 작업이 하면 할 수록 증가한다는 것이다.

 

즉 초기 설계에는 커다란 작업이 필요가 없었다. 필요한 기능만 구현하면 되기 때문에 Software Engineer가 별다른 큰 생산성 없이도 작업이 가능하다. 하지만 그 이후부터가 문제가 된다. Client가 초기에 요청했던 정도의 비슷한 작업이더라도 이미 잘못된 설계에서 추가나 변경하기에는 똑같은 작업량이 아니라는 것이다.

 

추가와 변경에 따른 빌드와 배포가 다시 필요하고 이는 잘못된 설계일 수록 Software Enginer는 이에 따른 딜레마에 빠지게 된다. 자신의 생산성에 의문을 가지게 되며, 작업 효율은 그에 따라 더 떨어지게 된다. 그러면 기한은 더욱 촉박해지고 Software Engineer는 다시 잘못된 방식으로 '급급하게' 수정하게 된다.

 

이에 따라 여기서 생산성은 0에 수렴하게 된다고 한다. 그럼 CEO의 시각에서는 이전과 다른 생산성에 대해 요청을 하게되고 더많은 Software Engineer를 필요로 하게 되는 '것' 처럼 보인다.

 

그래서 저자는 이러한 문제에 대해서 "빨리 가는 유일한 방법은 제대로 가는 것이다." 라고 이야기한다.

 

아래는 과거에 내가 가진 고정관념에 대해서 다시금 생각하게 해준 문구를 적은 것이다.

Software Engineer인 당신도 이해 관계자임을 명심하라. 당신은 소프트웨어를 '안전하게 보호해야 할 책임'이 있으므로 당신 역시 이해 관계가 존재한다. 이것이 바로 당신의 역할 중 하나이며, 당신의 ''책임'' 중 하나이다.

...

아키텍처가 후순위가 되면 기능구현은 처음에 빠른 ''것'' 처럼 보인다. 하지만 이는 자신의 뼈를 깎아서 내준것과 같다. 이는 결국 Software Engineer에게 돌아오며, 결국 이 상황을 용납했다는 것은 Software Engineer가 아키텍처를 위해 충분히 '투쟁'하지 않았다는 뜻이다.

 

위 문구와 더불어 이 "소개" 챕터를 처음 읽었을 때 아마 이전 회사에서 PM직을 받았을 때가 많이 생각 났던거 같다. 아마 받았다기 보다는 사수가 이직하게 되어 어쩔 수 없이 그 자리를 받았다는게 올바른 표현이라고 할 수 있다.

 

2년정도 가깝게 그 직무를 맞았고 그 사이에 각 분야별로의 개발자들과 같이 스케줄을 조정하고 그러면서 많은 부분에 대해서 배웠었다. 아마 이 책을 사전에 읽었더라면 PM직무를 수행함에 있어. 아니 개발이란 업무를 진행함에 있어서 매우 좋았을거란 생각도 들었다. 내가 이러한 부분을 먼저 알고 개발을 시작했다면 조금더 유연한 프로그램을 만들 수 있었을까? 란 그런 생각.

 

근데 두번째로 복기 하면서 드는 생각은 내가 만약 개발자로써 초기에 읽었다면 이 책을 이해할 수 없었을 것이다. 내가 이제와서 이런 생각이 드는 이유는 아무래도 내 자신이 개발자로써 이미 이에 대해 "증명"을 해왔기 때문이라는 생각이든다.

 

아키텍처가 없으면 어떤 일이 일어나는지에 대한 증명

 

초기 Firmware에서 O2O Service로 넘어오게 되면서 난 초기에 Web Developer로 직무를 수행했다. 새로운 서비스에 대한 Web Service를 만들고 그에 따라 Web Application Server도 겉핡기 식으로 구현했었다.

이후 유지보수에 대한 생각은 하지않고 개발에 착수해 기능을 만들기 급급했었다. 그리고 실질적으로 Service에 대한 Server를 만들 때도 똑같았다. 오로지 그 중심에는 "기능구현"이 먼저였다. 그렇게 어느정도 서비스가 자리가 잡았다는 생각이 들고 개발자를 한, 두명씩 다시금 뽑을 때 쯤에는 이전에 방치한 문제들이 수면 위로 들어났다.

 

이것이 난 저자가 말한 아키텍처가 없을 때, 즉 설계도가 없을 때의 문제라고 생각한다.

 

첫번째 징후는 "무의미한 빌드"였다. 혼자 작업하던 일을 여러명의 개발자와 분활하니 서로 수정한 영역에 대해 Conflict가 나는 횟수가 점차 증가했다. 어떤 기능은 비슷한 기능이지만 다른 모듈로 분리되어 있었다. 이는 나 혼자 작업할 때는 체감할 수 없었다.

 

왜냐면 이 코드는 내가 작성했고 어디랑 연결되어잇는지 "나 혼자" 기억 하고 있기 때문이다. 하지만 협업에 있어서 이 부분은 매우 크게 다가왔다. 서로가 이 코드가 어디까지 영향을 주는지 선이 그어져 있지 않았다. 이 부분은 이 책 중~후반부에도 다시 서술된다.

 

두번째 징후는 "수정에 대한 두려움"이 였다. 이 문제에 대한 수정이 어디에서 터졌는지 점점 Web단인지 Web이라면 어느 형태에서 발생한 문제인지 파악하기 힘들어 졌다. 수정하기 "급급해"지며 이후 원인보다 결과가 앞서는 경우도 생겼다. 그리고 이는 다음 버그에 원인이 되는 악순환이 이어졌다. 여기서 내가 내린 결정은 잘했다고 볼 수 없지만 일시적인 서비스 유지와 "수정 없음"이였다.

 

그리고 새로운 팀과 새로 프로젝트를 짜기 시작했다. 그 때 쯤이 PM 직무를 수행하기 시작했을 시기였다. 그리고 PM 직무를 처음 수행하면서 꽤 많은 시도를 해왔던거 같다. 스타트업에선 흔히들 시도했던 project 전체에 대한 Convension이나, Comit Rule, Branch Rule 그리고 CI/CD, DevOps 등등.. 아마 번지르르 했던건 많이 시도해봣던거 같다. 스타트업이라서 가능한것도 있었고 그리고 그와중에 귀찮은 것과 생각보다 쓸만한 것을 구분하는 계기가 되기도 하였다.

 

그리고 이 새 프로젝트의 첫 배포에 성공했을 때 느낀 것이 있다. 외부적으로 봤을 때는 단 한개의 기능도 바뀐것이 없다. 오히려 줄어들었다고 볼 수 있다. 하지만 소스코드 라인 하나를 수정하는데 드는 비용은 매우 적었고, 문제가 발생했을 때 그 원인을 파악하고 "분리" 할 수 있었으며, 누구에게 어떤 일을 줘야하는지 확실해졌다.

 

이 책은 개발자의 분야를 넘나들어 읽으면 매우 좋다고 생각한다. 여기서 서술하는 모든 Component와 Class, Method는 각 파트별로 Principle이 존재하지만, 결국 저자가 궁극적으로 말하는건 이러한 작은 Princple이 모여서 만들어지는 것이 아키텍트라는 것이다.

 

신호등이라는 "최소한"의 규칙이 존재하기 때문에 자동차는 목적지에 빨리 도착한다.

 

Programing Paradigm

 

이 저자는 건물을 만드는 것에 빗대어 자주 설명한다. 아키텍처는 도면을 디자인은 설계도를 그리고 코드는 블럭 Component는 골격과 같이 많은 내용을 비교한다. 그리고 이 챕터에서는 그중 제일 기본이되는 "벽돌"에 대해서 설명한다.

 

"벽돌", 즉- 코드는 개발하는데 제일 작은 단위라고 볼 수 있다. 이 코드의 질은 개발자에 따라 충분히 달라 질 수 있으며, 각각의 퀄리티가 다르다고 말한다. 모든 벽돌의 퀄리티가 통일 되면 더할 나위 없겠지만 모든 벽돌을 다 두들겨보며 튼튼한지 확인하는 인부 또한 존재하지 않을 것이다. 그럼 최소한 이 벽돌을 어떻게 두면 효과적으로 분산되며 만약 한개가 문제가 생겨도 나머지가 지탱해줄 수 있는 구조를 만들어두어야 한다.

 

"벽돌 하나 금갔다고 벽이 무너지면 그거야 말로 잘못된 설계이다."

 

그래서 그 기초인 Programing Paradigm 에 대해서 저자는 서술을 시작한다. 일단 크게 저자가 설명하는 내용은 3가지이다. 구조적 프로래밍, 객체지향 프로그래밍 그리고 함수형 프로그래밍이다.

 

이는 각각 아래와 같이 문구들이 서술되어있다.

구조적 프로그래밍은 제어흐름의 직접적인 전환에 대해 규칙을 부과한다.

객체 지향 프로그래밍은 제어흐름의 간접적인 전환에 대해 규칙을 부과한다.

함수형 프로그래밍은 할당문에 대해 규칙을 부과한다.

 

그리고 그 뒤에는 아래와 같은 문장도 같이 서술되어 있다.

각 패러다임은 프로그래머에게서 권한을 박탈한다. 어느 패러다임도 새로운 권한을 부여하지 않는다.

 

이 문장은 내게 많이 와닿았다. 구조적 언어, 그리고 객체 지향 언어도 사용해 보았지만 이들이 하는 역활은 각 패러다임에 맞게 작성하지 않을 경우 에러를 보여주고 프로그래머가 "제약된 권한"을 어겼을 때에 대해서 문제를 알려준다.

 

이로써 얻는 이득이 있기 때문이다. 저자는 이를 증명하기 위해 "과학을 증명하는 법"을 예시로 들었다.

F=ma가 세상이 움직이는 방식을 설명하는 믿을 만한 법칙이라는데 생사를 건다. 한 걸음씩 내딛을 때마다 F=Gm1m/r2이 옳다는데 건강과 안전을 건다.

과학은 서술된 내용이 사실임을 증명하는 방식이 아니라 서술이 틀렸음을 증명하는 방식으로 동작한다. 각고의 노력이 반례를 들 수 없는 서술이 있다면 목표에 부합할 만큼은 "참"이라고 본다.

결론적으로는 수학은 증명 가능한 서술이 "참"임을 입증하는 원리라고 볼 수 있고, 과학은 증명가능한 서술이 거짓임을 입증하는 원리라고 볼 수 있다.

즉 저자는 프로그래밍에 대해서, 정확히는 어떻게 프로그래밍을 하는 것이 좋을지에 대해서 과학과 같다고 서술 하고 있다. 즉 어느 방법이 정답인지는 모르겠지만 위에 나온 세가지 방법이 "참"이 아니라고 반증이 나오기 전까지는 "참"에 부합한다는 것이다.

 

그렇기 때문에 goto문은 도태 되었고 프로그래밍에 대해서 다양한 제약사항을 걸어두는 것이다. 각 패러다임은 그 도구에 어떠한 것에 더 특화되어 있고 더 편하게 사용할 수 있게 도와주는 것 뿐이다.

저자가 Programing Paradigm에 서술한 내용은 아래 한줄로 요약된다.

소프트웨어, 즉 컴퓨터 프로그램은 sequence, selection, iteration, indirection로 구성된다. 그 이상도 이하도 아니다.

 

Design Principles

 

이 챕터에서는 실질적으로 위에서 서술한 "벽돌"을 어떻게 놓아야 무너지지 않고 어떻게 "벽"을 만들어야 금이 잘 가지 않으며, 벽이 무너지더라도 "건물"에 영향이 가지 않도록 하는 방법에 대해서 서술한다.

주로 SOLID 원칙에 대해서 서술하며 아래 서브챕터들은 각 원칙들에 대해 예시를 보여주며 서술한다.

Single Responsibility Principle


단일 책임 원칙이라고 번역될 수 있으며, 간단히 말하면

하나의 모듈은 하나의, 오직 하나의 액터에 대해서만 책임져야 한다.

 

여기선 SRP에 대한 위반 예제로써 "우발적 중복"이라는 아래와 같은 예제를 든다.

 
 
 
 

 

이는 위에서 서술한 SRP을 위반한다. 왜냐하면 수정했을 때, 여러 액터들에게 영향이 갈 수 있기 때문이다. 즉 CFO팀 요청으로 Employee를 수정했을 경우 COO는 수정사항 여부에 대해 알 수 없을 뿐더러, 만약 실제 업무에 사용되 었을 경우 수정에 따른 잘못된 결과값을 사용했을 수 있다.

 

이와 같이 의존하는 코드를 너무 가까이 배치했을 때 이와 같은 경우가 발생한다. 실제 나도 겪어 봤던 사항이고 이런 원칙이 존재하는지 몰랐다. 그렇기 때문에 이 책이 더 좋게 느껴졌다. 마치 원인과 결과를 알지만 이거를 어떻게 정의해야하는 지 모르던 상황에서 누가 "그건 이런거야" 라고 말해주는 듯한 느낌이 들었다.

 

그 이후 "병합"이라는 예제도 나오는데 내용은 얼추 예상하듯 같은 Employee class에 대해 두 개발자가 작업후 병합에 대한 처리에 대한 이야기이다. 그렇기 때문에 이전에 작업할 때는 최대한 모듈을 쪼개서 같은 개발자가 최소한 같은 파일을 수정할 수 없게 처리하는 방식으로 회피를 했었다. 그럼 최소한 같은 모듈에 있지만 같은 코드가 두번 수정될 일은 없었기 때문이다.

 

여기서 저자는 이에 대한 해결책으로 액터에 따라 class를 나누고 data를 관리하는 class를 최상위 class로 두는 방식으로 이문제를 해결 하였다. 즉 두 개발자가 서로다른 액터에 컨트롤러를 수정하는 것이기 때문에 겹칠일이 없다는 것이다.

 

SRP은 위 2개의 예제를 들고 마무리되며, 이후 원칙에 SRP 원칙은 기본으로 깔게된다. 특히 다음 OCP에서 자주 사용되는 걸 볼 수 있었다.

Open-Close Principle


스크린샷 2020-09-24 오후 2.32.52

 

OCP는 간단하게 Component 단에서의 개방과 폐쇄라고 정의 되어 있으며 아래의 문단과 같이

Software Artifact는 확장에 대해서는 Open 되어 있어야하며, 변경에 대해서는 Close되어 있어야 한다.

라는걸 OCP의 기본으로 하기 때문이다.

 

위에 그림처럼 Presenter에 변경에 대해서 Controller는 Close하고 대신 Presenter라는 확장에 대해서는 Open 한다. 이와 같이 하위 Component에 의해 상위 Component가 재빌드되면 안되며 재배포 또한 할 수 없다는 것이 OCP 원칙에 정의다.

 

이로써 얻을 수 있는 이득이 중요한데 이는 아래와 같다.

확장(Open)하기 쉬운 동시에 변경으로 인해 시스템이 너무 많은 영향을 받지 않도록한다. 또한 이로써 하위 Component에서 발생한 변경으로부터 고수준 Component를 보호(Close) 할 수 있다.

 

그렇기 때문에 이 OCP이 어떻게 보면 제일 중요하다고 생각 되었고 또한 저자도 이 OCP 원칙이 아키텍처를 떠받치는 원동력이라고 서술하고 있다. 그렇기 때문에 OCP이 위반되지 않는단 선에서 Software Engineer가 생각 할 거리는 기하급수적으로 적어진다. 단지 상위 Component가 원래 해줄 역할을 보장해준다는 것이 전재이지만 그것은 다른 문제이다. 즉,

상위 Component에 대해서 많은 생각 할 필요가 없진다는 점에 대해서 중요하다.

 

간단히 예를 들어 A방에 있는 창문에 대해서 작업을 하고 있는데 아랫층이나 윗층에 대해 생각하면서 작업을 하고, 만약 윗층에서 어떤 작업 때문에 A방에 대해서 벽에 금이가거나 작업하고 있던 창문 사이즈가 달라진다면 엄청난 문제가 아닌가?

 

Liskov Subsitution Prinsiple


스크린샷 2020-09-24 오후 2.48.43

OCP이 각 Component의 확장과 보호에 대한 원칙이라고 한다면 이 LSP 원칙은 확장에 대한 재사용성에 대한 원칙이라고 볼 수 있다.

상시 치환 가능 할 수 있게 설계를 해야하는 것이 LSP 원칙의 요지인데 간단히 말하면

 

기능이 추가되는 것에 대해서 if문을 추가하거나 각 기능별로 비슷한데 매번 다른 Component를 호출해야 할 경우 이것을 최소화 해야한다는 것. 즉, "예외사항"을 처리해야하는 로직을 최소화 해야한다.

 

라는 것이 LSP의 요지다.

 

예를 들어 위의 그림은 책에 서술된 ''정사각형/직사각형 문제''를 가져온 것인데 위와 같이 설계하는 것은 잘못된 설계 방식이며 그 이유는 User 입장에서 Rectangle은 Square로 치환될 수 없기 때문이다. 이를 만약 LSP에 맞게 수정할려면 Shape 라는 상위 Type에 BaseRactangle이라는 하위 타입을 만들고 Rectangle과 관련된Rectangle과 Square라는 하위타입의 구조를 가져야만 한다.

 

이렇게 설계되면 User의 입장에서는 상호 치환 가능한 Shape Type을 가지게 되며, 이로써 유연한 코드를 가지게 된다. 만약 이렇게 설계 된다고 하면, Shape->(BaseRactangle)BaseCircle -> (Rectangle, Square)Circle,Ellipse와 같이하위타입을 "확장"할 때도 용이하게 된다.

 

그렇기 때문에 어디까지 올라가서 BaseClass를 만들것인가에 대한 생각이 필요하고 이를 각 Task에 맞춰서 너무 상위개념에 대한 정의를 굳이 이번에 수행하지 않는게 개발 효율에 도움을 줄 수 있다. 이는 OOAD 설계 방법론에 맞춰서 명사를 도출해보는 것을 통해 어떤 범위까지 구현하는게 맞을지에 대한 고민을 수행할 수 있다. -Allen -

 

이 규칙에 대해 먼저 알고 코딩을 했다면 보다 유연하게 코딩을 했을 거란 생각이 들었다. 이 부분은 아마 이후 코딩을 할 때 많이 쓰려고 노력하지 않을까란 생각이 들었다.

Insterface Segregation Principle


스크린샷 2020-09-24 오후 3.18.04스크린샷 2020-10-15 오후 3.03.32

위에서는 각 Component 별로의 확장, 분리, 수정에 대해서 이야기를 했다면 ISP같은 경우에는 원래 있던 짐을 덜어내는 걸(분리) 뜻한다.

 

예를 들어 위 이미지에서 User1에서는 op1을 사용하고 User2는 op2를 사용한다고 가정한다면 User1은 사용하지도 않는 op2가 변경되거나 그에 따른 메소드가 정의 될 때마다 재빌드 되며 재배포 된다. ISP는 이러한 부분을 분리하고자 하는 원칙이다.

 

즉 내가 사용하지 않는 "코드" 에 대해서는 원초적으로 분리를 해야한다는 것이다. 이것은 코드나 데이터 타입에 국한되지 않고 Component나 Controller, Presenter 그리고 아키텍처 개념에도 적용 될 수 있다.

 

자신이 사용하지 않는 것에 대해서는 Interface조차 가질 수 없어야 한다는 것이다. 이로써 얻는 이득은 불필요한 재빌드, 재배포 방지 및 "의도하지 않은" 동작에 대한 미연방지다.

 

사실 이 부분은 정확한 예가 맞는지 모르겠지만, 이전에 보기 좋게 한곳에 모아 놓는 것이 좋다고 생각하던 시기가 있었다. 그렇지만 반대로 그렇게 설계를 해버리니, 불필요하게 누군가가 수정한 Commit에 대해서 결과에 대한 아무 변화가 없지만 재빌드되는 과정이 반복되었다.

 

하지만 이를 위와 같이 Interface에 따라 분리하고 나서 재빌드하는 경우가 없어졌다. 즉 독립성, 의존성에 대한 숙지가 없었을 경우에 어떻게 되는지를 체감했던 케이스였다.

 

설계의 관점

아래는 위에 내용 이후 엘렌에게 받은 피드백을 바탕으로 추가한 것이다.

기능들의 cohesion을 고려했을때 해당 로직들은 한개의 module로 정의되는 게 맞다고 할때 어떤 모듈의 기능을 사용하는데 있어서 복수의 용도군을 정의할 수 있을때 각각에 맞는 interface/subClass를 생성하여 제한된 기능을 수행할 수 있도록 한다.

  • 해당 module에 대해서 접근하는 양방향 (사용자와 대상 module)의 역할을 보다 구체적이고 명확하게 정의하고 제한하여 이해도를 높이고 잘못된 영향을 주고 받는 것을 제한하는 효과를 가져옴.
  • 각 용도 별로 compact한 interface를 정의해주는 것은 상당한 overhead를 만든다.
  • 용도가 변경/추가될때마다 매번 이러한 interface를 개별적으로 재생성, 재정의하는 것은 매우 지치는 일이다.
  • compromise하는것이 그래서 중요. 특수한 용도를 가지거나 외부에 노출되는 경우를 제외하고 보통의 경우에 “일반적/범용적”인 범주의 단위로 정의하는 편이 효율이 좋음.(어느정도 위반을 허용한다.)

위 내용과 더불어 실무와 이 책에 다른 점이라고 한다면 실무에선 이 나누는 행위에 대한 Overhead에 대한 자원소비가 있다는 것. 즉 Overhead와 적절한 타협을 하는 것이 중요하다.

이 책에서는 대체적으로 Overhead와 같은 그러한 내용들에 대해서는 매우작게 서술하고 있다. 물론 이 저자가 말하는 Arctechture가 효율적인 역할을 발휘하는 것은 각 Component를 팀 단위로 개발할 때를 거의 전제로 말하고 있기 때문이기도 하다. (큰 규모의 개발)

Dependency Inversion Principle


2016-03-02_at_3.51.14_AM

Clearly, treating this idea as a rule is unrealistic

분명히, 이 생각을 규칙으로 다루는 것은 비현실적이다.

역으로 매우 많은 중복 코드를 양산할 수 있는 원칙이기 때문에 주의가 필요하다. - allen -

 

DIP는 의존 역전 원칙이란 의존 관계를 맺을 때 변화하기 쉬운 것 보다 변화하기 어려운 것에 의존하라는 원칙을 의미한다. DIP를 만족하는 설계는 변화에 유연한 시스템이 된다.

 

그렇다면 왜 유연한 시스템이 되며, 왜 유연한 시스템이 되기 위해서는 DIP 즉 "의존성에 대한 역전"이 필요한 것일까?

이 부분을 이해하기 위해서는 전통적인 애플리케이션이 어떤 식으로 동작해왔는지 이해한다면 더욱 쉽게 받아들일 수 있다.

 

스크린샷 2020-10-16 오후 12.24.41

전통적인 아키텍처에서는 Low-Level Component(e.g. utility layer)는 점점 더 복잡한 시스템 구축을 가능하게 하는 High-Level Component(e.g. policy layer)에 의해 소비되도록 설계된다. 이러한 구성에서 High-Level ComponentLow-Level Component"직접 의존"하여Task 를 수행하게 된다.

Low-Level Component에 대한 이러한 의존성은 High-Level Component의 재사용 기회를 제한한다.

 

이러한 문제를 해결 하기 위해서는 High-Level Component 를 재사용할 수 있게 구성하면 된다. 그러한 구성을 하기 위해서는 무엇이 필요한가?

그렇게 등장하게 되는 개념이 "추상화"이며 이를 통해 의존성을 역전시켜 High-Level Component 에 대한 재사용성을 증진시킬 수 있으며 이는 즉 확장성에도 영향을 끼친다는걸 바로 알 수 있을 것이다.

스크린샷 2020-10-16 오후 12.33.09

추상화된 High-Level Component의 interface rules만 준수한다면 Low-Level Component 에 무엇이 오든 구성에 대한 변화는 상관없게 된다. 위와 같은 예제가 이해하기 힘들다면 아래와 같은 그림을 통해 어떠한 점이 바뀌었는지 알 수 있다.

스크린샷 2020-10-16 오후 12.37.55

이와 같은 경우가 전통적인 구성방식이라고 가정한다면 자동차는 스노우 타이어의 변화에 매우 취약할 것이며 또한 어떠한 타이어를 추가하는 것에대해 높은 저항이 있을 것이다. 이와 같은 구성을 추상화를 통해 아래와 같이 변경하게 된다.

스크린샷 2020-10-16 오후 12.39.26

위 그림을 보면 알 수 있듯이 자동차는 변하기 쉬운 스노우타이어에 의존하던 관계를 중간에 추상화된 타이어 인터페이스를 통해 의존 관계를 역전시키고 있다.

 

이처럼 자신보다 변하기 쉬운 것에 의존하는 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것이 의존 역전 원칙이며 이 저자는 크게 4가지 규칙으로 안정된 추상화(DIP)를 가질 수 있다고 말한다.

  1. 변동성이 큰 구체 클래스를 참조하지 말라.
  2. 변동성이 큰 구체 클래스로부터 파생하지 말라.
  3. 구체 함수를 오버라이드 하지 말라.
  4. 구체적이며 변동성이 크다면 절대로 그 이름을 언급하지 말라.

 

이 4가지의 공통점을 한 문장으로 정의하면 다음과 같다.

"자신보다 변하기 쉬운 것에 의존하지 마라."

 

구체 클래스를 의존하게 되는 순간 변화에 따른 이펙트가 크고 그렇기 때문에 최대한 추상화 해서 사용해야하며, 위 4가지의 규칙에 따라 사용되어야 하는 이유이다. 이때 자주 사용되는 것이 Abstract Factory Pattern이며 이 책에서는 이 Pattern을 사용한 예시를 들어 설명했다.

 

Abstract Fatory Pattern을 사용함으로 써 제어흐름은 소스 코드 의존성과는 정반대 방향으로 흐르며, 의존성은 그와 반대 반향으로 역전된다. 이러한 이유로 이 원칙을 Dependency Inversion이라고 부르는 이유다.

 

Dependency Injection을 하기 위한 방법 또한 위를 위해 여러가지가 존재한다. 이로써 얻는 이득은 각 상위 Component와 하위 Component에 대해서 의존성을 역전 함으로써 보다 유연하게 프로그램을 작성하게 되며 그렇게 각 Component는 Layer에 상관없이 "독립성"을 가지게 된다.

 

이 부분은 처음 정독했을 때는 이런 것이 존재하는 구나 하고 넘어갔고 복기하면서는 아 이런거였어? 했던 서브챕터였다. 정확히는 "Abstract Factory" 개념을 알게되는 계기였고 생각보다 코딩할 때 많은 도움이 될거 같은 부분이 였다.

Component Principle

 

Runtime에 Plugin 형태로 결합할 수 있는 파일을이 이 책에 저자가 말하는 Component이다. 또한 아래와 같이

 

Component는 배포할 수 있는 가장 작은 단위이며 각 Components에 따라 재사용 및 배포가 가능해야 한다.

 

그리고 이 Component를 설계 하고 배포/관리 함에 있어서 REP, CCP, CRP 3가지 원칙이 존재한다.

Reuse/Release Equivalence Principle


재사용/릴리스 등가원칙이라고도 불린다.

하나의 Component로 묶인 클래스와 모듈은 반드시 함께 릴리스할 수 있어야 한다.

그리고 새로운 릴리스가 나온다는 소식을 접하면, 개발자는 이에 대해 새 변경사항을 확인할 수 있어야 하고 기존 버전을 쓸지 판단할 수 있게 하여야한다.

 

이 원칙을 소프트웨어 설계와 아키텍처 관점에서 보면 단일 Component는 응집성(Cohesion)이 높아야 한다. 각 Component를 구성하는 클래스와 모듈은 그 Component에 테마와 목적에 맞게 응집해 있어야 하며 이를 사용하는 개발자가 Component에 목적에 대해 이해하기 쉽게 설계 되어야 한다고 저자는 서술하고 있다.

 

나는 이부분을 읽으면서 Component 또는 그 아래 Module 개념에서도 적용 될 수 있겠다.라는 관점에서 보았다. 즉 팀으로 작업할 때 하나의 프로젝트에서 각 Components/Module을 개개인이 담당했을 경우 내가 담당하지 않은 Module에 대해서 변화가 있을 경우 그 변화에 대해서 바로 숙지할 수 있어야 하고 그 모듈을 작성한 개발자는 그 Module에 목적성이 중복되거나 벗어나는 릴리즈를 하면 안된다.

 

이 부분에 겹쳐서 볼 수 있지 않을까란 생각을 했다. 이부분 때문에 좋지 않은 경험을 한적도 있고 해서 그런것도 있었던거 같다. 아래 두가지 원칙도 넓은 범위로 충분히 적용될 수 있는 개념이라고 생각한다.

 

아마 곰곰히 생각해보면 Rest API도 이 Principle이 포함된다고 생각된다. 기존에 Backend 쪽에서 설계된 Restful API를 APP이나 WEB 에서 사용한다고 했을 때도 한번의 배포는 한가지의 테마 또는 목적에 맞게 응집되 어 있어야 사용하는 Layer 쪽에서도 그 수정에 대해서 빠르게 적용해갈 수 있을 것이다.

 

만약 Backend가 소통 없거나 목적에서 벗어난 수정을 실수로 포함해 배포를 하게되면 APP, WEB은 곤욕을 치르거나, 의도치 못한 버그를 발생시킬 수 있을 것이다. 그렇다면 원인을 파악하는데 많은 시간이 소요될 것이다.

Common Colsure Principle


동일한 이유로 동일한 시점에서 변경되는 클래스를 같은 Component로 묶어라

라는 원칙인데 이는 서로 다른 시점, 그리고 다른 목적성을 가지고 변경되는 클래스는 다른 Component로 분리하라는 말이다.

 

이는 이전에 서술되었던 SRP와 비슷한 말인데, SRP가 Class의 변경 이유가 단일 이유여야 한다는 것과 같은 의미로, CCP또한 Component도 단일 이유로 변경 되어야 한다는 것이다.

 

그래야 같은 이유로 변경되는 Class들을 서로 묶어야 릴리즈, 재검증, 배포 할 때 최소한의 작업량으로 작업이 가능해지며, 원인을 파악할 때 그 수정에 대한 목적에 따라 원인이 되는 Component와 Class를 빠르게 파악할 수 있기 때문이다. 만약 이 Component의 목적성과 테마가 여러개면 개발자는 수정에 대한 이유가 2개이고 하나의 문제가 발생했을 때 그 갯수만 큼 원이을 파악하는 시간이 길어 질 것이다.

 

그렇기 때문에 내가 느낀 CCP의 요지는 다음과 같다.

 

동일한 시점에 동일한 이유로 변경되는 것들을 한데 묶어라. 서로 다른 시점에 다른 이유로 변경되는 것들은 서로 분리하라.

Common Reuse Principle


필요하지 않는 것에 의존하게 강요하지 말라.

CRP에서는 공통적으로 사용되는 애들끼리 묶어야한다 것을 중점적으로 하는 규칙이다. CCP와 밀접하다면 밀접하다고 말 할 수 있는데 CCP 수정에 대해서 같은 목적성을 같게 만들어서 혼동성을 줄이기 위함이라고 한다면 CRP는 불필요한 재빌드, 재배포를 맊이 위해 만들어진 원칙이라고 할 수 있다.

 

즉 재사용되지 않는 Module이나 Class를 포함하게 되면 이를 사용하게되는 사람(또는 Code)는 불필요한 의존성이 생기고 이에 따라 의도치않은 문제가 발생할 수 있기 때문에 이를 사전에 차단하기 위한 원칙이라고 볼 수 있다.

이는 ISP와 밀접한 관계가 있는데 ISP는 사용하지 않는 Method가 있는 클래스에 의존하지 말라고 조언하고 CRP는 사용하지 않는 클래스를 가진 Component에 의존하지 말라고 조언한다. 즉,

 

필요하지 않은 것에 의존하지도 말고 포함하지도 말라.

 

라고 한줄로 정의할 수 있다.

Component Cohesion


스크린샷 2020-09-24 오후 4.38.45

이 세가지 균형은 어느 한쪽으로 치우쳐 질 수 있다는 점을 저자는 강조하고 있다. 즉 이것을 모두 지키면 좋지만 그렇게 되면 개발 가능성(Developablitiy)이 떨어질 수 밖에 없다는 것이다.

예를들어 개발 초기에는 개발 구현 가능성이 재사용성보다 더 중요하기 때문이다.

그렇기 때문에 Refactoring이라는 작업이 따로 있는 것이며, 개발자는 코드를 작성함에 있어 앞으로의 확장성을 염두해야 하는 이유이기 도하다.

Architecture

 

Architecture라는 것은 추상적인 것이며, 세부사항은 마지막의 그리고 또 마지막에 결정된다는 것이다. 세부사항이 정해지기 전까지는 추상적으로 작동할 수 있어야한다는 것이며 그러기 위해 저자는

 

가능한 많은 선택지를, 가능한 한 오래 남겨두는 전략을 따라야 한다.

 

라고 서술했다. 물론 그와 동시에 저자는 아키텍트는 코드에서 탈피해여 고수준의 문제에 집중해야한다는 거짓말에 절대 속아 넘어가면 안된다라고 말하기도 한다.

 

읽던 도중 제일 눈에 들어왔던 문장이 있는데

시스템 아키텍처는 시스템의 동작 여부와는 거의 관련이 없다. 형편없는 아키텍처를 갖춘 시스템도 수없이 많지만, 그런대로 잘 동작한다.

...

운영보다는 배포, 유지보수, 계속되는 개발 과정에서 어려움을 겪는다.

 

즉 Architecture는 행위에 대한 설계도가 아니라 구조에 대한 설계도 라는 점이다. 즉 아키텍처는 시스템에 동작 여부에 대해서는 dramatic한 변화를 만들지 못한다 다른 아키텍터라도 동작이 같을 수 있기 때문이다. 즉 우리가 주로 Architecture에 대해서 dramatic한 변화를 체감하고 또 목표로 해야하는 것은 Operation 보다는 Deploy, Maintenance, Develop과 같은 부분이다. 저자는 그러한 부분 때문에 운영쪽에서 이 Architecture에 대한 비용에 대해서 간과하기 쉽다.

 

왜냐하면 이 비용은 실질적으로 눈에 보인 금액이 아닌 추상적인 미래에 해 지출하는 금액이기 때문이다. 예를들어 지금 바로 동시접속자 10000명이 사용할 수 있는 채팅 앱을 만들라고 하면 충분하지 않은 Architecture 설계 없이도 더 빠르게 구현 가능할 것이다. 하지만 이를 Web-App으로 추가 개발한다고 했을 때 또는 이모티콘 기능을 넣는다고 했을 때 개발팀은 Architecture를 제대로 설계 하지 않은 대한 비용을 치뤄야 할 것이다.

 

저자는 Architecture의 구성을 크게 Develop, Deploy, Operation, Maintenance, Keep Open Option으로 나누어 설명했다. 앞에 3가지는 기본적인 구성으로 저자는 4번째에 따라 선택될 수 있는 "세부사항"으로 말하고 있다. 즉 Keep Open Option 에 요지는 아래와 같다.

 

세부사항에 대한 결정을 더 오래 참을 수 있다면, 더 많은 정보를 얻을 수 있고, 이를 기초로 제대로 된 결정을 내릴 수 잇다.

...

좋은 아키텍트는 "결정되지 않는 사항의 수를 최대화" 해야 한다.

 

그리고 이를 설명하기 위해 장치 독립성, 광고 우편과 같은 예시를 드는데 결론은 좋은 아키텍트는 "Independence"을 가지게 된다는 것이다.

 

즉, 아키텍트는 세부사항에 의존하지 않는 구조가 좋은 아키텍트이다. 세부사항에 대한 의존성이 높으면 높을 수록, 그리고 열려있는 Option이 없으면 없을 수록 아키텍트는 구조적으로 묶여있고 의존적인 존재일 수 밖에 없다.

 

Independence


저자는 좋은 Architecture는 아래와 같은 사항들을 지원해야한다고 한다.

  • Use Case
  • Opreation
  • Development
  • Deploy

그 중 Use Case는 Architecture의 Identity 라고 저자는 말한다. 즉, 이 Architecture가 존재하는 이유이기 때문이다. Operation, 즉 운영 지원과 같은 부분은 추상적인 부분이라고 저자는 설명했다. 즉 Use Case가 어떠한 목적성을 띄는가에 따라 Operation은 여러가지 선택을 할 수 있기 때문에 필요 조건이지 필수 조건은 아니라는 것이다. Monolihic 구조를 가져갈 수 있으며, Micro Service 구조를 가져갈 수도 있다. 상황에 따라 어느 구조를 가져갈지는 바뀔것이고 설계에 따라 구조를 만들어도 Use Case에 대한 목적성이 같더라도 상황( Traffic, 분산 처리와 같은 것들)에 따라 변경될 수 도 있다.

 

Development와 같은 경우에는 Conway 법칙을 예로 들며, 여기서 강조한 부분은

Architecture는 각 Team/Man이 독립적으로 행동하기 편하게하여 서로를 방해하지 않도록 해야 한다.

인데 좀 와 닿았던거 같다.

 

만약 내가 하는 작업은 독립적이지 못하고 이것을 수정함에 있어 영향이 갈 것을 판단하고, 그에 따라 다시 수정한다면 이 사람, 또는 팀의 온전하 능력을 이끌어내지 못할 것이다.

 

최대한의 능력을 이끌어 내려면 단일 책임(Single Responsibility)을 부과할 수 있는 구조를 가져가야 한다.

 

그리고 마지막 Deploy는 "immediate deployment" 에 가 까울 수록 좋다고 저자는 말한다. 이는 각 Component가 독립성을 가질 수록 더욱 빨라지며 불필요한 재배포를 할 필요가 없게 만드는데 있어서 Independence는 중요한 역할을 한다. 이를 충족시키지 못할 경우 매번 확인하는 작업을 거쳐야 할 것이다.

 

FitNesse


이 전에 여러가지 예제가 나오지만 안좋은 예제 뿐이기도해서 생략했다. 그중 좋은 케이스를 설명한 것중에 제일 기억에 남았던 부분을 설명하려고 한다. 저자는 자신이 2001년에 설계한 FitNesse라는 Application에 대한 이야기를 서술했다.

여기서 저자는 두가지의 큰 결정을 내린다.

  1. Web Server를 직접 작성한다.
  2. Database는 지금 결정하지 않고 마지막까지 남겨두자.

 

이러한 결정들은 옛날에 이전 직장에서 첫 사수와 같이 첫 3D Printer 프로젝트를 맡을 때도 비슷했다. 그 프로젝트는 3D Printer를 만드는 작업인데 이미지를 Display 하는 부분을 FrameBuffer를 이용해서 할지 OpenGL을 이용해서 할지 Linux Graphic Driver를 이용해서 작업할지 미정이었고 사수는 프로그램을 설계 함에 있어서 이 부분에 대해서 정하지 않고 넘어가는 것으로 정했다.

 

사실 그때 당시는 이해하지 못했고 그냥 아직 미정이라 그런거구나란 생각을 했다. 개발과 테스트를 진행 하면서 bitmap을 이용해서 이미지에 대한 윤곽만 확인할 뿐 실질적으로 출력은 프로젝트 맨 마지막 단에서 구성했다.

 

Display Module을 만들고 Driver Layer와 그 사이에 Display Interface 를 두었다. 테스트를 할 때는 BitmapDisplay, BitmapClean과 같은 임시 함수들로 Interface를 연결해서 사용했다. 사실상 마지막에 갔을때 최종적으로 FrameBuffer를 사용하게 되었고 이전 사수와 나는 FrameBuffer Driver를 구현하기 시작했다.

 

Driver를 만들고 BitmapDriver와 같이 Interface에 연결만 했을 뿐 그 이상의 작업은 필요하지 않았다. 문제가 있어도 FrameBuffer Driver에 문제였고 원래있던 상위 Layer에는 손을 댈 필요가 없었다.

 

생각해보면 이 3D Printer 프로그램은 Motor, Display가 존재하지 않더라도 파일을 읽어와서 Bitmap에 뿌리고 Motor가 움직이는 것처럼 Log를 찍는 것이 가능했다. 어떤 Motor Board가 와도 Motor Interface에 Motor별로 코드를 짜 넣으면 동작했으며 Display 또한 위에 서술 한것과 동일했다. 아마 이러한 점이 "Detail" 들을 미루고 최대한의 Option을 열어두는것.. 그리고 열어둘 수 있게 아키텍트가 설계 되는 것이 이후 변경에 대해 매우 유동적일 수 있다는 걸 깨달았다.

 

나도 모르는 사이에 사수의 Architecture에서 프로그램을 작성하고 있었다. 또한 Task를 수행할 때도 나는 Module안에 있는 Component 단위의 작업을 수행했다. 그 외에 Component 는 건드릴 필요도 없었고 건드려서도 안됬다. 이 챕터에서 이전 사수가 그려왔던게 뭔지 다시 알게 됬던 챕터 였던거 같고 내가 무엇이 부족한지도 다시금 알게되는 계기가 되었다.

 

이제 이후 Policy and Level, Business Rules, Screaming Architecture 챕터가 나오는데 각각 각 Component 의 Independence를 위한 정책과 수준 그리고 규칙, 유즈케이스의 중요성을 강조하는 챕터들이다.

 

이 3가지를 이야기하면서 내가 느낀 저자의 의도는 "어떠한 신규 프로그래머가 와서 시스템 아키텍쳐를 보았을 때 이것은 어떤 목적을 가진 아키텍처이며 내가 이런 모듈을 받앗을 때 어디까지 수정권한이 있는지 알 수 있어야 한다." 이다.

 

마치 편의점 도안을 보여주면 건설에 대한 전문지식이 없더라도 "아 이건 편의점 도안인가보내요." 라고 말 할 수 있는 수준의 아키텍처 말이다.

 

위 세가지 챕터는 아무래도 내용 자체들이 저자가 예를 많이드는 챕터라 직접 읽어보는 것을 추천한다.

 

Clean Architecture

이 챕터에서는 Clean Architecture 란 그래서 무엇인가? 에 대한 답변을 해준다. 여기에서의 주된 주제는 아무래도 의존성과 독립성이다. 여기서도 경계를 나누는데 나는 이 개념을 Layer라고 생각하면서 이해를 했다. 여기서 각 Layer를 담당하는 Circle이 나오며 이 Circle은 안으로 의존하는 구조를 유지하고 외부에 있는 Circle일 수록 User Interface와 가까워지는 설계였다.( 즉 변동성이 높은)

 

이 Circle들은 각각의 고유한 Policy와 Level을 가지고 있고 이전에 설명한 Boundary 와같은 것들을 종합적으로 모아서 설명해준다. 지금 까지의 공통적인 이야기는 말그대로 "분리", "분리", "분리"다. 그리고 그것이 무분별한 분리가 아닌 목적, 테마에 따라 어떻게 분리하는가에 대한 그리고 어떻게 분리하는게 제일 효율적인지에 대한, 그리고 그 분리한것들을 어떻게 응집력있게 모아둘 것인가에 대한 이야기.

 

그런 분리를 얼마나 잘 할건지에 대한 이야기라고 이해했다. 실질적으로 동작(서비스로 운영되고 있는)하고 있는 프로그램을 분리하는 것은 분리하는 만큼 많은 비용이 든다. 그럼 프로그램이 실질적으로 운영하기 전에 최대한 '잘' 분리 될 수 있도록 설계하는것이 아키텍쳐의 목적 중 하나이고 권한을 분리하고 불필요한 작동을 하지 않기 위해 또 분리를 한다.

 

그러면 분리를 한 걸 다시 붙이려면 원래 있던 코드는 앞으로 붙을 또는 변경될 Module에 대해서 추상적으로 알고 있어야 한다. 그렇기 때문에 추상화를 강조한다. 간단하게

 

얼마나 효율적으로 분리하고 조립할 수 있게 만드는지에 대한 이야기다.

Clean Embedded Architecture

 

재밋게도 Clean Architecture다음에 Clean Embedded Architecture에 대한 이야기도 나오는데, 아는 개념도 나오고 재미있게 읽었다. 지금 보면 HAL또한 Application 과 Hardware 간에 추상화를 지원해주는 역할을 해주는 구조라는 것도 깨달았다.

 

이 개념은 Windows OS나 Linux에서도 나오는데 생각해 보면 Linux또한 어떠한 하드웨어 위에서 돌아갈지 정해져 있지 않고 유동성있게 변경되어야 한다. 프로세서가 어떤 것일지 출력은 어떤 형식으로 할지에 대한 정의도 필요하다. 생각해보면 주변에는 예제로 삼을 수 있는 많은 Architecture들이 존재했고 조금만 생각해보면 이들이 얼마나 많은 분리들이 들어가 있고 많은 추상화를 사용했는지 알 수 있었다.

 

그리고 여기서 재미있던건 저자는 펌웨어의 정의를 좀 다르게 했다는 것이다. 물론 지금 생각해보면 저자가 맞다고 생각하지만..

저자는 펌웨어에 정의를 하드웨어에서 작동하는 코드 뿐만이 아니라 앱이나 웹또한 펌웨어가 될 수 있다고 말한다. 즉 코드 전반에 플랫폼에 대한 의존성을 심어둔다면 그것은 펌웨어와 다를 게 없다는 말이다. 아래는 이와 관련된 문단이다.

펌웨어나 펌웨어 엔지니어에 대해 딱히 악감정은 없다. 하지만 우리가 정말로 원하는건 펌웨어는 더 적게 만들고, 소프트웨어는 더 많이 만드는 것이다.

..

임베디드 엔지니어가 아닌 엔지니어들 또한 펌웨어를 작성한다! 임베디드 엔지니어가 아닌 당신도 코드에 SQL을 심어 놓거나 개발하는 코드 전바에 플랫폼 의존성을 퍼뜨려 놓는다면, 본질적으로 펌웨어를 작성하는 셈이다.

 

이 문단이 정말 좋았다.

 

저자는 이 분야가 안드로이드와 같은 APP 또한 포함되며 의존성이 있다면 추상화, 인터페이스를 통해 경계를 확실히 만들어 두어 의존성을 최대한 약하게라도 만들어야 한다고 말한다.

 

이 부분은 Web, App, Server 모두 에게 필요한 내용일거란 생각이 들었다.

팀내에서도 서로간 플랫폼에 따라 종속되면 안된다라고 가정하고 설계하면 더 빠른 배포와 분리 그리고 문제에 대한 원인파악이 더 빨라질 수 잇으며 궁극적으로는 특정 플랫폼에 대한 대대적인 개편에 대해서 자신의 영역을 방파제와 같이 방어 할 수 있다는 점이다.

 

서버에 대대적인 Rest API 개편이 있어서 2.0 API가 나온다고 하면 Web에서 설계할 때 Interface를 추상화하여 1.X 을 유지하면서 2.0 개발 및 테스트가 완료되면 Web단에서 2.0 Interface를 작성해서 붙이는 식으로 만들어 최소한의 의존성을 유지한다. 이런식이면 방어적으로 대처 할 수 있고 문제가 생길시 이전 1.0으로 사용하게 하는 식으로 할 수 있다.란 생각을 해보았다.

 

추상화.. 생각하면 할 수록 많은 걸 해볼 수 있을거란 느낌이 든다.

 

Details

저자가 제일 싫어하는 것처럼 보이는 Detail이다. 여기선 무엇이 Detail이고 무엇이 Detail이 아닌지에 대한 정의와 그에대한 설명을 해준다. 앞서 나온 FitNess 챕터에서도 책에선 안좋은 예제중에 하나가 무엇이 세부사항인지 모르고 섯부르게 Detail을 결정해서 개발할때 개발자 스스로가 자기한테 제약을 거는 경우를 예시로 들었었다.

 

여기에서 나오는 세부사항들은 크게 Database, Web, Framework 들이다.

 

3가지에 대해서 저자가 말하고자하는 것은 아키텍처의 유즈 케이스는 이 3가지에 대해서 알필요도 없고 알아서도 안된다고 서술한다. 즉, 서버는 RDBS을 쓸수도일고 아닐 수도 있고, 그냥 txt로 저장해서 사용해서 읽고 쓸 수도 있다. Web또한 Web일수도 있고 App일수도 있고 Play Station, Window App 일 수도 있다는 것이다.

그리고 재미있게 본점은 저자는 Framework를 Application과의 결혼이라고 서술했다. 설명을 들어보면 그리고 지금까지 해왔던 작업을 생각해보면 정말 맞는 표현이라고 생각한다.

한번 도입하면 의존성을 때기 힘들고 그렇기 때문에 거리를 두어 선택적으로 사용될 수 있는 형태를 유지해야한다. 또한 절대로 아키텍트의 영역을 침범할 수 없게 만들어야 한다. 하지만 세부사항이 아닌 경우 또한 존재한다.

저자가 든 예를 말해보자면

C++같은경우 STL과 결혼해야할 가능성이 높다. 이 관계를 피하기 힘들다. 자바를 사용한다면 표준 라이브러리와 반드시 결혼해야 한다.

..

이러한 관계는 정상이다. 하지만 선택적이여야한다. 애플리케이션이 프레임워크와 결혼하고자 한다면 애플리케이션의 남은 생애 동안 그 프레임워크와 상항 함께 해야 한다는 사실을 반드시 명심해야 한다.

 

이 챕터는 개발자가 아키텍처를 설계함에 있어 최대한 Option을 열어두기 위해 알고 있어야하는 내용을 서술하고 있다. 여기서도 저자는 아낌없이 강조를 했다.

최대한 마지막까지 Detail은 미뤄야한다.

마무리

 

개인적으로는 첫 Lab Day 였기도 해서 어떻게 작성해야 될지 감도 잘 오지 않아서 어떻게 써야 할지 막막했는데 일단 내가 살아오면서 해봤던 개발과 직접 비교하면서 회고록+설명 처럼 적게 되었다.

 

이 책을 다 읽고나면서 느낀점은 어린왕자 책과 같다고 생각한다. 처음 개발을 할 때 읽을 때, 쥬니어로서 읽을 때 그리고 시니어로서 읽을 때 이 책은 느낀점이 다 다를 거란 생각이 든다. 직접 설계해보고 실패해보고 그 경험이 축적될 때마다 아마 이책 내용에 대해 더 깊은 이해를 가지고 읽게 될거같다.

 

또한 코딩을 효과적으로 최적화해서 잘짜는 것 또한 중요하지만 그 코드의 Life-Cycle이 3개월이 안된다면 무슨 소용이 있을까? 제일 중요한건 최대한 효과적으로 내가 짠 코드가 오래 살 수 있게 만드는 것이 중요하다란 생각이 이 책을 다 읽고 나서 들었다.

 

 

Conclusion


얼마나 효과적으로 그리고 효율적으로 나눌지, 그리고 어느정도 선에서 나누는 것을 멈출지가 이 책이 전달하고자하는 내용인거같다.

 

'Study' 카테고리의 다른 글

RUP, The Rational Unified Process(옮기는 중)  (0) 2020.10.20
Comments