2026년 02월 22일
카카오같이가치는 카카오가 운영하는 사회공헌 플랫폼으로, 좋아요와 댓글만으로도 기부에 참여할 수 있는 서비스다.
매일 접속해서 참여하면 좋겠지만, 수백 개에 달하는 기부 항목을 매번 수동으로 처리하는 것은 현실적으로 어렵다.
자동화 기술을 활용하면 꾸준하게 참여할 수 있겠다는 생각에 크롬 익스텐션으로 개발하게 됐다.
크롬 익스텐션 환경에서 카카오 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에 저장된 참여 기록과 비교하여 미참여 항목만 선별스케줄링은 chrome.alarms API를 사용해 6시간마다 자동 실행되도록 설정했다.
이미 참여한 항목을 만나면 이후 항목들은 모두 처리된 것으로 판단하고 수집을 중단하는 최적화 로직도 넣었다.
이 덕분에 매 실행마다 22페이지를 모두 순회하지 않아도 된다.
팝업과 옵션 페이지를 각각 React 컴포넌트로 분리하여 개발했다.
댓글은 기본 5가지 메시지에서 랜덤 선택되며, 옵션 페이지에서 추가/삭제가 가능하다.
총 200개 이상의 기부 항목에 자동 참여할 수 있게 됐다.
처음 실행 시 전체 항목 처리에 약 10~15분이 소요되며, 이후 실행부터는 신규 항목만 처리해 훨씬 빠르게 동작한다.
1분기가 끝났다. GitHub 정리해보니 3개월 동안 3개 레포에서 152건 정도 작업했더라. 많이 만들긴 했다. 성과도 나오고 있고, D2C 퍼널 데이터도 잘 나오고 있다. 그런데 이 글을 쓰면서 계속 드는 생각이 있다. `'OKR 목표를 바라보고 달렸나?'` 이 질문에는 자신 있게 답하기 어렵다. ## 무엇을 했나 ### D2C — 0에서 1로 만든 제품 1분기에서 가장 큰 작업은 D2C 서비스를 처음부터 만들어서 런칭한 거다. 1월 말부터 근무지 선택, 월급일 입력 같은 초기 플로우를 만들기 시작했고, 2월 초~중순에 온보딩, CMS 자동이체, 본인인증, 상환 페이지, 급여계좌 R2 업로드 같은 핵심 기능을 완성했다. 2월 중순부터는 QA에 집중하고 바로 오픈할 정도로 촉박한 일정이었다. 런칭 후에는 Amplitude, PostHog 기반으로 퍼널 데이터 수집하고, 전환율 떨어지는 구간 잡아서 개선하고, 성과 측정까지 진행했다. 데이터는 잘 나오고 있다. ### 신분증 OCR 원래 Tesseract로 OCR을 붙였는데 인식률이 좋지 않았다. 코드에프, 네이버 클로바 등 여러 솔루션을 찾아봤는데, 문득 `'그냥 AI로 해볼까?'` 싶어서 Claude Vision을 붙여봤다. 프롬프트에 따라 인식률이 꽤 높아서 그대로 진행했다. 여러 선택지...
Notion을 사용하면서 대시보드에 시계나 진행률 같은 위젯을 넣고 싶었는데, 기존 서비스들은 가입을 요구하거나 커스터마이징이 제한적이었다. 가입 없이 URL 쿼리 파라미터만으로 위젯을 커스터마이즈하고, Notion에 바로 임베드할 수 있는 서비스를 직접 만들기로 했다. ## 핵심 컨셉 **"URL = Single Source of Truth"** — 모든 위젯 설정이 URL 쿼리 파라미터에 저장된다. 별도의 가입이나 DB 저장 없이 URL 하나만 공유하면 누구든 같은 위젯을 볼 수 있다. 사용 흐름은 단순하다: 1. 갤러리에서 위젯을 고른다 2. 색상, 언어, 표시 옵션을 커스터마이즈한다 3. 생성된 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종) 위젯 추가...
강의 시청 화면에서 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);