지난 1년 동안 서비스 회사에서 거의 풀스텍으로 서비스 개발 및 운영을 해왔었다. 작은 규모의 회사였기에 서비스 기획, 디자인, 개발, 운영 등 많은 부분에 대해 아이디어를 공유하고 참여할 수 있었다. 개발 역할 뿐 아니라 기획, 디자인 등의 서비스 전반에 대한 롤을 맡다보니 각 역할이 어떤 고민을 하고 있는지 생각할 수 있었다. 예전에 서비스 회사에 들어오기 전에 생각했던 서비스 개발과 지금의 서비스의 개발에 대한 생각은 많이 다르다. 막연히 서비스라는 것은 개발자가 치밀하게 잘 개발하고 홍보하면 시장에서 알아줄 것이라고 생각했다. 실상은 개발보다는 각 역할간의 커뮤니케이션과 정확한 목표를 설정하는 것이 매우 중요하였다.
Letshadow라는 서비스 개발하면서 세웠던 세가지 원칙이 있다. 해당 원칙들은 만약 내가 지금 회사의 서비스를 다시 시작한다면 꼭 하고 싶은 방향이라 할 수 있다. 세가지 원칙은 다음과 같다.
- 작은 시작, 짧은 리펙토링
- 목표와 목표가 아닌 것에 대한 명확한 분리
- 명확한 스펙 설정
서비스를 개발할 때 위의 원칙들을 따르려고 노력했고 해당 내용은 1.0.0 버전의 테크스펙에 자세히 나열해 놓았다.
첫번째. 작은 시작, 짧은 리펙토링
순수히 개인적으로 고민해왔던 부분이다. letshadow라는 서비스는 4년전 미국에 있었을 때부터 생각해놓은 서비스이다. 하지만 4년 뒤인 지금에 와서 개발을 하고 있다. 왜 그런 것일까?
이유는 너무 거창하게 생각했기 때문이다.
서비스를 하려면 남들이 좋다고 생각하는 기술들을 마구 사용해줘야 된다고 생각했었다. "적어도 서비스를 하려면 마이크로서비스에 리액트와 스프링부트 프레임워크를 이용한 SPA 정도 써줘야지" 라는 생각을 가지고 있었다. 지금 생각하면 왜 그런 생각을 했는지 아직도 의문이다. 아마 이뤄지지도 않을 성공적인 서비스를 생각하며 김칫국을 마셨기 때문이라고 생각한다. 그래서 4년이라는 기간동안 공부만하고 정작 시작하지는 못했다. 내가 공부를 많이 했기 때문에 개발할 때 문제를 척척 해결해 나갈 것이야 라는 얼토당토 않하는 생각을 가지고 있었다. 이런 생각은 서비스 개발을 하면서 산산히 부숴졌다. 서비스를 개발하면 정말 생각하지 못한 다양한 문제들에 부딪히게 되고 그것을 해결하는 과정에 시간을 더 많이 할애하게 된다. 그것을 간과한 채로 서비스를 개발하게 되었고 덕지덕지 붙은 쓸모없는 스펙들은 시작을 더욱 부담스럽게 만들었고 결국은 시작하지 못하게 만들었다.
1.0.0 버전에서는 스프링부트와 자바스크립트를 이용하여 API 통신하는 간단한 모델로 개발하였다. 덕분에 프론트엔드 단에서는 순수하게 동영상을 구간반복하고 자막을 배치하는 로직에 대해서만 고민할 수 있게 되었다. 이는 다음 1.1.0 버전에서 동영상 구간반복 + 자막 배치를 하는 라이브러리를 별도로 개발하여 클라이언트 로직과 구간반복 모듈의 관심사를 분리하는 긍정적인 결과도 낳게 되었다. 백엔드에서는 기본적으로 에러처리, OAuth로직, TDD, CI/CD 및 자동배포를 하는 서비스를 위한 기본적인 설정말 하였다. 심지어 비즈니스 로직 조차도 없다. 왜냐면 1.0.0 서비스에 대한 목표는 동영상 구간 반복하는 서비스만 제공하기였기에 다른 복잡한 내용들을 뺄 수 있었다. 덕분에 OAuth 인증과 복잡한 구글 OAuth Consent Page에 집중할 수 있었다. (Youtube Data API는 sensible scope이기에 복잡한 인증절차가 꼭 필요하다)
중요한 점은 불필요한 요소를 버림으로서 현재 필요한 내용을 반복해서 검증할 수 있다는 것이다. 다시말하면 TDD를 통한 꾸준한 리펙토링을 가능하게 해줬다. 개발할 내용이 많으면 검증할 부분도 많아지기 때문에 마음만 조금해 지고 검증은 안되는 상황이 생긴다. 자연스럽게 서비스의 완성도가 떨어지게 되는데, 특히 회사마치고 많은 시간을 들일 수 없는 프로젝트의 경우, 이러한 상황에서 더욱 더 완성도가 떨어질 수 밖에 없다고 생각한다. 선택과 집중이라고 했던가 비록 연애 뿐만이 아니라는 이야기이다. 리펙토링을 계속하다보면 변경될 부분이 보이게 되고 자연스럽게 분리를 하려고 한다. 이는 미래의 나에게 조금이나마 더 손쉽게 덜어낼 수 있는 똥을 던져줄 수 있다. 자연스럽게 객체지향 프로그래밍을 생각하지 않을 수 없게 만든다.
시작이 반이라는 말이있다. 이는 적게 시작하는 것이 반이라고 표현하고 싶다. 작게 시작하고 많이 반복해서 보고 검증하여 미래의 나에게 조금 더 변경가능한 똥을 주도록 하자가 첫번째 원칙이다.
두번째, 목표와 목표가 아닌 것에 대한 분리
서비스를 운영하는 입장에서 가장 중요한 부분이 아닌가 싶다. 여행 서비스를 개발하면서 애자일 방식을 채택했지만 한번도 스프린트가 제 때 마무리 된 적이 없다. 결국 서비스가 현재 목표가 제때 배포된 적이 없었다. 왜 그럴까?
바로 목표에 목표가 아닌 것을 계속 붙혀나갔기 때문이다.
내가 생각한 애자일 프로세스는 다음과 같다. 한주를 시작할 때 기획 회의를 하고, 디자이너가 디자인 한 이후, 기획자가 기획서를 만들고 그것을 개발자들과 실행가능한지 여부를 판단한다. 기획서가 완성되었다면 일정기간 스프린트를 하고 코드리뷰들을 하고 테스트하게 된다. 마지막으로 배포를 한다. 마지막으로 중요한 고객의 데이터를 기반으로 피드백을 하는 것이다. 이 사이클을 반복하는 것이 애자일 프로세스의 목표라고 생각한다.
회사 서비스에서도 애자일 프로세스를 도입했지만 상황이 조금 다르다. 먼저 기획자가 없기 때문에 모두가 모여 기획회의를 한다. 분명 한가지 목표를 제시하고 시작했지만 어느 순간에 여러가지 기능이 붙게 된다. 예를들어 회의 주제가 메모 작성 서비스 제공이라고 한다고 해보자 그럼 다음과 같은 상황이 발생한다. "메모 작성하는데 음성으로도 할 수 있으면 좋겠는데? 음성 서비스를 넣고, 기왕이면 많은 사람들과 공유할 수 있게 채팅 서비스도 넣는게 좋겠네. 그리고 공유라고 해서 말인데 SNS에 공유도 하고 태그로 검색도 될 수 있도록 하는 것이 좋을 것 같네. 이야 이 정도면 반응이 폭발적이겠어! 좋아좋아!" 이렇게 회의가 마무리 된다. 우리 서비스가 폭발할 수도 있다는 사실도 모른채 말이다. 결국 메모 작성 회의가 음성서비스, 공유, 태그 등 덕지덕지 붙어 하나의 큰 또 하나의 프로젝트가 되어 버린다. 문제는 기존 사이클은 유지한다는 것이다. 이러면 일정에 전혀 맞출 수 없고 맞추더라도 서비스는 엉성해지고 설계 또한 엉망이 되어 버린다.
더 큰 문제는 고객의 반응이 없다는 것이다. 메모 기획에서 나온 결과과 '우리만' 만족하는 서비스를 내놓고 막상 직접 사용하는 일반 사용자는 관심이 없다. 즉, 목표를 벗어나 버리니 고객이 기대하는 서비스를 제공하지 못한 것이다. 아니 사실 고객이 기대조차 하지 않은 것을 한 것이다. 피드백 또한 없으니 막상 중요한 고객의 요구사항을 예측할 수 있는 데이터도 얻지못한 채 해당 서비스는 사장되거나 다음 피처의 수리 대상이 된다. 결국은 시간 낭비만 한 것이다.
letshadow 서비스를 만들면 꼭 명확한 목표설정과 목표가 아닌 것을 눈에 보이게 분리하는 작업을 하고 싶었다. 프로세스와 결과가 얼만큼 달라질 수 있을지 궁금했다. 목표가 아닌 것을 계속 기록해 놓으면 넥스트 피처에서 언젠가는 사용하게 된다. 이는 미래의 좋은 설계를 이끌어 내고 더 나은 중장기적인 계획의 가이드라인이 된다고 생각한다. 이미 1.0.0 버전에서 많은 내용들이 목표가 아닌 것에 분류되었고, 많은 내용들이 다음 버전 혹은 명확하지 않은 미래의 목표를 더욱 명확하게 만들도록 계속 고민하게 해준다. 서비스에 더욱 애착이 가게 되고, 더 많은 목표가 아닌것들이 모여 다음의 목표가 된다.
이것이 목표와 목표가 아닌 내용들을 분리하면서 생각해온 내용이다. 아직 초창기라 중장기적인 목표가 명확하지 않지만 서비스에 대해서 좋은 방향으로 고민할 수 있다는 점에서 현재까지 긍정적이라고 판단된다.
세번째, 명확한 스펙 설정
회사에서 회의는 많이하지만 개발할 때마다 개발자가 주먹구구식으로 개발하는 경우가 종종있었다. 개발자 간의 커뮤니케이션이 비용이 계속 증가하다 못해 심지어는 커뮤니케이션하지 않고 그냥 개발하는 경우도 있었다. 또한 데이터를 기반으로한 의사결정이 아닌 특정인에 대한 의사결정의 문제, 특히 흔히 말하는 HIPPO에 대한 문제가 컸다. 왜 그랬을까?
이유는 구체적인 명세가 없었기 때문이다
회의가 끝난 이후 기획에 대한 명확한 스펙을 항상 정하지 않았다. 회의에서 이렇게 하자가 정해지고 그걸로 끝이다. 구체적으로 API가 어떻게 작성되고 어떤 스택이 사용되고 이런것은 개발자 개인이 알아서 판단하고 작성한다. 대부분 직급이 높은 사람이 작성한 API 명세에 따라가게 된다 (설득의 과정은 있지만 결론은 그렇게 된다..). 한 사람만이 판단한 결론으로 다른 상황의 개발자가 왜 그렇게 되었는지 일일이 묻고 수정하는 일이 더 길어지고, 결국은 그냥 포기한채로 API 스펙에 코드를 맞추게 된다. 이렇게 되면 커뮤니케이션 비용만 더 늘어나게 되고 서로 주장만 하다가 한쪽이 포기한 채로 끝나는 경우가 대부분이 되버린다.
이번에 뱅크샐러드 새미나를 보면서 꼭 도입해 보고 싶었다 (회사에서는 결국 도입하지 못하고 혼자만 하고 있다... 포기하면 빠르다...). 코드를 작성하기 전에 일정기간에 걸쳐서 코드 스펙을 미리 작성한다. 예를들어 API의 요청과 응답이 어떻게 되고 왜 이런 스펙을 사용하게 되었는지 어떤 문제점이 예상되고 해당 목표와 목표가 아닌 것들의 구분되고 해당 가설을 통해 어떤 결과를 도출해내는 등을 자세하게 적어서 팀원들에게 제공한다. 그러면 이제 서로 질문할 필요없이 코드스펙만 보면 된다. 근데 나는 왜 하고 있는가? 코드 스펙을 작성하면서 느낀 것은 코드의 변화 폭과 책임의 구분이 명확해진다는 것이다. 코드를 작성해야만 보이던 것들을 코드를 작성하지 않아도 보이게 된다. 예를들면 데이터의 흐름을 코드로 작성하면서 변경해 나가는 것이 아닌 미리 설계가 어느정도 된 상태에서 코드를 작성하게 된다. 그래서 코드를 작성하는데 시행착오가 적어지게 된다. 또 다른 이유 중 하나는 완성된 테크 스펙은 매우 좋은 문서가 된다는 것이다. 사실 테크스펙을 작성하면서 변경하기도 많이 했는데, 이러한 소소한 리펙토링(?)은 나의 관심도 높아지고 완성도도 높혀주는 것을 느꼈다. 또한 한 사람의 개인적인 결정이 아닌 데이터를 기반으로한 의사결정을 내릴 수 있다. AB 테스트처럼 통제된 환경변수에서 한가지 변수에 대해 가설을 설정하고 실제 데이터가 얼마만큼의 효과를 가져올지 객관적으로 판단할 수 있다. 그렇지 않고서는 생산성없는 책임공방만 이어지게 될 것이다.
마무리
앞에서 설명한 3가지는 개발자로서 좋은 습관이라고 개인적으로 생각한다. 농구에서 드리블 하나를 꾸준히 반복하면 다른 드리블을 연습하거나 배우는 것이 쉬워지는 것처럼 반복의 즐거움을 늘려주는 좋은 습관인 것 같다. 개발해야 될 것도 많고 공부해야 될 것도 많지만 좋은 서비스를 잘 만들어 가는 과정이 하나의 드리블을 마스터하는 즐거움을 준다. 요즘의 유일한 낙인 것 같다. 항상 노력하고 있지만 아직 내가 가지고 있는 시야는 좁다고 생각한다. 더 많은 트래픽과 데이터가 움직이는 곳에서 일을 하면서 실력을 늘리고 싶다. 그러기 위해서는 위처럼 기본적은 것에 힘을 쏟는다면 언젠가 기회가 오지 않을까