코드를 잘 짜서 무엇하리

클라이언트 개발자가 변화 속에서 살아남는법

앱개발자123
6 min readSep 22, 2020

사내에서 급하게 사이드 프로젝트를 진행하게 되었다.
기한은 코앞이라 불똥이 떨어졌는데 스펙정리는 부실해서 입사이래 가장 망가지는 기간이었다.
이 혼란속에 딱 한가지 얻어가는 것이 있다면,
아무리 급해도 코드는 잘 짜야 편하다는 것이다. Clean code matters!

좋은 코드 그거 다 주관적인것 아니겠어요

코드를 잘 짠다는 것은 언제 언급해도 좀처럼 의견이 좁혀지지 않는 뜨거운 감자 같다.
좋은 코드가 뭔데? 클린코드, 클린아키텍쳐, 디자인패턴, 리팩토링, 확장성, 변경가능성, 간결함, 코드 중복, 추상화, 모듈화… 코드 퀄리티 유지를 논할때마다 좋은 개념들이 슬쩍 나왔다가 두루뭉술하게 대화가 끝난다.
그러다보면 과연 이 세상에 잘짠 코드라는게 존재할까라는 생각도 든다.

계실까?

아직 3년차 밖에 안된 개발자라, 참 갈길이 멀지만 이 주제에 대해 중간 결론을 내리고 가려한다.
완벽한 코드는 절대 없다. 왜냐하면 사업의 의도와 방향이 변하기 때문이다. 찰나의 순간 완벽한 코드가 있을수는 있지만, 그 마저도 오래가는 못한다.
그렇지만, 꽤 괜찮게 코드를 짜는법은 있다. 그 변화에 맞춰 변경하기 쉬운 코드를 짜면된다. 변경하기 쉬운코드란, “어디를 고쳐야 하지?” 에 대한 답변이 빠르게 나오는 코드이다. 이 답변이 빠르게 나오려면 코드는 구조화 되어있어야 한다.

계신다!

1인분하는 개발자가 1.2인분 하는게 아니라,
0.5인분 하는 개발자가 1인분을 하도록

어떤 개발자가 굉장히 뛰어나서, 자신의 코드를 다 꿰고 있을수는 있다. 그렇지만 우리가 원하는 것은 한명의 특출난 개발자가 아니라, 쉽게 유지되는 개발팀이다. 나 또한 그렇게 뛰어난 사람은 아니라서, 코드가 읽기 쉬워야 하고, 더 나아가 어떤 코드를 읽어야 하는지, 찾기 쉬워야 한다고 생각한다.

구조화된 코드는 찾기 쉽고, 의도가 반영된 코드는 읽기 쉽다.

구조는 어차피 변할텐데 무슨 의미가 있겠어요

클린 아키텍쳐라는게 굉장히 난해하게 다가올 수 있는데, 쉽게 생각하면웬만한 앱 까보면 다 똑같다 를 말하려는것 같다. 다 똑같으니, 정형화된 구조에 맞춰 개발하면 웬만한 부분은 정리가 된다는 것이다.

여기서 짚고 넘어가야 할것이 있는데, 구조라는것은 5년,10년을 버틸 철옹성같은 무언가를 쌓는게 아니다.
반대로 잦은 변화도 금방 수용할수 있는 내진설계를 하려는 것이다.

수많은 앱들을 떠올려보자.
유저의 손가락이든, 키보드든, 마이크든 어디선가 입력이 들어오면 어떤 마법같은 로직을 거쳐, 저장된다.
반대로 저장된 정보는 꺼내진 후에 어른의 사정을 거쳐 가공된 후 GUI, 스피커 등으로 출력 된다.
입출력, 가공, CRUD. (굉장한 기술을 요구하는 앱이 아니고서야) 웬만한 앱은, 이 정도가 전부다.

입력 -> 가공 -> 저장 // 출력 <- 가공 <- 불러오기

클라이언트 개발자는 생각보다 할게 없다. 생각보다 생각할 것도 없다.
입출력은 디자이너가,
CRUD는 서버개발자가,
비지니스 로직은 기획자가 스펙문서로서 정해줄테니까.

