[LG U+ URECA] 요고다(YOGODA) 종합 프로젝트 회고 [최우수상]

지현·2026년 9월 6일
post-thumbnail

3주 동안 3명이서 AI 요금제 상담 → 가입 전환 → 관리자 모니터링까지 이어지는 풀사이클 서비스를 만들었다. 그 과정에서 배운 것들을 정리한다.


프로젝트 소개

YOGODA(요고다) 는 통신사 요금제를 AI가 상담해주는 서비스다. 단순히 "이 요금제가 좋아요"라고 추천만 하는 게 아니라, 추천 → 비교 → 가입 → 모니터링 → 프롬프트 개선까지 하나의 순환 구조로 연결한 플랫폼이다.

기존 요금제 추천 서비스들의 문제는 "추천은 잘하는데, 그 뒤가 없다"는 거였다. 사용자가 추천을 받고 실제로 가입했는지, 어디에서 이탈했는지, 어떤 프롬프트가 더 나은 결과를 내는지 등 이런 데이터가 전혀 남지 않았다. 요고다는 이 빈자리를 채워서 추천 품질을 데이터로 계속 개선할 수 있는 구조를 만드는 게 목표였다.

  • 기간: 2026.08.14 - 2026.09.03 (3주)
  • 팀: 3명 (박해준, 고유정, 서지현) - 전원 FE/BE 풀스택, 기능 단위로 책임 분담
  • 내 담당: 프로젝트 세팅(BE), 소셜 로그인/인증, 관리자 페이지 전체


🛠 기술 스택

Frontend : Next.js · React · TypeScript · TanStack Query · Zustand · Tailwind CSS · Storybook · next-intl
Backend : Node.js · Express · TypeScript · Socket.IO · JWT · Zod · Swagger
AI / Data : Gemini Interactions API · MongoDB Atlas · Mongoose · Azure Key Vault
Infra / Deploy : Vercel · Azure App Service
Auth : OAuth 2.0 (카카오 · 네이버 · 구글)
Quality / Collab : Vitest · Playwright · ESLint · Prettier · Husky · GitHub · Jira · Notion


담당 기능

나는 백엔드 초기 세팅, 소셜 로그인(구글/네이버/카카오), 그리고 관리자 페이지 전체를 담당했다.

관리자 페이지는 단순한 CRUD 어드민이 아니었다. 상담 퍼널 분석, UI 클릭률 추적, 프롬프트 버전 관리 및 A/B 테스트, 세션 로그 조회 등 이 모든 게 실제 채팅 데이터와 연결되어 돌아가야 했다. 프론트에서 데이터를 어떻게 보여줄지뿐 아니라, 백엔드에서 이벤트를 어떤 단위로 기록하고 어떻게 집계할지까지 설계해야 했기 때문에 풀스택 역할이 자연스러웠다.


주요 개발 기록

각 주제는 별도 개발일지에 상세히 정리해뒀다. 여기서는 뭘 했고 뭘 느꼈는지만 짧게 남긴다.

1. 소셜 로그인

카카오·구글·네이버 세 플랫폼 소셜 로그인을 모두 구현했다. 셋 다 OAuth 2.0 인가 코드 방식이라 핵심 로직은 동일했고, 코드보다 각 플랫폼 개발자 콘솔 세팅이 오히려 시간을 더 잡아먹었다. 하나의 표준을 제대로 이해하면 나머지는 따라온다는 걸 체감했다.

📝 개발일지 #2 - 구글/네이버/카카오 소셜 로그인 구현해보기

2. 비회원 채팅 세션

"비회원은 로컬에만 저장"이라는 초기 설계가 관리자 페이지를 만들면서 깨졌다. 비회원 이탈 데이터가 서버에 없으니 분석 자체가 불가능했기 때문이다. "연결 시점부터 저장"으로 바꾸면서 소켓 인증 타이밍, 세션 쪼개짐, 이탈 상태 되살아남 등 연쇄적인 문제를 해결해야 했다.

📝 개발일지 #3 - 비회원 채팅 세션 저장하기

