오랜만에 글을 씁니다.
지난 7월, 1년 9개월 동안의 직장 생활을 마무리하게 되었습니다. 퇴사 이후, 지난 3개월 동안 이전부터 꼭 도전해보고 싶었던 제품 개발을 하게 되었습니다. 그동안 꽤 많은 사이드 프로젝트를 진행했지만, 대부분이 실제 제품이라기보다는 학습을 위한 토이 프로젝트들이었습니다. 이번 글에서는 제가 어떤 문제를 발견하고, 어떻게 해결하려 했는지, 그 과정에서 기술적으로 어떤 선택을 했는지 간략히 이야기하려 합니다.
1. 시작 배경
이번에는 토이 프로젝트와 달랐습니다. 단순한 기술 구현을 넘어, 실제 시장에서 경쟁할 수 있는 제품을 만들고 싶었습니다. 그동안의 스타트업 경험을 바탕으로, 작지만 의미 있는 도전을 시작하고 싶었습니다.
아이디어를 고르는 기준은 명확했습니다:
이미 검증된 시장이 있을 것
1인 개발자가 감당할 수 있는 규모일 것
이런 기준으로 수많은 아이디어를 걸러내다 보니, 결국 제가 실제로 필요로 했던 것이 남았습니다. 바로 '어느 웹사이트에나 쉽게 부착할 수 있는 댓글 기능'이었습니다. 그동안의 사이드 프로젝트를 하면서 반복적으로 구현이 필요한 기능이었습니다. 댓글 기능만을 위한 라이브러리를 만들까-에서 시작한 아이디어는 조사를 거쳐가며 점차 바뀌었습니다.
2. 시장 조사
단순한 댓글 기능만으로 부족했습니다. 이미 Disqus나 다양한 무료 솔루션이 있었기에, 사용자들이 기꺼이 비용을 지불할 만한 차별화된 가치가 필요했습니다.
그래서 이런 질문들을 던져보았습니다:
어떤 시장을 공략할 것인가?
누구를 위한 제품을 만들 것인가?
어떤 차별화된 기능을 제공할 것인가?
시장 조사를 하면서 BuiltWith의 통계를 살펴보니, Disqus가 속한 댓글 시스템보다 고객 피드백 시장이 더 컸습니다. 물론 이 분류에는 상품 리뷰뿐만 아니라 이메일 마케팅까지 포함되어 있어서 시장이 실제보다 크게 보일 수 있습니다. 하지만 고객 리뷰로 범위를 좁혀도 충분하다고 느꼈습니다. 아직 시장이 독점되지 않았고, 여전히 많은 제품들이 경쟁하고 있어 진입 가능성이 있다고 생각했습니다.
결정적으로, 수 많은 쇼핑몰들이 아마존 같은 플랫폼 외에도 Shopify, Wix, WooCommerce 등의 사이트 빌더로 자체 쇼핑몰을 운영하며 별도의 피드백 시스템을 구독하고 있었습니다.그리고 그들 중 적지 않은 사용자들이 불편함을 겪고 있었습니다.
이를 보고 제가 던졌던 세 가지 질문에 모두 답을 할 수 있겠다는 생각이 들었고, 'E 커머스 리뷰 시스템'으로 방향을 잡게 되었습니다.
어떤 시장을 공략할 것인가? : 고객 피드백(E 커머스 리뷰) 시장
누구를 위한 제품을 만들 것인가? : 리뷰가 중요한 온라인 쇼핑몰들
이들이 겪는 문제:
너무 높은 가격
리뷰 수집의 어려움
가짜 리뷰 관리
낮은 리뷰 참여율
제한적인 기능
리뷰 수집의 어려움
가짜 리뷰 관리
낮은 리뷰 참여율
제한적인 기능
어떤 차별화된 기능을 제공할 것인가? : 위 문제들을 해결하는 제품
타겟 유저
이후 충분히 많은 자료 조사를 하면서 타겟 유저와 이런 것들을 좁혀갔습니다. 이 과정에서 제 제품을 사용할 타겟 유저를 구체화 해갔습니다. 프로젝트에 조금 더 확신을 갖게 되었습니다.
주요 사용자
: 온라인 쇼핑몰의 고객 관리/마케팅 담당자 혹은 쇼핑몰 운영자(비 개발자)
주요 문제점
설치 및 유지보수 어려움
복잡한 설치 과정으로 비개발자가 설치, 유지 보수의 어려움을 겪음
설치 후 오류 발생 시 해결이 어려움
기능적 문제- 리뷰 데이터 임포트/익스포트의 어려움, 리뷰 사라짐, 동기화 오류 등 안정성 문제, 리뷰 관리 기능의 제한 (수정, 숨김, 삭제 등)
성능 이슈: 웹사이트 로딩 속도 저하, 이미지 품질 저하, 모바일 환경 최적화 부족
커스터마이징 한계: 제한된 디자인 옵션, 브랜드 아이덴티티 반영의 어려움
가격 정책 불만 -
갑작스러운 요금제 변경과 숨겨진 비용
주문량 증가에 따른 과도한 비용 청구
고객 지원 미흡
이러한 문제들을 모두 해결한다면, 더 나은 제품을 필요로 하는 고객들에게 다가갈 수 있을 것으로 보였습니다.
3. 기술 설계
처음 설계할 때 가장 중요하게 생각한 것은 '어떻게 하면 사용자들이 쉽게 설치하고 빠르게 사용할 수 있을까'였습니다. 이를 위해 신중하게 스택을 선정했습니다.
기술 스택 선정
Supabase: Firebase의 대안으로 고려했는데, 특히 다음 장점들이 결정적이었습니다:
PostgreSQL 기반으로 복잡한 쿼리와 트리거 활용 가능
Row Level Security로 데이터 접근 제어 (보안)
무료 티어의 높은 할당량과 합리적인 요금제
멀티레포 구조: 두 개의 레포로 분리하여 각각 목적에 맞는 최적화를 진행했습니다:
1. commenti.co (Next.js):
API Routes로 결제, 인증 등 서버 로직 구현
SEO 최적화와 빠른 초기 로딩을 위한 SSR 활용
2. commenti-package (React + Vite):
가벼운 번들 사이즈를 위해 Vite 선택
사용자의 웹사이트 성능에 최소한의 영향을 주도록 최적화
Tree-shaking으로 불필요한 코드 제거
상태 관리 : 복잡한 상태 관리를 효율적으로 처리하기 위해 두 가지 라이브러리를 사용했습니다.
Zustand:
간단한 설정과 보일러플레이트 최소화
작은 번들 사이즈(Gzipped 1.2kB)로 성능 최적화
React Query:
서버 상태 관리와 캐싱 자동화
실시간 리뷰 업데이트를 위한 폴링과 리패칭
무한 스크롤 구현으로 대량의 리뷰 효율적 로딩
오프라인 지원과 optimistic 업데이트로 UX 개선
스크립트
대부분의 리뷰 솔루션들은 iframe을 사용했습니다. iframe은 설치가 간단하고 스타일 충돌도 없지만, 실제 사용자들에게 여러 문제가 있었습니다:
SEO 최적화 문제: 리뷰 내용이 검색엔진에 제대로 노출되지 않음
느린 로딩: 대부분의 iframe 기반 리뷰 위젯들은 초기 로딩에만 1~2초 이상 소요
사용자의 웹사이트 폰트나 스타일을 적용할 수 없음
모바일에서 스크롤이 부자연스럽고 반응형 대응이 어려움
이러한 문제들을 해결하기 위해 iframe 대신 js 스크립트와 Shadow DOM을 활용했습니다:
<!-- 기존 iframe 방식 -->
<iframe src="https://review-widget.com/embed?id=123"></iframe>
<!-- Commenti 방식 -->
<script src="https://cdn.commenti.co/commenti.js"></script>
<!-- 원하는 위치에 삽입 -->
<commenti-section></commenti-section>
이 방식의 장점은:
서비스 초기 로딩 시간을 300ms 내외로 단축
Shadow DOM으로 스타일 격리하면서도 사용자 정의 스타일 적용 가능
SEO에 유리하고 리뷰 콘텐츠가 검색엔진에 노출 (추가적으로 JSONLD를 사용하여 유저가 생산한 컨텐츠 태그를 추가했습니다.)
자연스러운 사용자 경험
결과적으로 사용자들은 간단한 복사-붙여넣기만으로 자신의 웹사이트에 맞춤형 리뷰 시스템을 설치할 수 있게 되었습니다.
배포 전략
사용자 경험을 최우선으로 고려한 배포 전략을 세웠습니다:
1. Github Actions + Cloudflare CDN:
Github Actions로 자동 빌드 및 배포
빌드된 스크립트를 S3 클라이언트를 통해 Cloudflare CDN에 자동 업로드
CDN을 통해 전세계 어디서나 빠른 로딩 속도
2. Cloudflare 서비스 활용:
R2 Storage: 사용자 업로드 이미지 저장
- S3보다 저렴한 비용
- CDN과 원활한 통합
Workers: R2에 이미지 업로드 시의 인증, URL 입력 시 scrapper를 사용
CDN 캐싱
- 지역에 상관없이 일관된 성능
- HTTPS 자동 적용
3. Next.js + Vercel (commenti.co):
사이트 내에서 결제나 인증 등 api route를 활용할 필요가 많았기 때문에 사용하게 되었습니다.
Vercel로 배포 관리 및 모니터링의 용이성
이런 구조로 안정적이면서도 확장 가능한 시스템을 목표했습니다. 사용자들이 쉽게 설치하고 빠르게 사용할 수 있는 환경을 만드는 데 중점을 두었습니다.
4. 기술적 난관과 해결
많은 난관들이 있었지만, 그동안 문제를 해결하면서 개발부터 배포까지 전반적인 과정을 다시금 이해할 수 있었습니다. 이번 글에선 주요 기술적인 도전을 간략히 회고하겠습니다. 기술적 난관을 해결한 사례는 추후 학습하게 된 내용들과 함께 올리도록 하겠습니다.
1. commenti-package: 스크립트 빌드와 배포 문제
처음 스크립트를 개발할 때 몇 가지 까다로운 문제들이 있었습니다:
// vite.config.ts
/*React 컴포넌트와 모든 의존성을 하나의 파일로 번들링해야 했음번들 사이즈가 너무 커지는 문제Tailwind CSS와 같은 스타일 처리 이슈
*/
plugins: [
react(),
visualizer({
filename: "bundle-analysis.html",
open: true,
}),],build: {
lib: {
entry: path.resolve(__dirname, "src/build/index.ts"),
name: "Commenti",
fileName: (format) => commenti.${format}.js,
formats: ["package"],},rollupOptions: {
external: [],
output: {
// CSS 파일
assetFileNames: (assetInfo) => {
if (assetInfo.name && assetInfo.name.endsWith(".css")) {
return "commenti.css";
}
return assetInfo.name || "commenti.css";
},
},
},
Github Actions 배포 파일 .github/workflow/deploy.yml
name: Deploy to Cloudflare R2
env: ....
run: |
npm install @aws-sdk/client-s3
node .github/scripts/deploy-to-r2.js// github/scripts/deploy-to-r2.jsimport { gzip } from "zlib";
..
const gzipAsync = promisify(gzip);async function uploadFile(filePath, key) {
try {
const fileContent = await fs.readFile(filePath);
// 빌드가 완료된 스크립트 압축
const compressed = await gzipAsync(fileContent);</pre>
답글, Verified(구매 인증), 수정, 사용자 차단 등 다양한 기능이 추가되면서 <strong>번들 사이즈가 커지는 문제가 발생했습니다:
1. 번들 사이즈 최적화
GitHub Actions에서 빌드 시 gzip 압축을 적용
Cloudflare R2에 압축된 스크립트를 업로드하여 CDN 배포
초기 500kb (로딩 1.3~5s)에서 182kb (500ms 이하)로 개선
2. 상태 관리 최적화
React Query를 도입하여 서버 상태 캐싱 구현
댓글 실시간 업데이트 시 필요한 컴포넌트만 리렌더링
불필요한 API 호출 최소화
3. 코드 분할 및 정리
사용하지 않는 코드 제거
초기 로딩에 필요한 코드만 먼저 다운로드 빠르게 앱을 서빙하는 것이 중요한 목적이었기에, 최적화를 통해 더 나은 사용자 경험을 제공하기 위해 노력했습니다.
2. Shadow DOM과 스타일링 문제
리뷰 위젯이 사용자의 웹사이트와 자연스럽게 어우러지면서도 독립성을 유지해야 하는 까다로운 요구사항이 있었습니다:
/* commenti.css */
/* 문제: font-family는 상속하면서 다른 스타일은 격리해야 함 */
:host {
--commenti-background: inherit;
--background: var(--commenti-background, white) !important;
....
--text: var(--commenti-text, 29 29% 29%);
/* 폰트는 설치된 웹사이트에서 상속 */
--font-family: var(--commenti-font-family, inherit) !important;
--rating: var(--commenti-rating, 44 94.2% 53.1%);
--verified: var(--commenti-verified, 142 76% 36%);
--safe-top: env(safe-area-inset-top, 1rem);
--safe-right: env(safe-area-inset-right, 1rem);
--safe-area-inset: 0px;
--commenti-font-size-base: 1.3em;
--commenti-font-size-xs: calc(var(--commenti-font-size-base) * 0.8);
....
--commenti-font-size-4xl: calc(var(--commenti-font-size-base) * 2.25);
}
스타일의 일관성 문제 중 하나는 웹사이트마다 다른 폰트 크기 설정으로 인해 일관된 UI를 유지하기 어려웠던 것입니다. 설치된 웹사이트에서 상대적 단위의 스타일(transform:scale(), %, rem )에 영향을 받아 의도한 디자인이 깨질 수 있었습니다. 예를 들어 font-size를 rem 단위로 사용할 때, 사이트 전체에 transform:scale()이 적용된 경우, 스타일이 격리되어도 문제가 생겼습니다. 이를 해결하기 위해 Shadow DOM 내부에서 독립적인 단위를 설정하여 일관된 사용자 경험을 제공하도록 했습니다.
3. Commenti.co: PayPal 결제 시스템 구현
북미 시장을 겨냥한 프로젝트였기에, PayPal API를 활용한 결제 시스템을 구축했습니다:
// 구독 상태 변경시 webhook으로 실시간 처리
async function handleSubscriptionChange(event: WebhookEvent) {
if (event.type === 'BILLING.SUBSCRIPTION.UPDATED') {
await updateUserPlan(event.resource); } }
다음과 같은 점이 어려웠습니다.
Sandbox 환경에서의 테스트 데이터 검증 :
개발 환경 paypal 서버 데이터는 따로 UI를 제공하지 않아 매 요청 로깅을 확인해야함.
구독 취소와 플랜 변경 시나리오 처리
자동 인보이스 생성 로직
이러한 기술적 문제들을 해결하면서, 안정적이고 사용자 친화적인 시스템을 구축하고자 했습니다. 구현 사항은 추후 글로 다시 정리할 예정입니다.
5. 개발 및 런칭
혼자 개발하는 프로젝트였지만 빠른 개발-테스트-배포 사이클을 위해 자동화가 필수였습니다.
CI/CD 파이프라인
# Github Actions workflow jobs:
build_and_test:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
steps:
- build_package
- run_tests
- deploy_to_dev_cdn
- # 개발 환경 CDN 배포
- production_deploy:
- if: github.ref == 'refs/heads/main'
- steps:
- deploy_to_prod_cdn
- # 프로덕션 CDN 배포
- deploy_to_vercel
- # commenti.co 배포
...
개발 환경에서의 테스트를 위해:
개발용 CDN 환경 구축
dev.package.commenti.co
)CDN 캐시를 비활성화해 실시간 테스트 가능
S3 호환 API로 Cloudflare R2에 자동 업로드
배포 이후 바로 개발 환경에서 테스트 가능
실제 사용자 환경과 동일한 조건에서 테스트
안전한 프로덕션 배포와 롤백 시스템 구축
6. 결과 및 배운 점
기술적 성과
결과적으로 2개의 레포를 런치했습니다.
Next.js 13 App Router를 활용하여 전체 웹사이트와 대시보드를 개발했습니다.
Supabase를 활용하여 사용자 인증, 리뷰 데이터 관리, 실시간 업데이트 기능을 구현했습니다.
PayPal Subscription API를 연동하여 자동 결제 및 구독 관리 시스템을 구축했습니다.
대시보드에서 리뷰 관리, 제품 페이지 설정, 디자인 커스터마이징 등의 기능을 Tanstack Query와 함께 개발하여 상태 관리를 최적화했습니다.
TailwindCSS를 활용한 반응형 디자인으로 모바일 환경에서도 원활한 사용이 가능하도록 했습니다.
Cloudflare R2와 Worker를 활용하여 이미지 업로드 및 최적화 파이프라인을 구축했습니다.
commenti-package:
Shadow DOM을 활용하여 4가지 UI 컴포넌트(텍스트 리뷰, 포토 리뷰, 텍스트 테스티모니얼, 포토 테스티모니얼)를 개발했습니다.
외부 CSS의 영향을 받지 않는 격리된 스타일링으로 안정적인 디자인을 보장했습니다.
번들링을 통해 단일 JavaScript 파일로 배포하여 간단한 설치 경험을 제공했습니다.
구독 모델별 기능 제한과 리뷰 제한을 효율적으로 관리하기 위한 타입 시스템을 구축했습니다.
웹사이트의 기존 폰트와 배경색을 자동으로 감지하여 적용하는 기능을 구현했습니다.
모바일 환경을 고려한 반응형 디자인으로 개발하여 다양한 디바이스에서 일관된 사용자 경험을 제공했습니다.
JSON-LD 스키마를 자동으로 생성하여 구글 리치 리절트에 리뷰가 표시되도록 SEO를 최적화했습니다.
기술 스택 측면에서 Next.js, React, TypeScript, Supabase, TailwindCSS 등 모던 웹 기술을 활용하여 확장 가능하고 유지보수가 용이한 아키텍처를 구축했습니다.
개발자로서의 성장
처음으로 프론트엔드부터 백엔드, 인프라까지 전체 개발 과정을 책임져보았습니다. 특히 결제 시스템 연동과 데이터베이스 설계 과정에서 많은 것을 배웠습니다. 실제 서비스를 위한 보안, 성능 최적화, 에러 처리의 중요성을 체감했고, 사용자 중심의 개발이 무엇인지 이해하게 되었습니다.