← 블로그로 돌아가기
Day 3

카카오톡 대화 생성기 + 유튜브 다운로더 랜딩페이지 개발

2026년 3월 28일 AM 10:50

devlogreacthtml2canvaslanding-page

오늘은 두 개 만들었다

3일차, 토요일. 쉬는 날이니까 욕심을 부렸습니다.

아침 10시 50분부터 자정까지. 챌린지 시작 이래 가장 오래 앉아있던 날입니다. 2일차에 아무것도 못 만든 죄책감도 한몫했습니다.

  1. 카카오톡 대화 생성기 — 가짜 카톡 대화 캡처를 웹에서 만드는 도구
  2. 유튜브 다운로더 랜딩 — 데스크탑 앱 소개 랜딩페이지

카카오톡 대화 생성기

왜 만들었나

"카톡 대화 캡처를 조작하고 싶다"는 게 아닙니다. 콘텐츠 제작자들이 예시 대화를 만들 때, 블로그에 카톡 형태의 UI를 넣고 싶을 때 쓸 수 있는 도구입니다.

기존에도 비슷한 서비스들이 있긴 한데, 대부분 디자인이 실제 카톡과 많이 다르거나, 기능이 부족했습니다. "진짜 카톡처럼 보이는" 캡처를 만드는 게 핵심이었습니다.

생각보다 까다로웠던 것들

Android vs iOS UI 차이

처음에는 "비슷하니까 하나로 합치자"고 생각했는데, 막상 만들어보니 상단바부터 다릅니다. Android는 뒤로가기 화살표 + 메뉴 버튼, iOS는 유니코드 네비게이션 아이콘. 이런 디테일을 놓치면 "가짜처럼 보이는 가짜"가 됩니다.

메시지 그룹핑 로직

실제 카톡에서는 같은 사람이 연속으로 보낸 메시지에 프로필을 매번 표시하지 않습니다. 또 같은 시간대에 보낸 메시지들은 마지막 메시지에만 시간이 표시됩니다. 이 두 가지 규칙을 코드로 구현하는 게 생각보다 까다로웠습니다.

900줄짜리 컴포넌트

결과적으로 page.tsx 하나가 900줄이 됐습니다. 바이브코딩이니까 컴포넌트 분리 같은 건 과감히 생략했습니다. 나중에 리팩토링하면 되지만, 솔직히 "동작하면 된다"는 마인드가 없었으면 3일차에 완성 못 했을 겁니다.

상태 관리는 useReducer 하나로 통합했습니다.

type Action =
  | { type: "ADD_MESSAGE" }
  | { type: "DELETE_MESSAGE"; index: number }
  | { type: "REORDER_MESSAGES"; from: number; to: number }
  | { type: "ADD_PARTICIPANT" }
  | { type: "REMOVE_PARTICIPANT"; id: string }
  | { type: "UPDATE_SETTINGS"; key: string; value: unknown };

메시지, 참여자, 설정을 한 곳에서 관리하니까 복잡도가 확 줄었습니다. useState를 7~8개 쓰는 것보다 훨씬 나았습니다.

이미지 추출에서 배운 것

html2canvas-pro로 미리보기 영역을 캡처해서 PNG로 내보냅니다.

const canvas = await html2canvas(element, {
  scale: 2,
  backgroundColor: null,
});

scale: 2는 레티나 디스플레이 대응입니다. 이걸 안 하면 캡처 이미지가 흐릿하게 나옵니다. 처음에 빠뜨렸다가 "왜 이렇게 화질이 낮지?" 하며 30분을 날렸습니다.


유튜브 다운로더 랜딩페이지

페인포인트 마케팅

유튜브 다운로더를 검색하면 나오는 사이트들, 다들 한 번쯤 써보셨을 겁니다.

이 불편함을 정면으로 공략했습니다. "광고 0개. 낚시 0개. 진짜 다운로드만."

인터랙티브 데모가 핵심

말로 설명하는 것보다 직접 보여주는 게 낫습니다. AppMock 컴포넌트로 앱 사용 과정을 그대로 시뮬레이션했습니다.

5단계 상태 머신으로 자동 전환됩니다. 사용자가 스크롤하면서 "아, 이런 식으로 쓰는 거구나"를 느낄 수 있게 했습니다. 스크린샷 한 장 넣는 것보다 인터랙티브 데모가 설득력이 훨씬 강합니다.


3일차 회고

2일차에 아무것도 못 만든 뒤라서, 오늘은 "만회해야 한다"는 마음이 컸습니다. 결과적으로 두 개를 만들었고, 둘 다 나름 완성도가 있습니다.

다만 토요일 하루를 통째로 쓴 건 지속 가능하지 않습니다. 평일에 짧게 집중하는 패턴을 찾아야 합니다. 챌린지는 마라톤이지 단거리 달리기가 아니니까요.

오늘의 교훈: 2일차의 실패가 3일차의 동기부여가 될 수 있다. 중요한 건 다음 날 다시 앉는 것.