3. React Query 캐시와 useState 초기값 충돌

프롬프트 편집 화면에서 새로고침은 정상인데 탭 전환 후 돌아오면 텍스트박스가 비는 버그를 만났다. React Query 캐시가 재마운트 시 데이터를 즉시 채워주면서, useState 초기값 기반의 리셋 로직이 무력화되는 게 원인이었다. 초기값을 외부 데이터에서 유도하지 않고 undefined로 고정해서 해결했다.

📝 개발일지 #5 - React Query 캐시 때문에 useState 초기값이 틀어지는 버그

4. 프롬프트 관리 - 어디까지 관리자에게 열어줄 것인가

AI 시스템 프롬프트 중 인사말+역할+규칙만 관리자 편집 범위로 열고, JSON 응답 형식은 코드에 고정시켰다. 관리자가 실수로 응답 형식을 건드리면 전체 채팅이 멈출 수 있기 때문이다. 세션 생성 시점에 프롬프트 버전을 고정하는 방식으로 대화 중 말투가 바뀌는 문제도 방지했다.

📝 개발일지 #6 - 프롬프트는 어디까지, 어떻게 채팅에 반영되어야 할까?

5. 퍼널 이탈 / UI 클릭 분석

Hotjar 같은 히트맵 대신 직접 이벤트 추적을 구현했다. 채팅 화면은 동적 스크롤이라 히트맵이 강력한 조건이 아니었고, 관리자에게 필요한 건 이미 정해진 전환 버튼들의 CTR을 정밀하게 모니터링하는 것이었다. 퍼널은 순서 보장, UI 이벤트는 세션당 1건으로 중복 방지하며 기록했다.

📝 개발일지 #7 - 퍼널 이탈 / UI 클릭 분석 기록과 집계

6. API 응답 속도

대시보드 API가 3초대로 느려서 직렬 쿼리를 Promise.all로 병렬화했지만 2초대에서 멈췄다. 쿼리 하나당 왕복 220ms가 일정하게 나와서 인프라를 의심했고, MongoDB Atlas 클러스터가 미국 리전이었던 게 원인이었다. 서울로 옮기니 1초 미만으로 해결됐다.

📝 개발일지 #4 - API 응답이 왜 또 느릴까..?


결과 수치

항목수치
페이지 수38개
API 수 (Swagger 문서화)59개
테스트 통과64개 (FE 32 + BE 26 + E2E 6)
PR110개
Lighthouse Performance95점
Lighthouse Accessibility100점

Claude Design으로 관리자 UI 프로토타이핑

관리자 페이지 UI를 처음부터 그리기 막막해서 Claude Design을 써봤다. 디자인 시스템(메인 컬러, 카드 스타일, 레이아웃)을 프롬프트 상단에 정의해두고 페이지 단위로 생성 → html to design 플러그인으로 Figma에 가져와서 다듬는 워크플로우를 사용했다.

디자이너 없이 백지부터 시작하는 막막함이 확 줄었고, 일관된 톤앤매너를 유지하는 데도 효과적이었다.


팀 회고 (KPT)

Keep 계속 가져갈 것

  • API 계약 우선: Swagger로 59개 API를 문서화하고, FE/BE가 같은 명세를 기준으로 맞춰 작업했다. API 변경 시 계약 동기화를 먼저 하는 습관이 재작업을 줄여줬다.
  • 공통 UI / 품질 자동화: Storybook으로 공통 컴포넌트 25종을 독립 관리하고, Husky + lint-staged로 커밋 전 자동 검사를 걸었다. 프로젝트 후반에도 코드 품질이 흔들리지 않았다.
  • 데이터 기반 의사결정: 프롬프트 성과를 감이 아니라 전환율 데이터로 비교할 수 있게 구조를 만든 것.

