TinyPilot: Month 23

Michael Lynch

TinyPilot: 23개월 차

원문은 Michael Lynch님이 에 게재했습니다. 이 블로그 구독하기

한 줄 요약

8개월간의 리디자인이 마침내 끝났다!

하이라이트

  • TinyPilot 웹사이트 리디자인이 마침내 완료됐다.
  • Debian 패키지를 만드는 법을 배웠는데, 놀랍도록 간단하다.
  • Vue를 비롯한 프론트엔드 프레임워크를 포기했다.

목표 달성 점수

매달 초에 달성하고 싶은 목표를 정한다. 이번 달에는 목표를 얼마나 달성했을까?

TinyPilot으로 홈랩 NAS 서버 구축에 대한 블로그 글과 영상 공개

회고나 연말 리뷰가 아닌 블로그 글을 쓴 건 1년여 만에 처음이었다. 레딧에서는 반응이 미지근했지만, 해커 뉴스에서는 2위까지 올랐다.

이 글 덕분에 많은 방문자가 TinyPilot 웹사이트로 유입됐고, 월간 순 방문자 수가 1만 4천 명에 달했다. 역대 최고 기록으로 이전 기록보다 30% 높은 수치다. 글 작성과 영상 제작에 약 45시간을 들였는데, 그만한 노력을 들일 가치가 있는 성과였다.

TinyPilot 웹사이트 리디자인 완료

  • 결과: 마침내 완료!
  • 점수: A

리디자인이 마침내 끝났다. 지난 4개월 동안 매달 이번 달이면 끝날 것 같았지만, 매번 무언가가 생겨 지연됐다. 이제 공식적으로 완료됐다.

마케팅 에이전시 또는 프리랜서 고용

  • 결과: 6월 초에 프리랜서를 고용했다
  • 점수: B

함께할 만해 보이는 에이전시를 찾았지만, 어딘가 꺼림칙한 느낌이 들었다. 3개월 계약으로 가격에 합의했는데, 내가 합의한 뒤에 에이전시 쪽에서 최소 5개월 계약으로 바꾸자고 했다. 큰 경고 신호였다. 계속 조율해 보려 했지만 제안들이 모두 석연치 않아 결국 논의를 중단했다.

다행히 전기 공학 파트너 회사에서 디지털 마케팅 프리랜서를 추천해 줬다. 첫 통화부터 지금까지 이야기해 본 누구보다 잘 맞았고, 바로 고용했다.

TinyPilot 통계

지표2022년 4월2022년 5월변화
순 방문자5,26814,296+9,028 (+171%)
총 페이지뷰11,97424,131+12,157 (+102%)
판매 수익$43,771.00$54,844.20+$11,073.20 (+25%)
기업 구독$47.75$47.750
로열티$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% 증가했다.

대부분의 방문자는 해커 뉴스에서 유입됐지만 판매에는 큰 영향을 미치지 않은 것 같다. 해커 뉴스에 글이 오르기 전에도 판매는 이미 4월 대비 약 25% 증가할 추세였다. 결과는 지연되어 나타날 수도 있다. 6월 초 실적이 이례적으로 강하게 시작되고 있기 때문이다.

TinyPilot 웹사이트 리디자인

휴, 리디자인 말이다.

뭐라고 말해야 할까?

몇 달째 질질 끌어왔고, 끝은 항상 몇 주 앞인 것처럼 느껴졌다.

이 프로젝트 초기에 디자이너와 에이전시들을 인터뷰할 때, 두 달 정도 걸리는 리디자인에 8,000~15,000달러를 쓸 생각이라고 말했다. 판매에 실질적인 영향을 주는지 확인하기도 전에 6개월과 4만 달러를 써야 하는 프로젝트는 절대 원하지 않는다고 분명히 했다.

결국 프로젝트는 8개월이 걸렸고 4만 6천 달러가 들었다. 피하고 싶었던 함정에 정확히 빠진 셈이다.

