교육 제품: 1개월 차
한 줄 요약
블로깅 강의를 다시 시작합니다.
하이라이트
- 2020년에 만들었던 블로깅 강의를 다시 정비하고 있습니다.
- htmx는 꽤 쓸 만하지만 기대했던 모든 것을 충족하지는 못합니다.
- 예전에 운영하던 키토 식단 사이트 Is It Keto의 인수자를 찾고 있습니다.
Hit the Front Page 다시 시작하기
2020년에 저는 “Hit the Front Page of Hacker News”라는 블로깅 관련 동영상 강의를 만들었습니다. 강의 자료에 자부심이 있었고 수강생들로부터 긍정적인 피드백도 들었지만, 마땅히 기울여야 할 관심을 기울이지 못했다는 느낌이 들었습니다.
강의를 출시했을 당시 TinyPilot이 빠르게 성장하고 있어 강의를 마케팅하거나 자료를 개선할 시간이 없었습니다.
지난 블로그 글에서 앞으로 어떤 일을 하면 좋을지 독자들에게 설문을 했습니다. 가르치는 모습을 보고 싶다고 답한 분들의 결과는 다음과 같았습니다.

지난 블로그 글에서 진행한 독자 설문 응답 결과
데이터를 해석하는 방법은 여러 가지가 있겠지만, 제가 내린 결론은 많은 분이 제가 글쓰기 기법을 가르쳐 주길 특히 기대한다는 것이었습니다. 의도적 수련(deliberate practice)이 상위권에 오른 것도 조금 의외였는데, 열기는 약간 덜하긴 했습니다.
기존 강의가 이미 거의 완성된 상태였고, 집계 방식에 따라 2~3위를 차지했기 때문에 자료의 먼지를 털어내고 2024년 버전으로 업데이트해 다시 공개하기로 했습니다.
파일럿 프로그램 수강생 모집
Rob Fitzpatrick의 책 Write Useful Books는 제가 교육용 제품을 대하는 방식에 큰 영향을 주었습니다. 그는 책이나 동영상 강의를 내기 전에 반드시 해당 주제를 라이브로 먼저 가르쳐 보고, 실제 수강생의 피드백을 바탕으로 개선해야 한다고 주장합니다.
저희 부부는 8월 말에 첫 아이 출산을 앞두고 있어, 출산 후에는 몇 달간 가족과 시간을 보내며 잠시 자리를 비울 계획이었습니다. 이 강의를 고민하던 시점에는 출산 예정일까지 약 10주 정도 남아 있었고, 강의 자체가 6주 과정이라 여유가 많지 않았습니다.
강의에 대한 간단한 소개 글을 쓰고 블로그 구독자들에게 메일로 보냈습니다. 관심 있는 분은 짧은 신청서를 작성해 달라고 부탁했고, 신청서를 제출한 분들께는 작성 내용을 바탕으로 개별 답변을 드리고 결제 링크를 보내 자리를 확정했습니다.
결과는 다음과 같았습니다.
- 1,944명의 구독자가 강의 안내 메일을 받았습니다.
- 11명이 관심을 표하며 설문(신청서)을 작성했습니다.
- 7명이 강의를 결제했습니다.
- 신청서를 냈지만 등록하지 않은 4명 중 3명은 시간대가 맞지 않아서였습니다.
화상 플랫폼 찾기
화상 통화를 위한 Zoom의 현실적인 대안이 거의 없다는 사실에 놀랐습니다. Zoom이 보안을 둘러싸고 거짓말을 한 사실이 드러난 이후로 계속 피해 왔지만, 라이브 강의 시장에서는 사실상 유일한 선택지인 듯합니다.
지난 몇 년간 업무 회의에는 Jitsi Meet를 써 왔고 대체로 만족했지만, Zoom 회의에 참여할 때 품질이 더 좋다는 것을 느꼈습니다. Jitsi Meet의 유료 요금제를 찾아봤지만, 모든 유료 옵션에 “문의하기”로만 표시되어 있어 아마도 월 최소 1,000달러는 넘을 것으로 보였습니다.
그래서 Jitsi도 쓸 만은 하지만 다소 투박합니다. 녹화 기능을 지원하지 않아 다음과 같은 편법을 쓰고 있습니다.
- 노트북에서 수업 화상 통화를 호스팅합니다.
- 데스크톱에서도 같은 통화에 참여합니다.
- 데스크톱에서 일반 화면 녹화 프로그램으로 통화를 녹화합니다.
- 녹화한 영상을 PicoShare에 업로드합니다.
- PicoShare 링크를 수강생들에게 메일로 보냅니다.
원하는 것보다 복잡하지만, 발표 슬라이드가 노트북 화면을 가득 채워도 데스크톱 모니터로 모두의 얼굴을 볼 수 있다는 부수적인 장점은 있습니다.
Jitsi Meet보다 더 나은 대안을 알고 계시면 알려 주세요.
Hacker News에서 방향을 틀어야 할까?
강의를 신청한 학생 중 절반 정도는 Hacker News 자체에는 큰 관심이 없다고 했습니다. 그저 제 글을 좋아해서 제 글쓰기 과정을 더 배우고 싶어, Hacker News에 초점이 맞춰져 있음에도 불구하고 등록한 경우였습니다.
설문 결과를 다시 보면, 블로깅 자체보다 글쓰기 전반에 대한 관심이 더 높아 보입니다. 그리고 Hacker News를 직접 요청한 사람은 아무도 없었습니다.
그래서 Hacker News에서 벗어나 더 일반적인 주제로 방향을 틀어야 할지 고민하고 있습니다.
Hacker News를 떠나면 저만의 강점을 잃을까 봐 걱정됩니다. 블로깅이나 글쓰기를 가르치는 사람은 셀 수 없이 많아 그 속에서 두드러지기 어렵다고 느낍니다. 반면 Hacker News를 전문적으로 가르친다면, 그 분야를 다루는 사람이 아무도 없으니 제가 세계에서 가장 잘 가르치는 사람이 될 수 있습니다.
또 다른 문제는 제 블로깅 성공 사례 대부분이 Hacker News와 관련되어 있다는 점입니다. 개인 블로거 중에서는 Hacker News에서 이례적인 성과를 냈지만, 더 일반적인 글쓰기 강의를 한다면 내세울 만한 이력이 그만큼 강하지 않습니다. 블로그로 수익을 내고 있는 것도 아니고, 자랑할 만한 대규모 구독자를 보유한 것도 아닙니다.
한편으로는 제 강의를 구매한 분들 대부분이 저를 먼저 알고 난 뒤에 강의를 찾은 분들이라고 생각합니다. 애초에 ‘Hacker News 최고의 전문가’를 검색해서 들어온 분들은 아닐 가능성이 큽니다.
어쩌면 결론은 다른 수많은 경쟁자와의 경쟁을 너무 걱정하지 않아도 된다는 것일지도 모릅니다. 어차피 제 강의로 오는 경로는 저를 통해서이거나 입소문을 통해서일 가능성이 크기 때문입니다.
원래의 Hacker News 포맷으로 강의가 95% 정도 완성된 상태라, 이번 과정은 Hacker News에 초점을 맞춰 그대로 출시할 예정입니다. 이후에 자료를 다듬어 더 일반적인 강의로 확장할 생각입니다.
htmx 배우기
지난 2년간 htmx가 점점 더 자주 눈에 띄었습니다. 친구인 Cory Zue가 htmx를 사용하는 것을 보고 관심이 생겼습니다.
오랫동안 가장 큰 걸림돌은 htmx의 존재 이유를 이해하지 못했다는 점이었습니다.
htmx 랜딩 페이지의 첫 문장 중 하나는 “왜 <a> & <form>만 HTTP 요청을 할 수 있어야 할까?”입니다. 이 문장을 읽었을 때 저는 ‘그러면 좋긴 하겠지만, 자바스크립트면 어떤 HTML 요소든 어떤 요청이든 보낼 수 있는데, 몇 줄의 자바스크립트를 아끼자고 완전히 새로운 방법론을 도입해야 할까?’라는 생각이 들었습니다.
결국 htmx가 와닿게 된 계기는 책 Hypermedia Systems였습니다. htmx 저자들이 직접 쓴 책으로, htmx의 동기와 여러 활용 시나리오를 자세히 설명합니다.
4년 전의 저에게 htmx를 소개해야 한다면 이렇게 말하고 싶습니다.
과거의 나에게 하는 htmx 소개
웹사이트 프로그래밍을 처음 배울 때 이렇게 HTML을 작성하던 걸 기억하시나요?
<form action="/users" method="POST">
<input name="first-name" placeholder="First name" />
<input name="last-name" placeholder="Last name" />
<input type="submit" value="Add user" />
</form>오늘날에는 이렇게 작성하지 않을 겁니다. 사용자가 폼을 제출했을 때 페이지 전체를 다시 불러오는 것을 피하고 싶기 때문입니다. 전체 페이지 새로고침은 느리고 사용자를 혼란스럽게 하며, 특히 “User added successfully”라는 메시지만 보여주려는 경우에는 더욱 그렇습니다. 그리고 서버가 입력을 거부했을 때 사용자가 입력한 내용을 모두 날려버리고 싶지도 않을 겁니다.
그래서 대신 자바스크립트를 이용해 이렇게 작성하게 됩니다.
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("form").addEventListener("submit", (evt) => {
evt.preventDefault(); // Block default submit.
fetch(`/users`, {
method: "POST",
credentials: "include",
headers: {
Accept: "application/json",
},
body: JSON.stringify({
firstName: document.querySelector("[name='first-name']"),
lastName: document.querySelector("[name='last-name']"),
}),
})
.then((response) => {
if (response.ok) {
return response.json();
}
// TODO: Handle errors too.
})
.then((result) => {
// TODO: Handle success.
});
});
});자바스크립트 양이 엄청 많은 건 아니지만, 폼이 필요할 때마다 같은 코드를 반복해서 작성하게 됩니다. 중복을 리팩터링할 수는 있지만, 그러면 UI 로직이 여러 파일에 흩어지게 됩니다. 서버와의 모든 클라이언트 상호작용마다 불필요한 마찰이 생기는 셈입니다.
아니면 React나 Vue 같은 무거운 프레임워크를 도입하게 되는데, 그러면 내 코드와 브라우저에 실제로 나타나는 것 사이에 수많은 자바스크립트 추상화 계층이 생기게 됩니다.
htmx가 약속하는 것은 웹 페이지를 처음 만들 때의 그 단순함으로 돌아가는 것입니다. HTML을 작성한 뒤 모든 로직을 React나 직접 작성한 이벤트 핸들러에 떠넘기는 대신, htmx를 앱에 통합하고 폼을 이렇게 작성하는 겁니다.
<form hx-post="/users" hx-target="this">
<input name="first-name" placeholder="First name" />
<input name="last-name" placeholder="Last name" />
<input type="submit" value="Add user" />
</form>그러면 별도의 커스텀 자바스크립트를 작성하지 않아도 htmx가 알아서 모든 것을 동작하게 해 줍니다.
지금까지의 htmx 사용 경험
htmx를 시험해 보기 위해 다시 작성하며 ScreenJournal의 일부를 htmx로 바꾸고 있습니다. ScreenJournal은 제가 만든 오픈소스 영화 리뷰 앱으로, 영화판 Goodreads라고 생각하면 됩니다. 혹은 오픈소스이자 못생긴 letterboxd 같은 서비스입니다.