Problem 아쉬웠던 것

  • API 명세 변경에 따른 재작업: 계약 우선이라는 원칙은 좋았지만, 초기 설계가 바뀌면서 이미 구현한 부분을 재작업한 경우가 있었다. 명세를 더 일찍 확정하거나, 변경 범위를 최소화하는 연습이 필요하다.
  • 초기 설계와 최종 구현 간 차이: 비회원 세션 저장 건처럼, 처음엔 합리적이었던 설계가 관리자 요구사항이 추가되면서 뒤집히는 경우가 있었다. 다양한 관점을 초기에 더 검토했어야 했다.
  • 통합 시점이 늦어진 부분: 각자 기능 단위로 개발하다 보니 FE-BE를 합쳐보는 시점이 좀 늦었다. 중간중간 통합 테스트를 했으면 마지막 주에 여유가 있었을 것이다.

Try 다음에 바꿀 것

  • 실험 지표 사전 정의: 프롬프트 A/B 테스트를 만들긴 했지만, "무엇을 기준으로 더 나은 프롬프트인지" 지표를 사전에 명확히 정의하고 시작하면 더 의미 있는 실험이 될 것이다.
  • 통합 테스트 시점 앞당기기: 기능 개발 완료 후가 아니라, 스프린트 중간에 FE-BE 연결 테스트를 루틴으로 잡기.
  • 성능·접근성 자동 측정: Lighthouse 점수를 수동으로 재는 게 아니라 CI에 통합해서 매 배포마다 자동으로 체크하기.

개인적으로 배운 것

  1. 비회원 세션 건이 대표적이다. "비회원은 저장 안 해도 된다"는 판단이 틀린 게 아니었다. 다만 그때는 관리자 관점을 고려하지 못했을 뿐이다. 한 가지 관점에서 내린 합리적인 판단도, 다른 관점이 끼어들면 다시 흔들릴 수 있다는 걸 몸으로 배웠다.
  2. 프롬프트 관리 기능을 만들면서 느낀 건, 커스터마이징 권한을 준다고 전부 열어주면 안 된다는 것이다. JSON 응답 형식처럼 깨지면 서비스 전체가 멈추는 부분은 시스템이 쥐고 있어야 한다. "얼마나 자유롭게 열어줄까"가 아니라 "어떤 걸 관리자에게 맡기고 어떤 걸 시스템이 소유해야 하는지 그 경계를 정하는 것"이 핵심이었다.
  3. 히트맵 라이브러리 대신 직접 이벤트 추적을 만든 건, "쉬운가 어려운가"가 아니라 "이 화면의 특성에 어떤 방식이 더 맞는가"로 판단한 결과였다. 도구 선택의 기준이 난이도가 아니라 적합도여야 한다는 걸 실감했다.
  4. API 응답 속도 문제에서, 쿼리 최적화만으로 해결하려 했으면 2초 벽을 넘지 못했을 것이다. "이 데이터 양에 이 시간이 맞나?" 하는 의문이 인프라(리전) 문제를 짚어줬다. 코드를 더 파는 것과 한 발 물러서서 전체 그림을 보는 것 사이의 전환이 중요하다.

마무리

3주라는 시간이 길면서도 굉장히 짧게 느껴졌다. 매일 새로운 문제를 만나고 해결하면서 밀도 있게 보낸 건 맞는데, 돌이켜보면 좀 더 개발 속도를 냈어야 했다는 아쉬움이 남는다.

개발을 더 빨리 끝냈으면 테스트 기간을 충분히 확보할 수 있었을 거고, 사용자 입장에서 UI/UX를 다듬는 시간도 가질 수 있었을 텐데 후반으로 갈수록 기능 구현에 급급해진 느낌이 있었다. 다음 프로젝트에서는 개발을 일찍 마무리하고, 테스트와 사용자 관점의 개선에 시간을 더 쓸 수 있는 페이스를 만들고 싶다.

그래도 이번 프로젝트를 통해 정말 많이 배웠다. 설계가 뒤집히는 순간의 대응, 데이터를 기록하고 집계하는 구조 설계, 코드 너머의 인프라까지 시야를 넓히는 감각 이런 것들은 강의에서 배울 수 없는, 직접 부딪혀봐야 느는 종류의 경험이었다.


GitHub: yogoda-backend · yogoda-frontend

0개의 댓글