이 경험에 대해서는 더 긴 블로그 글을 쓸 예정이지만, 주요 실수는 다음과 같다:

  • 범위가 너무 넓었다: 범위를 작게 유지해서 리브랜딩부터 시작했어야 했는데, 에이전시가 본격적인 리디자인으로 확장하도록 내버려뒀다.
  • 작업 시간 보고가 너무 느렸다: 에이전시가 2주 지연이 아니라 발생 즉시 청구 시간을 보고하는 시스템을 고집했어야 했다. 작업에 얼마나 시간이 걸리는지 알 수 없으면, 예상보다 비용이 많이 들 때 범위를 조정할 수 없다.
  • 일정에 더 많은 투명성이 필요했다: 프로젝트가 얼마나 오래 끌릴지 놀라지 않도록 타임라인에 대한 소통을 더 요구했어야 했다.
  • 관리 시간이 부족했다: 한 달에 40시간 일하는 에이전시가 한 달에 40시간 일하는 개인 프리랜서와 비슷한 관리 오버헤드가 들 거라고 가정했다. 에이전시는 더 많은 사람이 관여되고, 사람이 많다는 것은 더 많은 관리가 필요하다는 뜻이다.

그래도 결과를 한번 보자. 이 프로젝트에서는 결제 과정의 세 페이지, 즉 랜딩 페이지, 제품 페이지, 장바구니 페이지를 리디자인했다:

기존 랜딩 페이지 스크린샷새 랜딩 페이지 스크린샷

리디자인 전후 랜딩 페이지

기존 Voyager 2 제품 페이지 스크린샷새 Voyager 2 제품 페이지 스크린샷

리디자인 전후 제품 페이지

기존 장바구니 페이지 스크린샷새 장바구니 페이지 스크린샷

리디자인 전후 장바구니 페이지

비용을 빼고 보면 결과에는 만족한다. 새 디자인이 이전보다 명백히 더 낫다고 생각한다. 새로운 로고와 이미지가 프로젝트를 더 전문적이고 독특하게 보이게 한다.

그러니 새 디자인이 더 낫긴 한데, 4만 6천 달러만큼 더 나은가?

시간을 되돌릴 수 있다면 절대 그 많은 돈과 시간을 리디자인에 쏟지 않았을 것이다. 그래도 아직 본전을 뽑을 가능성은 있다.

고정 비용을 제외하면 TinyPilot 판매 수익의 70%가 이익이다. 즉 리디자인이 본전을 찾으려면 6만 6천 달러의 추가 판매를 만들어내야 한다. 판매가 10% 증가한다면 월평균 5만 달러에서 5만 5천 달러로 오르게 된다. 그러면 약 1년 만에 투자금을 회수하게 된다. 더 나은 마케팅이 사이트에 더 많은 고객을 끌어들인다면 더 빨리 본전을 찾을 수 있다.

Debian 패키지는 쉽다

TinyPilot에서 내린 특이한 설계 결정 중 하나는 설치 및 업데이트 메커니즘이다. 우리는 Ansible을 쓰고 있는데, 이는 DevOps 엔지니어가 대규모로 시스템을 프로비저닝하기 위해 설계된 도구다. 나는 TinyPilot의 첫 프로토타입을 Raspberry Pi에 프로비저닝하기 위해 Ansible을 사용했다. 그 방식이 잘 작동해서 그대로 유지했다.

Linux에 소프트웨어를 설치하는 더 나은 방법이 있다는 건 알고 있었지만 경험이 없었다. TinyPilot은 Raspberry Pi의 하드웨어 기능을 설정하는 데 특이한 요구사항이 있어서, 표준 설치 도구를 그런 요구사항에 맞게 적용하는 과정이 두려웠다. 대신 제대로 동작하고 별 문제도 일으키지 않던 Ansible을 계속 썼다. 느리긴 해서 몇 초면 될 설치가 2분이 걸렸지만, 그 정도는 감수할 만했다.

2년이 지나자 Ansible의 한계에 다다르고 있다. 설치 과정이 너무 복잡해졌고 업데이트에는 5분 이상이 걸린다.

Debian 패키지(예: apt-get)를 예전에도 고려했지만 Debian 패키징 도구에 대한 부정적인 이야기를 들은 적이 있었다. 거기에 저장소 서버, 키 페어, 패키지 서명 과정까지? 기본적인 것만 갖추는 데도 엄청난 노력이 들고, 우리가 필요한 작업을 하는 것도 엄청나게 번거로울 것 같았다.