ScreenJournal은 영화를 리뷰하는 취미용 웹 앱입니다.
다시 작성한 좋은 예 중 하나는 알림 설정 페이지를 htmx로 재구현한 것입니다. 사용자가 받고 싶은 이메일을 지정할 수 있는 페이지입니다.

ScreenJournal의 알림 설정 페이지
알림 페이지는 다음 기능들을 위해 꽤 많은 커스텀 자바스크립트가 필요했습니다.
fetch로 페이지를 새로고침하지 않고 폼 내용을 제출하기- 요청이 진행되는 동안 폼 입력 비활성화하기
- 요청 진행 중 상태 스피너 표시하기
- 요청이 실패하면 오류 메시지 표시하기
바닐라 자바스크립트에서 htmx로 전환한 결과는 다음과 같습니다.
전체 코드 줄 수가 줄었고, 특히 자바스크립트 코드가 크게 줄었습니다. 로직이 프런트엔드에서 백엔드로 이동했는데, 저는 백엔드 코드가 UI 코드보다 테스트하기 쉽다고 느끼기 때문에 이런 방식을 선호합니다.
htmx를 사용하면서 느낀 몇 가지 소감을 정리하면 다음과 같습니다.
htmx는 추상화 계층을 추가하지만 직관적이다
- Vue나 Angular를 쓸 때는 내 코드가 어떻게 웹 앱으로 변환되는지 전혀 감을 잡을 수 없었습니다.
- htmx는 동작 방식이 충분히 직관적이어서, 작동하는 모습을 보고 나면 직접 다시 구현할 수도 있을 것 같습니다.
htmx의 오류 처리는 아쉽다
- htmx의 모델은 서버에 요청을 보내고 서버의 응답을 페이지 내 하나의 요소에 넣는다고 가정합니다.
- 문제는 성공했을 때는 HTML 폼을 교체하고 싶지만, 오류가 발생했을 때는 폼은 그대로 두고 폼 아래에 오류를 표시하고 싶다는 점입니다.
- htmx가 제시하는 해법은 서버가 사용자의 입력을 모두 포함해 HTML 폼을 다시 렌더링하라는 것이지만, 이미 존재하던 것을 처음부터 다시 렌더링하는 방식이라 마음에 들지 않고, XSS 취약점의 공격 표면도 넓어집니다.
- 직접 이벤트 핸들러를 작성하면 우회할 수는 있지만, 그렇게 되면 프레임워크와 싸우는 느낌이 듭니다.
htmx는 콘텐츠 보안 정책(CSP)을 약화시킨다
- 저는 교차 사이트 스크립팅(XSS)을 막는 최후의 방어선으로 CSP를 선호합니다.
- htmx는 대부분 CSP와 호환되지만, htmx가 하는 일이 워낙 많다 보니 공격자가 커스텀 HTML을 작성할 수 있게 되는 것은 사실상 임의의 자바스크립트를 작성할 수 있게 되는 것과 같습니다.
- 예시
<form action=/delete-account" method="post" onload="this.submit()">- CSP가 이 코드의 실행을 차단합니다.
<form hx-post="/delete-account" hx-trigger="load">- CSP는 이와 동등한 이 코드의 실행을 허용합니다.
- htmx를 사용해도 안전한 애플리케이션을 만들 수는 있지만, XSS에 대한 신뢰할 만한 최후의 방어선으로서 CSP의 역할은 약해집니다.
Is It Keto 매각
이번 주에 확인해 보니 Amazon이 어느 시점에 제휴 링크 방식을 변경하면서 Is It Keto에 있는 제휴 링크의 90%가 깨진 상태였습니다. 사이트는 여전히 Google AdSense로 수익을 내고 있지만, 더 이상 유지보수할 시간이 없습니다.
사이트를 인수할 분을 찾고 있으며, 다른 인디 창업자나 예비 창업자로부터 멋진 제안을 받는다면 시세보다 낮은 가격에 판매할 생각입니다.
마무리
무엇을 해냈나?
- 소수 정예 코호트와 함께 블로깅 강의를 시작했습니다.
- ScreenJournal의 많은 부분을 htmx로 포팅하며 htmx를 배웠습니다.
- 강의의 첫 보너스 콘텐츠를 녹화했습니다.
배운 점
- 생각했던 것만큼 제 강의가 Hacker News라는 각도에 묶여 있지 않다는 것을 알게 되었습니다.
- 사람들이 제 강의를 듣는다면 Hacker News에서의 성과 때문이 아니라 제 글을 좋아하기 때문일 가능성이 크므로, 그런 고객이 어떤 사람인지 더 고민해야겠습니다.
다음 달 목표
- 강의 중 4개 레슨의 공개용 버전을 녹화하기
- 새 버전의 강의 판매 시작하기
도움 요청
화상 통화 플랫폼
다음 조건을 만족하는 화상 통화 플랫폼에 대해 추천할 만한 것이 있으면 알려 주세요.
- 필수: 90분 통화에 최대 10명 참여 지원
- 필수: 참가자가 새 계정을 만들거나 기기에 소프트웨어를 설치하지 않고도 통화 참여 가능
- 필수: 월 80달러 이하
- 있으면 좋음: 화상 통화 녹화 기능
강의 플랫폼 경험
Maven이나 Udacity 같은 강의 플랫폼에서 강사 또는 수강생으로 경험해 보신 적이 있다면 알려 주세요.
글을 무작위로 읽기