TinyPilot: 23개월 차
한 줄 요약
8개월에 걸친 리디자인이 드디어 끝났습니다!
주요 내용
- TinyPilot 웹사이트 리디자인을 마침내 마쳤습니다.
- Debian 패키지를 만드는 법을 배웠는데, 놀랄 만큼 간단합니다.
- Vue와 프론트엔드 프레임워크 전반을 포기했습니다.
목표 평가
매달 초에 이루고 싶은 목표를 선언합니다. 그 목표들을 얼마나 달성했는지 살펴보겠습니다.
TinyPilot로 홈랩 NAS 서버를 구축하는 방법에 관한 블로그 글과 영상 게시
회고나 연말 결산이 아닌 블로그 글을 쓴 것은 1년여 만에 처음이었습니다. Reddit에서는 반응이 그저 그랬지만, Hacker News 2위까지 올랐습니다.
이 글은 많은 방문자를 TinyPilot 웹사이트로 이끌어 월간 순 방문자 수가 1만 4천 명에 달했습니다. 역대 최고 기록이며, 이전 기록을 30% 넘었습니다. 글 작성과 영상 제작에 약 45시간을 썼으니, 결과는 그 노력을 정당화하는 데 도움이 됐습니다.
TinyPilot 웹사이트 리디자인 완료
- 결과: 드디어 끝냈습니다!
- 평가: A
리디자인이 드디어 완료됐습니다. 지난 4개월 동안 매달 이 프로젝트가 끝날 거라고 예상했지만, 늘 무언가가 생겨 지연됐습니다. 이제 공식적으로 끝났습니다.
마케팅 에이전시 또는 프리랜서 채용
- 결과: 6월 초 며칠 만에 프리랜서를 채용했습니다.
- 평가: B
괜찮아 보이는 에이전시를 찾았지만, 조금 미심쩍었습니다. 3개월 계약의 가격에 합의했는데, 합의한 뒤 최소 5개월로 바꾸자고 요청했습니다. 상당한 위험 신호였습니다. 계속 협의해 보려 했지만 그들이 내놓는 제안은 모두 의심스러웠고, 결국 논의를 끝냈습니다.
다행히 전기공학 파트너 회사에서 디지털 마케팅 프리랜서를 추천해 주었습니다. 첫 통화부터 그동안 이야기했던 누구보다 훨씬 잘 맞았기에 즉시 채용했습니다.
TinyPilot 통계
| 지표 | 2022년 4월 | 2022년 5월 | 변화 |
|---|---|---|---|
| 순 방문자 | 5,268 | 14,296 | +9,028 (+171%) |
| 총 페이지 조회 수 | 11,974 | 24,131 | +12,157 (+102%) |
| 판매 매출 | $43,771.00 | $54,844.20 | +$11,073.20 (+25%) |
| 엔터프라이즈 구독 | $47.75 | $47.75 | 0 |
| 로열티 | $2,253.61 | $3,269.56 | +$1,015.95 (+45%) |
| 총매출 | $46,072.36 | $58,161.51 | +$12,089.15 (+26%) |
| 이익 | -$19,392.76 | $6,445.38 | +$25,838.14 (+inf%) |
방문자와 판매 측면에서 강한 한 달이었습니다. 방문자는 거의 세 배가 됐고, 판매는 25% 증가했습니다.
방문자 대부분은 Hacker News에서 왔지만, 판매에는 큰 영향을 미치지 않은 듯합니다. 글이 Hacker News에 올라가기 전에도 판매는 이미 4월보다 약 25% 높은 수준을 기록할 전망이었습니다. 효과가 늦게 나타날 수도 있습니다. 6월 초반이 이례적으로 강하기 때문입니다.
TinyPilot 웹사이트 리디자인
아, 정말. 리디자인 말입니다.
무슨 말을 해야 할까요?
몇 달째 질질 끌렸고, 끝은 늘 불과 몇 주 앞에 있는 것처럼 느껴졌습니다.
이 프로젝트를 시작하며 디자이너와 에이전시를 인터뷰할 때, 몇 달 동안 진행할 $8-15k 규모의 리디자인에 비용을 쓰고 싶다고 말했습니다. 변경이 판매에 실제로 효과가 있는지 확인하기도 전에 6개월과 $40k를 써야 하는 프로젝트는 절대 원하지 않는다고도 했습니다.
결국 프로젝트는 8개월이 걸렸고 $46k가 들었습니다. 피하고 싶었던 바로 그 함정에 빠졌습니다.
이 경험에 관해서는 더 긴 블로그 글을 쓸 예정이지만, 주요 실수는 다음과 같습니다.
- 지나치게 넓은 범위: 에이전시가 본격적인 리디자인으로 범위를 넓히게 두기 전에 리브랜딩부터 시작해 범위를 작게 유지했어야 했습니다.
- 작업 시간 보고가 너무 늦었음: 2주 지연된 보고가 아니라 작업이 발생하는 대로 에이전시가 청구 가능 시간을 보고하는 시스템을 고집했어야 했습니다. 작업에 얼마나 시간이 걸리는지 볼 수 없다면, 예상보다 비용이 많이 드는 것으로 판명될 때 범위를 조정할 수 없습니다.
- 일정에 더 많은 투명성이 필요했음: 프로젝트가 얼마나 오래 끌릴지 놀라지 않도록 일정에 관해 더 많은 소통을 요구했어야 했습니다.
- 관리 시간 부족: 월 40시간 일하는 에이전시는 월 40시간 일하는 개인 프리랜서와 대략 같은 관리 오버헤드가 필요할 거라고 가정했습니다. 에이전시에는 사람이 더 많고, 사람이 많다는 것은 더 많은 관리를 뜻합니다.
하지만 결과를 살펴보겠습니다. 이 프로젝트에서는 결제 흐름의 세 페이지, 즉 랜딩 페이지, 제품 페이지, 장바구니 페이지를 리디자인했습니다.


