· 4분 읽기
1분기가 끝났다. GitHub 정리해보니 3개월 동안 3개 레포에서 152건 정도 작업했더라.
많이 만들긴 했다. 성과도 나오고 있고, D2C 퍼널 데이터도 잘 나오고 있다. 그런데 이 글을 쓰면서 계속 드는 생각이 있다. 'OKR 목표를 바라보고 달렸나?' 이 질문에는 자신 있게 답하기 어렵다.
1분기에서 가장 큰 작업은 D2C 서비스를 처음부터 만들어서 런칭한 거다.
1월 말부터 근무지 선택, 월급일 입력 같은 초기 플로우를 만들기 시작했고, 2월 초~중순에 온보딩, CMS 자동이체, 본인인증, 상환 페이지, 급여계좌 R2 업로드 같은 핵심 기능을 완성했다. 2월 중순부터는 QA에 집중하고 바로 오픈할 정도로 촉박한 일정이었다.
런칭 후에는 Amplitude, PostHog 기반으로 퍼널 데이터 수집하고, 전환율 떨어지는 구간 잡아서 개선하고, 성과 측정까지 진행했다. 데이터는 잘 나오고 있다.
원래 Tesseract로 OCR을 붙였는데 인식률이 좋지 않았다. 코드에프, 네이버 클로바 등 여러 솔루션을 찾아봤는데, 문득 '그냥 AI로 해볼까?' 싶어서 Claude Vision을 붙여봤다. 프롬프트에 따라 인식률이 꽤 높아서 그대로 진행했다. 여러 선택지 중에서 가장 합리적인 걸 골랐을 뿐인데, 결과적으로 잘 작동하고 있다.
3월에 마케팅 웹사이트를 전면 리뉴얼했다. 이번에는 작업 방식이 좀 달랐다.
Figma MCP를 연동해서 초기 디자인을 잡고, AI로 디테일을 빠르게 구현했다. 소개페이지, 도입문의, 고객센터를 새로 만들고 B2B/B2C 디자인 시스템을 통합했다. Claude 마케팅 스킬 기반으로 GEO, SEO 최적화도 진행해서 JSON-LD 구조화 데이터, 영문 번역까지 붙였다.
외부 CRM 툴을 쓰면 비용이 꽤 나온다. 그래서 세일즈팀이랑 같이 요구사항 정리하고 직접 만들어봤다. SQLite에서 PostgreSQL로 마이그레이션하고, JWT 인증, shadcn/ui 디자인 시스템, AI 리드 파인더까지 1주일 만에 구축했다.
해보면서 느낀 건, SaaS 서비스가 왜 어려운지 이해가 됐다는 거다. 원하는 기능부터 AI 활용, 리드 수집까지 — 팀의 요청사항에 맞춰 넣으면 빠르게 구축할 수 있다. 범용 SaaS보다 우리 워크플로우에 딱 맞는 도구가 나온다.
미팅룸 예약이 번거로워서 슬랙봇을 만들었다. Claude가 Playwright로 오렌지플래닛 사이트를 열어서 동작 방식이랑 API를 알아서 파악하고 구현했다. 나는 우리 사용성에 맞게 개선하는 정도만 했다. 크롤링부터 구현까지 2시간이면 됐다.
| 1월 | 2월 | 3월 | |
|---|---|---|---|
| 작업 건수 | 25 | 62 | 65 |
| 주요 테마 | 홈 리뉴얼, D2C 초기 구축 | D2C 완성·런칭, 설날 이벤트 | OCR, WWW 리뉴얼, CRM, 슬랙봇 |
1월에 25건으로 시작해서 3월에 65건까지 올라갔다. 1~2월에 D2C라는 큰 제품을 만들면서 기존 서비스도 유지하고, 3월에는 새 레포 2개까지 추가된 거다.
성과는 나오고 있다. D2C 퍼널 데이터도 잘 나오고, 데이터 수집하고 개선하는 사이클도 돌리고 있다. 돈이 되는 것도 알고, 방향이 맞다는 것도 안다.
다만 아쉬운 부분은, 이 모든 걸 하면서 '이전 분기에 세운 OKR 목표를 바라보고 달렸느냐'라는 거다. 솔직히 목표를 의식하면서 일하기보다는 요청이 들어오면 빠르게 쳐내고, 기능이 필요하면 바로 만들고, 런칭 날짜가 다가오면 QA를 밀어 넣는 식이었다. 경주마처럼 달렸다.
결과가 나쁜 건 아니다. 근데 OKR이라는 게 '결과가 나왔으니 됐다'가 아니라 '목표를 의식하면서 그 방향으로 움직였느냐'의 문제다. 매출 기반으로 어떻게 성장할지를 깊이 고민하면서 달렸어야 했는데, 그 부분이 부족했다.
이번 분기에 확실히 느낀 건, AI를 활용하는 방식이 많이 바뀌었다는 거다.
WWW 리뉴얼은 Figma MCP + Claude로 초기 디자인부터 SEO 최적화까지 빠르게 돌렸고, 슬랙봇은 Playwright로 사이트 분석부터 구현까지 AI가 처리했고, OCR도 결국 AI 솔루션이 제일 나았다. CRM도 AI 리드 파인더를 넣으면서 세일즈팀의 워크플로우 자체가 바뀌었다.
거기에 더해서, 개발 프로세스 자체를 AI로 자동화하는 시도도 했다. 핀테크 특성상 유저 분기가 많아서 다양한 케이스를 일일이 테스트하는 데 시간이 많이 들었는데, DB에 테스트 seed 유저 정보를 넣고 Playwright로 스크린샷을 캡처해서 비주얼 테스트를 자동화했다. e2e 테스트까지 확장하는 방향도 고민 중이다.
이 캡처 기반 위에 AI 에이전트팀이 개발자/디자이너 역할로 구현한 뒤, PM 역할의 에이전트가 11개 항목(정보 계층, 액션 배치, 시각적 일관성, 인지 부하 등)으로 채점하고, 기준 미달인 부분을 자동으로 수정하는 루프를 만들었다. 구현 → 캡처 → 채점 → 수정을 모든 항목이 통과할 때까지 반복하는 구조다. 다만 비주얼적으로는 AI가 한계가 있기 때문에, Mobbin에서 다른 앱의 레퍼런스를 참고해서 주요 영역의 디자인 퀄리티를 높이는 과정을 주입하는 방식도 시도하고 있다.
단순히 '코드 작성을 도와주는 도구'가 아니라, 기획부터 구현, 검수까지 전체 사이클에서 AI를 쓰는 방식이 자리잡아가고 있다. 2인 팀이라 리소스가 한정되어 있는데, 이런 자동화를 얼마나 잘 만드느냐가 곧 업무량을 줄이는 핵심이라는 걸 체감한 분기다.
2월 D2C 런칭 전 2주, 3월의 65건 — 지속 가능한 페이스는 아니었다. 빠르게 만드는 건 확인됐는데, 그 대가로 fix PR이 35%나 나왔다. 빨리 만들고 빨리 고치는 패턴이 습관이 되면 안 된다.
2인 팀에서 서로 빠르게 치고 나가다 보니 리뷰를 충분히 주고받지 못한 부분이 있다. 의도적으로 리뷰를 요청하고 받는 습관이 필요하다.
'이 기능이 정말 필요한가', '더 적은 코드로 같은 효과를 낼 수 있는가'를 5분만 고민하자.2022년에 카페 코딩 회고를 쓸 때는 '공부해서 발전해야 하는 순간'이라고 적었다.
4년이 지난 지금은 상황이 달라졌다. 그때는 기술 스택을 넓히는 게 성장이었다면, 지금은 만든 것이 비즈니스에 어떤 의미가 있는지 설명할 수 있는 것이 성장인 상황이다.
많이 만들었고, 성과도 나오고 있다. 다만 2분기에는 경주마가 아니라 방향을 보면서 달리는 사람이 되자.
Notion을 사용하면서 대시보드에 시계나 진행률 같은 위젯을 넣고 싶었는데, 기존 서비스들은 가입을 요구하거나 커스터마이징이 제한적이었다. 가입 없이 URL 쿼리 파라미터만으로 위젯을 커스터마이즈하고, Notion에 바로 임베드할 수 있는 서비스를 직접 만들기로 했다. 핵심 컨셉 “URL = Single Source of Truth” — 모든 위젯 설정이 URL 쿼리 파라미터에 저장된다. 별도의 가입이나 DB 저장 없이 URL 하나만 공유하면 누구든 같은 위젯을 볼 수 있다. 사용 흐름은 단순하다: 갤러리에서 위젯을 고른다 색상, 언어, 표시 옵션을 커스터마이즈한다 생성된 URL을 Notion의 /embed 블록에 붙여넣는다 기술 스택 Framework: Next.js 16 (App Router) Language: TypeScript 5 Styling: Tailwind CSS 4 Monorepo: Turborepo + pnpm Deploy: Vercel (한국 리전) i18n: 딕셔너리 패턴 (ko/en) 아키텍처 Turborepo 모노레포로 패키지를 분리하여 관리한다. apps/web — Next.js 앱 (랜딩, 갤러리, 커스터마이저, 임베드) packages/widget-core — 위젯 타입, 레지스트리, 파라미터 파싱, 공용 프리셋 packages/widgets — 개별 위젯 구현체 (6종) 위젯 추가 시 registerWidget()으로 등록하면 갤러리, 커스터마이저, 임베드 라우트가 자동 생성된다. 위젯 갤러리 현재 6종의 위젯을 제공한다....
카카오같이가치는 카카오가 운영하는 사회공헌 플랫폼으로, 좋아요와 댓글만으로도 기부에 참여할 수 있는 서비스다. 매일 접속해서 참여하면 좋겠지만, 수백 개에 달하는 기부 항목을 매번 수동으로 처리하는 것은 현실적으로 어렵다. 자동화 기술을 활용하면 꾸준하게 참여할 수 있겠다는 생각에 크롬 익스텐션으로 개발하게 됐다. 기술 스택 Extension: Chrome Manifest V3, Service Worker Frontend: React 18 Build: Vite 5 CORS 문제 해결 크롬 익스텐션 환경에서 카카오 API를 직접 호출하면 CORS 오류가 발생한다. Extension의 Origin이 chrome-extension://... 형태이기 때문에 카카오 서버에서 요청을 거부한다. 이를 해결하기 위해 declarativeNetRequest API를 활용하여 요청 헤더를 자동으로 교체했다. { "action": { "type": "modifyHeaders", "requestHeaders": [ { "header": "Origin", "operation": "set", "value": "https://together.kakao.com" } ] }, "condition": { "urlFilter": "*together*kakao.com*", "resourceTypes": ["xmlhttprequest"] } } rules.json을 통해 글로벌 규칙을 적용하니 fetch 호출 코드에서 헤더를 별도로 관리할 필요가 없어졌다. 자동화 로직 핵심 자동화는 Service Worker(background.js)에서 처리한다. 실행 흐름: 기부 목록 수집: 전체 페이지를 순회하며 진행 중인(STATUS_FUNDING) 항목 수집 중복 필터링: chrome.storage에 저장된 참여 기록과 비교하여 미참여...
강의 시청 화면에서 cmd + i 눌러서 개발자도구 오픈 console에 스레드에 있는 코드 입력 붙여넣기 안되는 분들은 allow pasting 수기 입력 후 진행 마지막 챕터 끝에 5초 정도 듣기 var no = $("#no").val(); var num = $("#num").val(); var log_num = location.search.match(/max_num=([\d]*)\&/)[1]; var cl_start_time = Math.floor(new Date().getTime()/1000) - 4020; var cl_start_check = $("#cl_start_check").val(); var user_id1 = location.search.match(/user_id1=([a-zA-Z0-9]*)$/)[1]; var allData = { no, num, log_num, cl_start_time, cl_start_check, user_id1, page_time: 147.146, }; var allData2 = { no, num, cur_page: Number(log_num), max_num: 0, user_id1, goyong_yn: "9" }; $.ajax({ url: "jindo_check_cl.php", type:'POST', data: allData }); $.ajax({ url: "timestamp.php", cache: false }); $.ajax({ url: "ajax.jumsu2_update_page.php", type:'POST', data: allData2, async: false }); setTimeout(() => { $('#frame')[0].src = $('#frame').attr('src').replace(/[\d]{2}\.html$/, `${pad(6, 2)}.html`) }, 500);