실험 삼아 Debian 패키지를 만들어 보니 생각보다 훨씬 쉬웠다. Debian 패키지는 특정 폴더 구조와 몇 개의 특수 파일을 가진 tarball에 불과하다. 처음으로 동작하는 .deb 파일을 만드는 데 한 시간 정도 걸렸다.

그리고 저장소 서버와 키 페어는? 알고 보니 선택 사항이었다. 저장소가 전혀 없어도 .deb 패키지 파일을 직접 배포할 수 있다.

debhelper는 Debian 패키지를 만들기 위한 공식 도구인데, 듣던 대로 정말 헷갈리고 어려웠지만 꼭 필요한 건 아니었다. debhelper를 건너뛰고 Debian 메타데이터 파일을 직접 만드는 편이 더 쉽다는 걸 알게 됐다.

더 좋은 점은 Ansible에서 Debian 패키지로 한 번에 아찔하게 갈아탈 필요가 없다는 것이다. 우리 속도에 맞춰 로직을 조금씩 Ansible에서 Debian 패키지로 옮기면 된다.

우리의 첫 Debian 패키지는 오픈소스 WebRTC 서버인 Janus용이다. 예전에는 각 기기에서 애플리케이션을 소스부터 컴파일했는데, 약 30분이 걸렸다. 새로운 Debian 패키지는 몇 초 만에 설치된다. 그리고 32비트 ARM 바이너리가 필요함에도 Docker의 QEMU 통합을 이용해 x64 클라우드 서버에서 Debian 패키지를 빌드할 수 있다. 코드를 컴파일하고 패키징하는 모든 코드는 오픈소스로 공개되어 있다.

Debian 패키지에 대해 공부할 때 도움이 됐던 자료는 다음과 같다:

검색 광고가 정체되고 있다

지난번에 계산했을 때 Google 검색 광고는 엄청나게 좋아 보였다. Google Ads에 1달러를 쓸 때마다 0.69달러의 이익을 내고 있었다. 이제 시간이 더 지나고 데이터가 더 쌓이자 그림이 덜 장밋빛이다.

지난달 수치를 계산할 때 4월과 5월 첫 주를 포함했다. 그 첫 주가 이상치였던 것으로 드러나, 월별로 나누어 보면 수익성이 약해진다:

지표4월5월
광고비$804.12$4,283.71
노출 수5,270239,498
클릭 수3513,327
클릭률 (CTR)6.6%1.4%
클릭당 비용 (CPC)$2.29$1.29
전환으로 인한 수익$1,314.91$7,649.60
광고 대비 수익 (ROAS)1.631.79

내 수익의 약 30%는 하드웨어와 인건비로 나가기 때문에 ROAS가 1.43 정도면 대략 손익분기점이다(1.43 - 30% = 1.0). 그 이상이면 이익이다. 1.79라면 광고에 1달러를 쓸 때마다 0.26달러를 버는 셈이니 계속 진행할 예정이다.

TinyPilot의 새로운 디지털 마케팅 컨설턴트가 내 Google Ads 계정을 검토하고 가치가 낮은 키워드에 과도하게 지출하고 있는 여러 지점을 찾아냈다. 그래서 향후 몇 달 안에 이 수치를 개선할 수 있을 것이다.

사이드 프로젝트

PicoShare

PicoShare는 내가 3월에 공개한 오픈소스 도구로, 이메일로 보내기엔 너무 큰 파일을 쉽게 공유할 수 있게 해준다.

5월에는 파일을 업로드한 뒤 메타데이터를 수정하는 기능을 추가했다:

PicoShare의 메타데이터 편집 화면 스크린샷

5월에 PicoShare에 파일 메타데이터 편집 기능을 추가했다.

원래는 파일을 업로드할 때 메모를 추가하고 만료 시간을 정할 수 있었고, 그 결정은 번복할 수 없었다. 이제 PicoShare는 더 유연해져서 언제든지 파일의 메타데이터와 만료일을 변경할 수 있다.

편집 화면을 추가한 뒤, 파일을 삭제하는 과정을 더 안전하게 만들 좋은 기회라는 걸 깨달았다. 이전에는 파일 목록에서 삭제 버튼을 클릭하면 확인도, 되돌리기도 없이 파일이 바로 사라졌다. 이제 파일을 삭제하려면 먼저 편집 화면으로 들어가 삭제를 클릭한 뒤 삭제를 확인해야 한다:

PicoShare의 삭제 확인 대화상자 스크린샷

실수로 파일을 삭제하는 일을 줄이기 위해 확인 대화상자를 추가했다.

WanderJest

2020년 초, 나는 사람들이 주변의 라이브 코미디 공연을 찾을 수 있도록 돕는 사이트인 WanderJest를 만들고 있었다. 팬데믹 때문에 3월에 사이트를 중단했다. 일상이 서서히 정상으로 돌아오면서 주말과 저녁 시간에 WanderJest를 다시 들여다보고 있다.

PicoShare를 개발하면서 특히 인상 깊었던 점은 기술 스택을 단순하게 할수록 개발 속도가 얼마나 빨라지는지였다:

PicoShareWanderJest
백엔드GoGo
프론트엔드Go templates + HTML5Vue 2
데이터 저장소SQLite + LitestreamFirestore

Firestore는 스키마 변경이 너무 어려워 속도를 늦춘다. 내가 아는 유일한 방법은 커스텀 마이그레이션 코드를 작성해 프로덕션 서버에 배포하는 것이다. SQLite라면 프로덕션 데이터베이스를 그냥 다운로드해 SQL 쿼리로 만지작거린 뒤 서버에 다시 올리면 된다.

현재 WanderJest를 Vue 대신 Go 템플릿을, Firestore 대신 SQLite를 쓰도록 다시 구현하는 중이다.

WanderJest 라이브 사이트 스크린샷Go 기반의 새로운 WanderJest 사이트 스크린샷

현재 Vue 기반 WanderJest 사이트(왼쪽)와 Go HTML 템플릿으로 재구현 중인 WanderJest(오른쪽)

Go로 프론트엔드를 작성하는 건 생각보다 쉽다. 초기 경험은 Vue만큼 좋지 않다. 조건부 렌더링이나 반응형 속성이 있으면 좋겠지만 바닐라 JS에서는 그런 걸 얻을 수 없다. 하지만 전체적으로 Go로 페이지를 렌더링하는 것이 훨씬 더 간단하다.

Vue로 페이지에 데이터를 렌더링하는 과정은 다음과 같았다:

  1. 백엔드가 데이터 저장소에서 데이터를 가져온다.
  2. 백엔드가 프론트엔드와 공유할 속성만 담은 데이터 사본을 만든다.
  3. 백엔드가 데이터를 JSON으로 직렬화한다.
  4. 프론트엔드가 백엔드에서 JSON 데이터를 가져온다.
  5. 프론트엔드가 백엔드에서 가져온 데이터를 기반으로 페이지 요소를 채운다.

반면 Go 템플릿으로 페이지를 렌더링하는 과정은 단 두 단계뿐이다:

  1. 백엔드가 데이터 저장소에서 데이터를 가져온다.
  2. 백엔드가 데이터 저장소에서 가져온 데이터로 페이지 템플릿을 채운다.

Go에서 프론트엔드를 렌더링하면, 백엔드가 프론트엔드에 어떤 데이터를 노출할지 정하고, 어떻게 직렬화·역직렬화하며, 로컬 캐시를 어떻게 관리할지 고민하는 모든 작업을 건너뛸 수 있다.

Vue 버전과 기능이 동일해질 때까지 기다려봐야겠지만, 전체 코드 줄 수를 약 50% 줄일 수 있을 것으로 예상한다.

마무리

무엇을 해냈나?

  • TinyPilot 웹사이트 리디자인을 완료했다.
  • 새로운 TinyPilot 릴리스를 공개했다.
  • 홈랩 NAS 서버에 대한 새로운 블로그 글을 공개했다.
  • 디지털 마케팅 프리랜서를 고용했다.

배운 점

  • Debian 패키지는 생각보다 쉽다.
  • 프론트엔드 프레임워크 없이 사는 게 더 편하다.

다음 달 목표

  • TinyPilot 설치용 자체 완결형 tarball을 만든다.
  • TinyPilot 웹사이트 리디자인에 대한 장문의 블로그 글 초안을 완성한다.
  • 유료 검색 광고의 ROAS를 2.0으로 높인다.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글