랜딩 페이지 리디자인 전후


제품 페이지 리디자인 전후


장바구니 페이지 리디자인 전후
비용 문제를 제외하면 결과에는 만족합니다. 새 디자인은 이전 디자인보다 명백히 낫다고 생각합니다. 새 로고와 이미지는 프로젝트를 더 전문적이고 개성 있게 보이게 합니다.
그렇다면 새 디자인이 $46k만큼 더 나을까요?
시간을 되돌릴 수 있다면, 분명 그렇게 많은 돈과 시간을 리디자인에 쏟지는 않았을 겁니다. 그래도 충분히 본전을 뽑을 가능성은 있습니다.
고정비를 제외하면 TinyPilot 판매 매출의 70%가 이익입니다. 즉, 리디자인이 제 몫을 하려면 추가 판매를 $66k 만들어 내야 합니다. 판매가 10% 증가한다면 월평균 $50k에서 $55k로 늘어납니다. 그러면 약 1년 후에는 앞서게 됩니다. 더 나은 마케팅이 더 많은 고객을 사이트로 끌어들인다면, 더 빨리 투자금을 회수할 수 있습니다.
Debian 패키지는 쉽습니다
TinyPilot에서 내린 독특한 설계 결정 중 하나는 설치 및 업데이트 방식입니다. 시스템을 대규모로 프로비저닝하도록 설계된 DevOps 엔지니어용 도구인 Ansible을 사용합니다. TinyPilot 첫 프로토타입에 쓸 Raspberry Pi를 프로비저닝할 때 Ansible을 사용했습니다. 그 방식이 잘 작동했기에 그대로 유지했습니다.
Linux에 소프트웨어를 설치하는 더 나은 방법이 있다는 것은 알고 있었지만, 경험이 없었습니다. TinyPilot에는 Raspberry Pi의 하드웨어 기능을 구성하는 특이한 요구사항이 있어 표준 설치 도구를 그 요구사항에 맞게 조정하는 과정이 두려웠습니다. 대신 문제없이 잘 작동하던 Ansible을 계속 사용했습니다. 몇 초면 끝나야 할 설치가 2분 걸릴 정도로 느리긴 했지만, 크게 나쁘지는 않았습니다.
2년이 지난 지금, Ansible의 한계에 다다르고 있습니다. 설치 과정은 지나치게 복잡해지고 있고, 업데이트는 5분 이상 걸립니다.
과거에 Debian 패키지(예: apt-get)를 고려한 적은 있지만, Debian 패키징 도구에 관한 부정적인 이야기를 들었습니다. 게다가 리포지터리 서버, 키 페어, 패키지 서명 절차까지요? 기본 설정만 갖추는 데도 엄청난 노력이 필요하고, 필요한 일을 하려면 믿을 수 없을 만큼 고통스러울 것 같았습니다.
실험으로 Debian 패키지를 만들어 봤는데, 우려했던 것보다 훨씬 쉬웠습니다. Debian 패키지는 특정 폴더 구조와 몇 개의 특수 파일을 갖춘 tarball일 뿐입니다. 약 한 시간 만에 처음으로 작동하는 .deb 파일을 만들었습니다.
그렇다면 리포지터리 서버와 키 페어는요? 알고 보니 선택 사항이었습니다. 리포지터리 없이도 .deb 패키지 파일을 직접 배포하면 됩니다.
Debian 패키지를 만드는 공식 도구인 debhelper는 들었던 대로 혼란스럽고 어려웠지만, 꼭 필요한 것은 아닙니다. debhelper를 건너뛰고 Debian의 메타데이터 파일을 직접 만드는 편이 더 쉽다는 결론을 내렸습니다.
더 좋은 점은 Ansible에서 Debian 패키지로 무서운 한 번의 도약을 할 필요가 없다는 것입니다. 원하는 속도로 Ansible의 로직을 Debian 패키지로 점진적으로 옮길 수 있습니다.
첫 Debian 패키지는 오픈 소스 WebRTC 서버인 Janus용입니다. 예전에는 각 기기에서 애플리케이션을 소스부터 컴파일했고, 약 30분이 걸렸습니다. 새 Debian 패키지는 몇 초 만에 설치됩니다. 32비트 ARM 바이너리가 필요하지만, Docker의 QEMU 통합 기능을 이용하면 x64 클라우드 서버에서 Debian 패키지를 빌드할 수 있습니다. 코드 컴파일과 패키징을 위한 모든 코드는 오픈 소스입니다.
Debian 패키지를 배우는 데 도움이 된 자료는 다음과 같습니다.
- 나만의 deb 패키지와 apt 리포지터리 만들기 및 호스팅하기
- 바이너리 deb 패키지 빌드하기: 실용 가이드
- Debian 신규 관리자 안내서
- 공식 Debian 문서
- debian/ 디렉터리 기본 개요
검색 광고의 성과가 안정되고 있습니다
마지막으로 계산했을 때 Google 검색 광고는 굉장해 보였습니다. Google Ads에 1달러를 쓸 때마다 $0.69의 이익을 내고 있었습니다. 이제 시간이 더 지나고 데이터도 더 쌓이니, 그림이 그만큼 장밋빛은 아닙니다.
지난달 수치를 계산할 때는 4월과 5월 첫 주를 포함했습니다. 그 첫 주는 이상치로 드러났기에, 월별로 나누면 이익은 더 낮습니다.
| 지표 | 4월 | 5월 |
|---|---|---|
| 광고비 | $804.12 | $4,283.71 |
| 노출 수 | 5,270 | 239,498 |
| 클릭 수 | 351 | 3,327 |
| 클릭률(CTR) | 6.6% | 1.4% |
| 클릭당 비용(CPC) | $2.29 | $1.29 |
| 전환 매출 | $1,314.91 | $7,649.60 |
| 광고비 대비 매출(ROAS) | 1.63 | 1.79 |
매출의 약 30%는 하드웨어와 인건비로 나가므로, ROAS 1.43은 대략 손익분기점입니다(1.43 - 30% = 1.0). 그보다 높으면 이익이 납니다. 1.79에서는 광고에 1달러를 쓸 때마다 여전히 $0.26을 벌고 있으니 계속할 생각입니다.
TinyPilot의 새 디지털 마케팅 컨설턴트가 Google Ads 계정을 검토해 저가치 키워드에 과도하게 지출하는 몇 군데를 찾아냈습니다. 따라서 앞으로 몇 달 동안 이 수치를 개선할 수 있을 듯합니다.
사이드 프로젝트
PicoShare
PicoShare는 이메일로 보내기에는 너무 큰 파일을 공유할 수 있게 해 주는, 제가 3월에 공개한 오픈 소스 도구입니다.
5월에는 파일을 업로드한 뒤 메타데이터를 수정하는 기능을 추가했습니다.

