Robert C. Martin의 Clean Architecture 1부 1, 2장을 읽고 메모한 글입니다. 요약글은 아닙니다.
1장. 설계와 아키텍처란?
일반적으로 설계는 저수준, 아키텍처는 고수준의 구조나 결정사항을 가리킬 때 쓰이는 용어이다. 그러나 설계와 아키텍처 사이에는 근본적인 차이가 없다. 두 가지를 뚜렷하게 구분할 수는 없다. 고수준에서 저수준으로 향하는 의사결정이 연속적으로 이루어진다고 보는 것이 맞다.
소프트웨어 아키텍처의 목표는 필요한 시스템을 만들고 유지보수하는 데 투입되는 인력을 최소화하는 데 있다.
즉, 비용은 최소화, 생산성은 최대화. 이 사항을 만족할 수 있다면 좋은 설계라고 볼 수 있다. 이런 설계(아키텍처)를 어떻게 할 수 있는지에 대해 앞으로 다룰 것이다.
2장. 두 가지 가치에 대한 이야기
소프트웨어 개발자의 두 가지 책임: 행위(behavior)와 구조(structure)
- 행위(behavior): 요구사항을 버그 없이 구현. (=프로그램을 동작하게 만들기)
- 구조(structure): 시스템의 아키텍처를 유연하게 만들기. (=프로그램을 변경하기 쉬운 구조로 짜기)
둘 중 더 높은 가치는?
업무 관리자에게 묻는다면 프로그램이 동작하게 만드는 것(행위)이 당연히 우선이라고 말할 것이며, 대다수의 개발자가 이에 동조하는 태도를 취하게 될 것이다. 그러나 밥 아저씨는 극단적인 예시를 들어보이거나, 아이젠하워 매트릭스 기법을 적용하는 등 여러가지 근거를 들어가며 '구조'를 우선시해야 한다고 주장한다.
- 완벽하게 동작하지만 수정이 불가능한 프로그램을 내게 준다면, 이 프로그램은 요구사항이 변경될 때 동작하지 않게 되고, 결국 프로그램이 돌아가도록 만들 수 없다. 따라서 이러한 프로그램은 거의 쓸모가 없다.
- 동작은 하지 않지만 변경이 쉬운 프로그램을 내게 준다면, 나는 프로그램이 돌아가도록 만들 수 있고, 변경사항이 발생하더라도 여전히 동작하도록 유지보수할 수 있다. 따라서 이러한 프로그램은 앞으로도 계속 유용한 채로 남는다.
기능을 급하게 개발하는 것보다 유연한 구조를 설계하는 것이 중요하다고 관리자를 설득하는 것은 개발자의 역할이며 책임이다.
이번 장에서는 읽으며 많은 생각이 들었기 때문에 간단히 첨부해본다.
예전 신입 시절에 내 사부사수님 포지션의 책임님께 이런 질문을 했던 적이 있다.
"제가 지금 맡은 부분이 제게는 난이도가 좀 높은데요. 코드를 더럽게 하더라도 일단 돌아가게끔 할까요, 아니면 잘 안 돌아가도 일단 깔끔하게 짜볼까요?"
지금 돌이켜보면 저 무책임하고 이상한 질문은 뭔가 싶은데, 그때 그분께서는 "깔끔하게 짜는 게 더 좋아요. 그래야 (제가) 고치기가 더 쉽거든요." 라고 하셨고 신입이었던 나는 곧바로 설득되었다.
밥 아저씨가 1-2장에서 다루는 내용이 딱 이 질답을 대변하고 있는 것 같다. 클린 아키텍처를 읽지 않았던 시절의 내가 저런 질문을 했다는 게 약간 소름끼치기도 하지만, 어떻게 보면 그만큼 많은 솦 개발자들의 딜레마가 아닐까 하는 생각도 든다.
신입 때 클린 아키텍처를 읽었다면 '이게 맞다!!' 하고 밥 아저씨에게 동조했을 테지만, 더 이상 신입이라고 부를 수 없는 연차를 먹은 지금의 내 생각은 조금 다르다. 내 코드를 봐주고 백업해줄 사람이 나 외에는 없고, 그런 내 코드가 회사가 열심히 밀고 있는 프로젝트에 들어가는 경험을 1년 남짓 하면서, 돌아가지 않고 구조만 깔끔한 코드는 외부의 눈에는 예쁜 쓰레기에 불과하다는 것을 (아니, 예쁜지도 모를 것이다) 체감했기 때문이다. 비개발쪽 팀장님(관리자)과 QA 담당자분께 '자신의 입장에서는 잘 돌아가는 프로그램이 곧 그 개발자의 퍼포먼스다'라는 말을 직접 듣기도 했다. 회사 입장에서도 요구한 것(돌아가는 프로그램)을 제공하지 않는 사원에게, 그 사원이 요구하는 것(월급)을 제공할 이유는 없다고 생각한다. 동작하는 프로그램은 필수다! 우선순위에서 밀리지 않는다.
그렇다고 해서 유연한 구조가 우선순위에서 밀린다는 말은 아니다. '일단 (내일 배포니까) 돌아가게 할까요? (안예쁜 플래그를 넣어서)' 라는 말을 지금껏 최소한 다섯 번 이상은 해왔지만, 그렇게 급하게 처리해둔 코드가 추후 반드시 문제가 된다는 것을 위에서 언급한 1년 남짓의 경험을 통해 뼈저리게 느꼈다. 그 프로젝트는 회사를 대표하는 수준으로 큰 프로젝트였는데 그만큼 레거시와 각종 알 수 없는 코드들도 상당했다. temp 변수, 아무 역할도 안 하는 플래그, 이상한 주석, 땜빵의 흔적, 곳곳에 숨어있는 서너 쌍둥이들(중복코드) 등등... 기존 기능을 건드리려면 코드 파일들을 몇 번이나 번갈아 들춰봐야 했고 그렇게 했는데도 버그가 생기는 참사도 있었다. 기획 쪽에서 기존 기능 개편안을 가져올 때마다 기존의 레거시 코드와 전쟁을 벌였고 그 전쟁에 소요되는 에너지와 시간이 상당했던 것으로 기억한다. 아예 계획을 잡고 리팩토링을 했던 적도 몇 번 있었고 코드리뷰 때 구조도를 그리며 리팩토링 산출물 같은 것;을 발표했던 기억도 난다. (그렇게 한 리팩토링도 내 능력부족으로 인해 별로 깔끔하지는 않았으니 지금 생각하면 창피한 흑역사다. 그 코드를 남기고 떠난 덕에 내 수명이 많이 늘어났을 것이라고 예상된다. 코드에도 잊혀질 권리를 행사할 수 있겠으면 좋겠다.) 어쨌든 '기능이 잘 동작한다'는 말은 버그가 없다는 것도 포함하는 표현이고, 그러기 위해서는 제대로 된 구조를 갖추는 것이 필수적이다. 그 코드를 오래 쓸수록 중요도는 높아진다. 지금 속해있는 조직에서는 좋은 쪽으로 그 말을 체감하고 있다. 한국의 밥 아저씨 같은 분과 일하고 있어서 어쨌든 서비스가 잘 나가게 되면 필연적으로 내가 짜놓은 코드와 오래오래 사이좋게 지내야 하는데, 코드를 질나쁘게 짜놓으면 코드 역시 개발자에게 질나쁘게 굴기 마련이다. 쭉쭉 기능을 붙이고 동작을 개선하고 해야 하는데 뭘 어떻게 붙여야 할지 막막해지고 눈앞에 오로지 Bool 변수만 아른거리게 되는 것이다... 그러니 유연한 구조는 필수다. 우선순위에서 밀리지 않는다.
동작은 현실적인 문제이고, 구조는 자칫 이상적인 것처럼 보이지만 사실 현실적인 문제다. 따라서 나의 결론은, 동작과 구조는 어느 것을 우선할 문제가 아니라 둘 다 필수라는 것이다.
칸트의 순수이성비판에 이런 말이 나온다. '지성 없는 감성은 맹목적이고, 감성 없는 지성은 공허하다.' 대상을 올바르게 파악하기 위해서는 감성(인식, 경험)과 지성(개념, 사고) 중 어느 것도 빠져서는 안 되는 필수 조건이라는 말이다. 나는 솦 개발자의 두 가지 책임에 대해 이렇게 말하고 싶다. '동작하지 않는 유연한 구조는 자기만족이고, 스파게티 코드로 동작하는 프로그램은 시한폭탄이다.' 이렇게 쓰고 보니까 후자가 더 위험해 보이니 밥 아저씨의 말이 맞는가 싶기도 한데...어쨌든 둘 다 나쁘다. 둘 다 안 된다. 어느 것에 우열이 없다고 생각한다. 그냥 쓰레기(전자)나 재활용도 안 되는 쓰레기(후자)나 둘 다 밖에서 보면 쓰레기 아닌가.
사실 이 생각들은 따로 일기장에 길게 썼던 것이다. 깔끔하게 정리하여 여기에 덧붙이고 싶었는데 막상 쓰다보니 일기보다 더 장황한 글이 되었다. 혹시라도 여기까지 읽어주신 분이 있다면 감사하다는 말을 전하고 싶다. 읽다 지겨워서 스크롤만 내려 여기를 읽으신 분이 있다면 죄송하다는 말을 전하고 싶다.
'개발서적 읽으며 끄적끄적 > Clean Architecture' 카테고리의 다른 글
SOLID 원칙을 Swift 코드로 이해해보기 (0) | 2019.12.03 |
---|---|
클린 아키텍처 3-6장 (0) | 2019.11.16 |