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에 저장된 참여 기록과 비교하여 미참여...
출퇴근 서비스를 만들었지만, 그룹웨어의 다른 기능들을 사용하려면 결국 그룹웨어 페이지에서 QR코드를 인증해야했다. 나는 console에 스크립트를 입력하여 로그인하다보니 상관 없었지만, 다른 사람들에게 개발자 도구 켜서 스크립트 입력하세요라고 알려주기에는 비개발자들이 접근하기 어려웠다. 크롬 플러그인 처음에는 출퇴근 페이지에서 한번에 처리하는게 편하다고 생각했지만, CORS 이슈와 쿠키 셋팅하는 부분에서 우회하는 처리가 까다로웠다. 시간을 많이 소요하기에는 임펙트가 없다고 생각하기에 플러그인으로 CORS를 해결하고 API를 다이렉트로 호출하여 setCookie를 받으면 빠르게 작업 처리가 가능하다고 판단하여 크롬 플러그인 형태로 진행했다. 결과물 그룹웨어 로그인 플러그인
회사 합병으로 기존 출퇴근과 법인카드 사용 방식이 변경되었고, 그룹웨어 페이지에 접속하여 수기 진행하는 방식으로 제공되었다. 그룹웨어의 출퇴근 방식은 PC로만 제공되어서 모바일로 출퇴근이 불가능했고, 노트북을 회사에 두고 다니는 사람들은 퇴근을 누르지않아 회사로 복귀하는 상황이 지속적으로 발생했다. 또한 법인카드 사용내역 등록 방식이 복잡해지면서 혼란이 가중되고 직원들이 불편함을 호소했다. 기존처럼 모바일로 출퇴근한다면 생산성이 올라가지 않을까하여 그룹웨어와 통신하는 웹페이지를 기획했다. 초기버전 프론트는 Next.js로 Vercel로 배포하였으며, 백엔드는 Node.js로 구성했다. 백엔드는 서버에 배포했는데, AWS Lightsail + Ubuntu 환경에 nginx를 붙였다. SSH 셋팅을 진행하고 PM2로 서비스를 관리했다. ( 참고 ) 초기버전에서는 출퇴근 기능과 법인카드 사용내역을 포맷에 맞게 등록해주는 기능을 구현했다. 사이트에서는 항상 로그인 계정을 입력받고 그룹웨어와 통신하여 데이터를 가져온다. 출퇴근과 법인카드는 직원들이 가장 많이 접근하는 메뉴이기 때문에 채널에 오픈 당시 많은 환영을 받았다. 기능 업그레이드 5월 포괄임금제 정책이 변경되면서 출퇴근 기록이 중요해졌고, 유저에게 더 의미있는 정보를 제공해보았다. 다양한 인사관리 프로그램을 참고하여 어떤 정보를 제공하면 좋을까 고민하고 다음과 같이 UI를 변경했다. 메인화면에서는 출퇴근 시간을 UI로 명확하게 보여주고, 휴가와...
플레이오토 입사 당시, 팀장님이 온보딩 기간 동안 만들고 싶은 것 있는지 찾아보라고 하셨다. 당시 점심시간에 배달시켜먹는 채널이 있었는데, 배달 앱이 크게 활성화되어있지 않다 보니 채널에 메뉴판을 올리고 다른 사람들이 댓글 형식으로 먹고 싶은 메뉴를 이어 적는 형태였다. 해당 방식을 그대로 사이트 형태로 옮기는 작업을 진행했다. 가게와 메뉴 선정 먼저 자주 배달시키는 가게들 위주로 추가했다. 체인점 같은 경우에는 웹 페이지로 메뉴를 제공하다 보니 스크랩핑해서 DB를 구성할 수 있었는데, 중국집같이 전단지만 있는 경우에는 수동으로 추가 후 제보받는 형식으로 진행했다. 메뉴 선택과 주문 가게를 선택하면 메뉴를 고를 수 있는 방식이다. 단순하게 마지막 주문하는 사람을 결제자로 지정하려고 했으나, 카드 실적 등 여러 사유로 결제하고 싶은 사람이 있어 선택사항으로 정산 받을 계좌번호를 입력할 수 있도록 처리했다. 결제하기는 한 명만 가능하며 이미 입력한 사람이 있다면 이후 사람들은 주문만 가능하다. 주문 리스트와 별개로 Result라는 항목을 따로 만들었는데, 전화주문을 하다 보면 주문자가 업체 연락처, 회사 주소를 찾아보고 음식 별 개수를 다시 정리하는 일이 있어 해당 영역만 봐도 주문이...