5월에 PicoShare에 파일 메타데이터 수정 기능을 추가했습니다.
원래는 파일을 업로드할 때 메모를 추가하고 만료 시간을 선택할 수 있었으며, 그 결정은 최종적이었습니다. 이제 PicoShare가 더 유연해져 언제든 파일의 메타데이터와 만료일을 변경할 수 있습니다.
수정 화면을 추가한 뒤, 파일 삭제 과정을 더 실수하기 어렵게 만들 좋은 기회라는 생각이 들었습니다. 이전에는 파일 목록에서 삭제 버튼을 클릭하면 확인도, 되돌리기도 없이 파일이 사라졌습니다. 이제 파일을 삭제하려면 먼저 수정 화면으로 이동해 삭제를 클릭한 다음, 삭제를 확인해야 합니다.

실수로 파일을 삭제하는 일을 줄이기 위해 확인 대화상자를 추가했습니다.
WanderJest
2020년 초, 저는 근처의 라이브 코미디를 찾는 데 도움을 주는 사이트인 WanderJest를 만들고 있었습니다. 팬데믹 때문에 3월에 사이트 개발을 보류했습니다. 일상이 서서히 돌아오면서 주말과 저녁 시간에 WanderJest를 다시 살펴보고 있습니다.
PicoShare를 개발하며 인상적이었던 점 중 하나는 더 단순한 기술 스택이 개발 속도를 얼마나 높이는가였습니다.
| PicoShare | WanderJest | |
|---|---|---|
| 백엔드 | Go | Go |
| 프론트엔드 | Go 템플릿 + HTML5 | Vue 2 |
| 데이터 저장소 | SQLite + Litestream | Firestore |
Firestore는 스키마 변경이 너무 어려워 개발 속도를 떨어뜨립니다. 제가 아는 유일한 방법은 맞춤형 마이그레이션 코드를 작성해 프로덕션 서버에 배포하는 것입니다. SQLite에서는 프로덕션 데이터베이스를 내려받아 SQL 쿼리를 작성해 이것저것 다뤄본 다음 서버에 다시 올리면 됩니다.
현재 WanderJest에서 Vue를 Go 템플릿으로, Firestore를 SQLite로 교체하는 재구현 작업을 하고 있습니다.