디자이너, 기획자, 서버 개발자

클라이언트 개발자의 역할은 단순하다.
이 3개의 협업포인트에서 오는 내용들을 코드에 그.대.로. 받아 적어 내리면 된다.

근데 그 그대로 라는게 참 어렵다. 쉬웠으면 내가 돈을 못벌었지

우리는 이것을 구조적으로 분리할수 있다. 용어는 조금 상이할수있지만 presenter / domain / repository 정도이다. 이렇게 구조를 분리하면 변화하는 환경에 효과적으로 대응 할수 있다. 스펙변경이 일어날때, 그것이 디자인 변경인지, 서버의 변경인지 등에 따라 변경될 코드 위치를 빠르게 찾아 낼수 있기 때문이다.

각 협업자의 영역을 구조로서 분리 할 수 있다.

적용

이제 실제 디자인과 실제 API를 기다리지 않아도 비지니스 로직을 짤수 있게 된다.

구체적인 버튼의 모양과 위치는 안나왔지만, 우리는 그 버튼이 어떤 데이터를 활용해 어떤 기능을 할지 알고있다. 그렇기 때문에 구체적 UI와 별개로, UI state를 관리함으로서 많은 기능을 미리 구현할수 있다. 이후 UI가 나오면, state의 변경대로 대응만 해주면 된다.

ViewState를 명시적으로 구분하면, 관리하기도 편하고 실제 UI와 종속성도 분리할수 있다.

또한 API 스펙이 나오지 않아도, 어떤 의미를 가진 데이터가 오갈지 알고있기때문에, API 스펙대로가아닌, 서비스 의도가담긴 entity를 활용해서 비지니스로직을 미리 구현할수있고, 이후 API가 나오면 mapper function을 통해서 entity와 연결해줄수 있다.

UserEntity라는 개념을 API구현 이전에 정의 해놓음으로서, User와 관련된 많은 동작을 미리 구현할수 있다.
실제 API가 만들어졌을때는, 이렇게 API스펙 <-> Entity간의 mapper만 구현하면 된다.

클라이언트 개발은 어떻게 겨우 눈에만 잘 돌아가는 것을 개발하는 것이 아니다. 디자이너, 서버개발자, 기획자의 의도를 고스란히 코드에 녹여야 한다. 그 의도가 불분명할땐, 명확하게 풀수있도록 가이드를 해주는것 또한 클라이언트 개발자의 역할이다.
그리고 가장 중요한 것은 변경이 생겼을때, 서비스의 의도가 어떻게 변했는지 파악하고, 이를 코드에 반영할수 있는 것이라고 생각한다.

기존에는 User가 device를 항상 갖고 있을거라는 가정하에 개발을 진행하였다.
하지만 device는 유저의 여부와 상관없이 사용될수 있는 개념이었고,
오히려 쓸데없는 User에 대한 종속성만 생기게 되었다. 물론 null check를 통해서 대충 넘길수도 있는 부분이지만, 의도에 맞게 리팩토링을 통해 User와 Device를 분리함으로서 개념적으로도 개발적으로도 독립적으로 사용될수있도록 변경하였다.

그게 왜 그렇게 오래 걸리는지 모르겠네요

버튼하나 옮기는데 왜 5천만년이 걸리냐고?
코드가 사업의 의도와 멀어졌기 때문이다.
개발 언어와 자연어가 근본적으로 다르다는 핑계로
이를 조율하고 맞출 생각을 안했기 때문이다.
개발일정이 조금 길다 싶으면 개발자의 역량일수 있지만,
상식적인 범위에서 벗어난다면, 코드와 의도의 간극이 얼마나 벌어져있는지 점검할 필요가 있다.

멍청하니까 기대를 하면 안된다.

코드는 지극히 단순하다. 한치의 융통성도 없이 사람이 시키는대로만 한다.
그래서 코드가 요청을 제대로 수행하지 못하고 있다면, 우리가 뭘 시키고 있는지 돌이켜 봐야한다.

--

--