사이드프로젝트로 린스타트업 실천해보기 - 이터레이션 (2/3)
2024년 03월 24일 작성TL;DR
- 내가 사용자인 프로젝트를 하자.
- 초기에는 변경에 유연하게 대응할 수 있는 것이 최우선이다.
- 자주 배포할 수 있도록 적절한 파이프라인을 미리 구축해두자.
- 메트릭을 먼저 정해서 쌓을 수 있도록 준비하자.
시작하며
지난 글1 이후로 주말에 조금씩 진행중인 프로젝트2를 통해 린스타트업을 체득해나가는 과정에 대해서 이야기 해본다. 약간 서비스 개발에 대한 일기 같은 느낌의 글이 될 것 같다.
이름을 대충 정하기
보통 서비스 시작 전에 가장 시간을 많이 들이는 부분은 이름을 정하는 것인데, 실제로는 그럴 필요가 없다고 생각한다. 개인적인 기준으로는 2시간 이상 이름을 정하는 것은 시간낭비이다.
내가 이렇게 생각하는데는 몇 가지 이유가 있는데,
- 다루고자 하는 문제와 방법이 이터레이션 동안 지속적으로 변화하기 때문에 이름도 아예 추상적이거나 문제와 관련이 없는 이름이어야 한다. 이런 추상적인 이름은 오히려 쉽게 만들기 어렵다.
- 어차피 아무도 모르는 서비스 이므로 이름을 바꾸는것도 자유롭다. (예를 들어, Instagram 은 처음에 Burbn 이라는 이름이었고, Miro 도 원래는 realtimeboard 였다.) 정식출시 전에 더 좋은 이름이 생각나면 바꾸면 그만이다.
원래 내 프로젝트의 이름은 Send + English = Sengl
이었는데, 매일 하나의 표현을 보내주는 서비스가 핵심기능이었기 때문이다.
하지만, 이터레이션을 거치면서 서비스의 방향이 바뀌게 되었고, ChatGPT 한테 서비스의 컨텍스트를 주고 하나 지어달라고 했다.
그래서 나온 ComposeBold
이라는 이름으로 해둔 상태이다. (다음에 바꿀 땐 클로드에 물어볼 예정이다.)
린스타트업 프로세스 팁
린 스타트업에서 가장 중요한 것은 가설(Hypothesis), 실험(Experiments), 검증(Analyze)의 이터레이션을 효과적으로 돌릴 수 있도록 해두는 것이다.
각 과정에서 중요하게 생각해야하는 부분을 간단히 적어본다.
가설
애자일 프로세스는 작은 실험들을 모아서 진행하는 바텀업으로 진행하게 되기 때문에, 실험을 진행하는 동안 원래의 목표가 희석되거나 변형되는 경우도 생긴다.
이런 것을 방지하기 위해서는 매 가설을 세우는 과정에서 반드시 원래 풀고 싶었던 문제와 조율(align)하는 것이 중요하다. (gradient vanishing 을 막기 위해서 skip connection 을 사용하는 것과 비슷한(?) 느낌)
원래 내가 풀고 싶은 문제와 조건은 아래와 같았다.
- 준비 없이 짧은 시간에 쉽게 할 수 있어야 한다. (출근 지하철 대기, 퇴근 지하철 안 같이)
- 영어 작문을 하면서 어휘력을 키울 수 있으면 좋겠다.
- 내가 원하는 표현을 지정해서 익숙해질 때까지 연습할 수 있으면 좋겠다.
이런 내용을 정리해둔 한장의 그림인 린 캔버스를 사용하는 것도 도움이 된다.
실험
초기 실험은 구현이 필요하지 않은 경우가 많다.
특히 내가 사용자인 경우, 아이디어를 직접 몸으로 실천해보거나, 종이와 펜으로 그려서 실험을 해보거나, 쥬피터 노트북 같이 인터랙티브한 환경에서 간단히 실험을 하는 식으로 실험과 검증을 빠르게 진행할 수 있다.
하지만 어느 정도 방향성이 정해져서 코드를 작성하게 되고, 서비스를 통해 실험 및 검증을 해야하는 경우에 아래 3가지가 중요한 것 같다.
- 아키텍쳐와 코드를 쉽게 뜯어고칠 수 있도록 구성하기
- 피쳐를 빠르게 배포할 수 있도록 파이프라인을 구축하기
- 메트릭을 먼저 정해서 쌓을 수 있도록 준비하기
서버리스
아키텍쳐와 코드 측면에서 가장 추천하는 방법은 역시 서버리스를 사용하는 것이다. 서버리스는 코드를 작성하고, 배포하고, 테스트하는 과정을 매우 쉽게 만들어준다.
다만, 모든 기능을 처음부터 다 잘게 쪼개서 함수로 구분하는 것은 복잡도를 높일 수 있기 때문에, 처음에는 proxy 방식으로 소수의 함수로 묶어서 구현하는 것이 좋다.
코드 작성에 대해서도, 개발하는 속도도 중요하지만 적절한 모듈화가 되어 있어야 마구마구 뜯어고치기 좋기 때문에, 아무리 빠르게 개발하더라도 적당한 추상화를 진행하면서 개발해야한다.
개인적으로 람다는 Vertical Sliced Architecture3 를 적용하는 것이 무난한 것 같다.
비용측면에서 서버리스가 유리한데, 비용이 사용한 만큼만 발생하고 프리티어도 제공하기 때문에 초기에는 사실상 비용이 나가지 않는다.
실험대상인 ComposeBold2 도 서버리스로 구성되어 있고, 아직 혼자서만 사용하는 서비스이기 때문에 비용도 전혀 발생하지 않는다. (Bedrock 비용은 발생한다.)
메트릭
코드를 빌드하기 시작하면 메트릭을 쉽게 쌓고 확인할 수 있는 환경을 구성해야 한다.
Google Analytics 의 Tag Manager 같은 기능을 쓰는것도 좋고, 그냥 DB 테이블에 데이터를 넣어두고 봐도 좋다. 여튼 본인이 편한 방식으로 메트릭을 쌓고 볼 수만 있으면 된다.
개인적으로는 AWS CloudWatch Logs 에 Structured 로그를 쌓고, Cloudwatch Logs Insights 로 쿼리를 날려서 확인하는 방식을 사용하고 있다.
메트릭으로 쌓아서 볼 내용이 있으면 EMF (Embedded Metric Format) 를 사용하면 좋다. EMF 는 CloudWatch Logs 에서 쉽게 파싱할 수 있는 형태로 로그를 쌓을 수 있게 해주는데, 직접 커스텀 메트릭을 API 호출로 쌓는것 보다 가격이 매우 저렴하다.
배포와 디버깅
람다를 쓰면 자연스럽게 IaC(Infrastructure as Code) 를 쓰게 되므로 배포 자동화가 매우 쉽다. CI/CD 같은 파이프라인도 CDK Pipeline 을 통해 쉽게 구축할 수 있지만, 혼자 개발하는 경우에는 그냥 cli 로 배포하는 것으로 충분한 것 같다.
람다를 쓰더라도 로컬에서 테스트할 수 있도록 환경을 설정하는 것은 매우 중요하다. 테스트 케이스를 많이 작성하면 좋겠지만 언제 사라질 지 모르는 코드에 대해서 테스트 케이스를 작성하는 것은 비효율적이다. (그리고 1인 개발을 하는 입장에서 테스트 케이스를 꼭 작성해야 할 만큼 어려운 로직을 사용하는 일도 많이 없는 것 같다.)
API Gateway Proxy 와 람다를 연결해서 사용하면 보통 특정 framework (python 이라면 flask, golang 이라면 gin) 을 사용할 수 있는 wrapper 라이브러리를 사용하게 된다.
해당 라이브러리를 사용하면 로컬에서는 원래 웹 프레임워크로 서버를 띄우고, 동일한 엔드포인트와 페이로드로 로컬에서 쉽게 테스트한 뒤에, 바로 배포할 수 있다.
그 외에도 가능하면 디버깅을 위해서 X-Ray 같은 서비스를 사용해서 트레이싱을 하는 것을 추천한다.
람다에서 OpenTelemetry 를 사용해서 X-Ray 를 사용하는 것도 해봤는데, ADOT 는 람다 콜드스타트 시간도 오래 걸리고 기능도 제한적이며 장점이 거의 없다. 그냥 X-Ray 를 사용하는 것이 훨씬 저렴하고 편하다.
검증
앞에서 말했듯, 초기에는 실험과 검증이 한번에 진행되는 경우가 많다.
하지만 개발을 시작해서 서비스를 배포하고 나면, 실험과 검증이 점점 분리되기 시작한다.
위에서 말한대로 메트릭을 잘 쌓아두고 쉽고 (저렴하게) 확인할 수 있는 환경을 구축해두면, 검증을 할 때 매우 편하다.
프로젝트 이터레이션
ComposeBold 는 대략 서너달 전부터 주말에 시간날때마다 진행하고 있는 프로젝트로, 이터레이션(가설-실험-검증) 을 많이 진행했고 피벗도 몇번 진행했다.
이터레이션 전에 린 캔버스2 를 만들면서, Golden circle 의 Why 와 How 는 정리할 수 있었지만 What 은 정하지 못한 상태였다.
아마존 스타일의 PR/FAQ 도 정리를 나름 해봤지만, pre-PFM 상태에서는 PR/FAQ 보다 린 캔버스 정도가 적절한 것 같다.
매 이터레이션은 아래 내용을 중심으로, 직장인으로써 큰 덩어리의 시간보다 작은 짜투리 시간을 활용하여 영어 실력을 늘릴 수 있는 방법을 찾는 실험위주로 진행했다.
- 준비 없이 짧은 시간에 쉽게 할 수 있어야 한다. (출근 지하철 대기, 퇴근 지하철 안 같이)
- 영어 작문을 하면서 어휘력을 키울 수 있으면 좋겠다.
- 내가 원하는 표현을 지정해서 익숙해질 때까지 연습할 수 있으면 좋겠다.
글의 마무리로, 이렇게 진행한 이터레이션 중에 기억나는 몇 개를 적어본다.
첫번째 이터레이션 - 문제 분석
내가 가장 나아지고 싶은 부분이 뭘까 생각해보니 영어 어휘력이 약해서 문장을 잘 못만드는 부분이었다.
그래서 몇몇 책을 사서 몇주간 다양한 어휘력 책을 읽고 외워봤는데 생각보다 늘지 않았다. 해당 어휘를 쓸 일이 많이 없고 보고 읽을 수는 있게 되었지만 그 어휘나 문장을 활용할 수가 없었기 때문이었다.
영어 일기를 쓰면 어휘력 증강에 도움이 된다는 이야기를 많이 하길래 해당 내용으로 시작하기로 했다.
그래서 그날 저녁에 자리에 앉아서 영어일기를 써보려고 했는데, 뭘 써야할지 감이 안왔다. 하필 그날은 별 이슈도 없는 평범한 날이어서 그날 있었던 일 중에 기억나는 일이 딱히 없었고, 아는 문장으로 대충 써봤더니 시간이 너무 많이 지나있었다.
다만, 이렇게 고민하면서 글을 쓰고 하면 실력이 늘거 같긴 해서 영어 일기를 쓰는 방향성은 맞는 거 같지만 더 쉽게 써줄 수 있게 도와주면 좋겠다고 생각했다.
그래서 처음엔 영어 일기를 쓸 글감을 하루에 하나씩 주는 서비스 - Sengl
이라는 이름으로 시작했다.
두번째 이터레이션 - PoC 와 프로토타이핑
하루에 하나씩 글감을 푸시하는 것이 핵심이었지만 푸시 시스템을 구현하는데 오래 걸리므로 알람을 걸어두고 그냥 내가 들어가서 테스트 해봤다.
쥬피터 노트북에 Claude 2.0 을 사용해서 (그 때는 3 가 없었으므로), 말을 걸면 그날의 글감을 주는 것을 구현했다.
며칠 써보니 나쁘지 않은 것 같아서(이대로 계속 공부하면 실력이 좋아질 것 같은 느낌) 서비스 형태로 구현을 해서 혼자서 사용해봤다.
그런데 막상 구현해서 써보니, 글감을 지정해주는 것은 좋은데 지정된 글감에 따라 글을 안쓰게 되는 경우도 점점 늘어나고, 일이 바빠지면서 작문을 할 수 있을 정도의 시간을 확보하기도 어려워졌다.
자유롭게 글을 쓰는 식으로 학습할 경우 피드백을 읽고 되새김 하는 과정이 글을 쓰는 과정보다 더 중요한데, 마치 그냥 준비 없이 전화영어를 들어가서 이미 알고 있는 문장으로만 이야기 하고 나오는 느낌이었다.
이런 형태의 전화영어는 이미 많이 해봤고 실력이 늘지 않았다는 것을 체험했었기 때문에 좀 다른 방식을 찾아봐야 했다.
세번째 이터레이션 - 피버팅
전날 회식을 하고 아침 출근길에 유튜브를 보다가, 어제 집에 잘 들어갔어? 를 3초안에 말하지 못하면 클릭하세요
라는 쇼츠를 보고 나서, 이런 방식으로 영어 표현을 익히면 효과적일 것 같다고 생각했다. (참고로 Did you get home safe yesterday? 라는 문장이었다.)
계속 봐왔던 쇼츠이고 영상인데 왜 갑자기 클릭하게 되었을까 생각해봤더니, 표현이 내가 쓰고 싶은 표현이었기 때문이었다.
대신 공부하는 대상을 다시 생각해봤을 때 문장은 너무 큰 단위이라 유연함이나 활용도도 떨어지는 것 같아서 표현으로 범위를 좁혔다. (get home 을 자유롭게 활용할 수 있도록)
내가 표현을 많이 알면서도 활용을 잘 못하는 이유는 크게 2가지 인 것 같은데,
- 내가 그 표현을 평소에 쓸 일이 없다고 생각해서 관심이 없고,
- 실제로 그 표현이 있는 문장을 해석할 수는 있지만 어떻게 문장 안에서 쓰는지는 모르기 때문이다.
내가 평소에 생존을 위해 영어를 공부하는 방식을 돌아보니 아티클을 읽다가 모르는 표현이 나오면 그것을 메모해두고, 나중에 다시 보면서 익히는 방식을 쓰고 있었다.
이 방식으로 하면 1번은 해결되지만, 2번은 해결되지 않는다. 그래서 누군가 말을 하거나 글을 쓰면 알아 들을 수는 있지만 내가 처음부터 글을 쓰거나 말을 하는데 어려움을 겪고 있는 것 같았다.
그래서 그냥 평소에 내가 공부하는 방식을 적용해서 글을 쓰면서 표현을 익히는 방식으로 바꿔보기로 했다.
네번째 이터레이션 - 스케일링
서비스를 글감을 주고 피드백하는 시스템에서, 매일 하나의 한글 문장을 보여주고 번역하는 연습을 할 수 있는 방식으로 완전히 재작성해봤다.
이 방식은 위에서 말한 3가지 조건을 다 만족하면서도 꾸준히 하면 실력이 늘 것 같은 느낌도 받을 수 있었다.
원래는 크롤러가 몇개의 소스에서 데이터를 계속 긁으면서 데이터를 추가하는 방식이었는데, 사용자가 원하는 표현을 직접 추가하는 기능을 넣으면서 해당 방식은 더 이상 유효하지 않은 방식이 되었다.
사용자가 무슨 표현을 추가할지 알 수 없고, 해당 표현마다 번역과 예문을 추가하기 위해서 크롤러를 쓰는 것은 스케일링이 어렵기 때문이다.
그래서 모든 크롤러를 제거하고 클로드를 이용해서 자동화하도록 변경했다. 이로써 운영비용이 매우 저렴해지고, 처음 보는 표현들에 대해서도 대응이 가능한 서비스가 되었다.
다섯번째 이터레이션 - 기능적 피버팅
한동안 쓰다보니, 매일 번역하는 기능보다 내가 원하는 표현을 추가하는 기능이 더 중요하다는 것을 깨달았다.
그래서 매일 번역하는 기능을 아예 빼봤더니, 내가 아티클을 안 읽는 날은 아예 공부할 일이 없게 되는 문제도 있어서 두개의 기능이 모두 상호보완적으로 필요하다는 것을 깨달았다.
결국, 표현 사전 기능을 메인으로 두고 매일 번역하는 기능을 서브기능으로 사용하게끔 전체적으로 조정했다. 내가 마주친 표현을 마스터하는 측면에서는 현재까지 가장 괜찮은 상태인 것 같다.
여섯번째 이터레이션 - 모바일 환경
이 후, 막상 기능이 완성되고 보니 PC 보다 모바일에서 점점 더 많은 시간을 사용하게 되었다.
따라서 모바일에 더 친화적인 UX 가 필요하다는 것도 깨닫게 되었고, 모바일에서 문제를 쉽게 푸는 방향으로 수정하게 되었다.
그 후
지금도 영어는 계속 못하는 상태이지만 매일 한번씩 표현을 보고 번역하고, 내가 원하는 표현을 추가하면서 조금씩 실력이 늘고 있는 것 같다.
영어공부보다 서비스에 대한 고민을 더 많이 하게 되어서 실제로 영어가 늘지 않는 느낌인 것이 새로운 고민이지만… 영어 외적으로도 무언가를 학습할 때 비슷한 방식으로 고민하게 되어서 전체적으로는 좋은 경험이 되는 것 같다.
마치며
린스타트업의 유용함은, 스타트업에 사용자 전문가가 없으므로 사용자의 피드백을 직접 받는 방식을 취한다는 것에 있다.
린스타트업을 체득하는 실험을 하면서도 아직 사용자에게 오픈하지 않았는데, 이 부분에서 약간 목적을 벗어나는 느낌이 들기도 한다.
하지만 아래와 같은 이유로
- 아직까지 내 자신이 사용자로서 충분하기도 하고,
- 다양한 채널의 피드백을 받는다고 해서 그것을 반영할 수 있는 시간을 개인적으로 확보할 수도 없으며, (현재도 2주에 몇 시간 정도만 프로젝트에 쓸 수 있는 것 같다.)
- 프로젝트의 목적상 개인 비용을 내고 서비스를 오픈하는 것이 개인적으로 의미를 가지지 않기 때문이다.
또한, 최근에 영어 회의를 진행하고, 출장대비를 잠시 하면서 단순히 표현을 익숙하게 익히는 것으로는 부족하다고 느껴서 해당 기능을 계획하면서 실험하려고 하고 있다.
여튼 마지막 글에서는, 린스타트업을 제대로 체험하긴 해야하니깐, 오픈을 하고(언제 닫을지는 모르지만), 실제 사용자 피드백을 받아서 서비스를 개선하는 과정에 대해서 이야기해볼 예정이다.