현재 Vue 기반 WanderJest 사이트(왼쪽)와 Go HTML 템플릿으로 진행 중인 WanderJest 재구현(오른쪽)
Go로 프론트엔드를 작성하는 일은 예상보다 쉽습니다. 초기 개발 경험은 Vue만큼 좋지 않습니다. 조건부 렌더링이나 반응형 속성이 있으면 좋겠지만, 순수 JS에서는 제공되지 않습니다. 그래도 전반적으로 Go로 페이지를 렌더링하는 일은 훨씬 간단합니다.
Vue에서 페이지에 데이터를 렌더링하는 과정은 다음과 같았습니다.
- 백엔드가 데이터 저장소에서 데이터를 가져옵니다.
- 백엔드는 프론트엔드와 공유할 속성만 포함한 데이터 사본을 만듭니다.
- 백엔드는 데이터를 JSON으로 직렬화합니다.
- 프론트엔드는 백엔드에서 JSON 데이터를 가져옵니다.
- 프론트엔드는 백엔드에서 가져온 데이터를 바탕으로 페이지 요소를 채웁니다.
반면 Go 템플릿으로 페이지를 렌더링하는 과정은 두 단계뿐입니다.
- 백엔드가 데이터 저장소에서 데이터를 가져옵니다.
- 백엔드가 데이터 저장소의 데이터로 페이지 템플릿을 채웁니다.
Go로 프론트엔드를 렌더링하면 백엔드가 프론트엔드에 어떤 데이터를 노출할지 선택하고, 이를 어떻게 직렬화 및 역직렬화할지 정하고, 로컬 캐시를 어떻게 관리할지에 대한 모든 작업을 건너뛸 수 있습니다.
Vue 버전과 기능 동등성에 도달할 때까지 기다려야겠지만, 전체 코드 줄 수를 약 50% 줄일 수 있을 것으로 보입니다.
마무리
무엇을 완료했나?
- TinyPilot 웹사이트 리디자인을 완료했습니다.
- 새 TinyPilot 릴리스를 공개했습니다.
- 홈랩 NAS 서버에 관한 새 블로그 글을 게시했습니다.
- 디지털 마케팅 프리랜서를 채용했습니다.
배운 점
- Debian 패키지는 보기보다 쉽습니다.
- 프론트엔드 프레임워크 없이 사는 편이 더 쉽습니다.
다음 달 목표
- TinyPilot 설치용 독립 실행형 tarball을 만듭니다.
- TinyPilot 웹사이트 리디자인에 관한 장문의 블로그 글 초안을 완성합니다.
- 유료 검색 광고의 ROAS를 2.0으로 높입니다.
글을 무작위로 읽기