최종 프로젝트 [어디가냥] 회고

Updated: 2025-06-27

project
cover image

[어디가냥] 프로젝트 회고

배포 주소: https://meowhere.vercel.app/

1. 프로젝트 개요

프로젝트 기간: 2025년 5월 27일 ~ 2025년 6월 26일

기술 스택:

  • 프론트엔드: Nextjs, Typescript, TailwindCSS
  • 상태관리: Zustand, React Query
  • 백엔드: codeit-globalnomad REST API, Next.js API Routes
  • 인증/ 외부 APIs: Kakao Login API, Kakao Map SDK, Daum Search API
  • 데브툴: Github, ESLint, Prettier

팀 구성: 프론트엔드 5명

최종 프로젝트로 저희 팀은 사용자가 전국의 다양한 체험을 쉽게 찾고 등록할 수 있는 플랫폼인 ‘어디가냥’을 기획하고 개발했습니다. 이 사이트는 지도 기반의 위치 정보와 다양한 필터 기능을 통해 사용자가 원하는 체험을 직관적으로 탐색할 수 있도록 했으며, 간편한 카카오 로그인과 체험 공유 기능을 통해 지인들과 함께 즐길 수 있도록 구성했습니다. 또한 사용자는 체험 예약과 찜하기는 물론, 자신이 등록한 체험을 관리하고 참여 통계를 확인할 수 있어 개인 맞춤형 체험 관리가 가능하도록 구현했습니다.

2. 라이브러리 및 프레임워크

이번 프로젝트에서는 서비스의 목적과 사용자 경험에 적합한 기술을 선택하는 것을 우선으로 하여 다양한 라이브러리와 프레임워크를 도입하게 되었습니다.

Next.js

  • SSR/SSG 지원: 체험 목록 페이지의 SEO 최적화로 검색 엔진 노출 향상
  • API Routes: 백엔드 API 통합 개발로 개발 효율성 증대, HTTP-only 쿠키 설정
  • Image Optimization: 체험 이미지 자동 최적화로 페이지 로딩 속도 개선
  • File-based Routing: 직관적인 페이지 구조로 유지보수성 향상

TypeScript

  • 타입 안정성: 체험 데이터, 유저 정보 등 복잡한 데이터 구조의 런타임 에러 방지
  • 팀 협업: 명시적 타입 정의로 코드 이해도 향상 및 버그 사전 방지

Zustand

  • 경량성: Redux 대비 적은 보일러플레이트로 빠른 개발 가능
  • 모달, 토스트, UI 상태 관리: 모달, 토스트, 테마 등 UI 상태 중앙 집중식 관리
  • TypeScript 친화적: 타입 추론과 자동완성 완벽 지원

React Query (TanStack Query)

  • 서버 상태 관리: 체험 목록, 예약 정보 등 API 데이터 캐싱 및 동기화
  • 자동 리페칭: 백그라운드에서 데이터 최신 상태 유지로 UX 향상
  • 로딩/에러 상태: 사용자 친화적인 로딩 및 에러 처리 간소화
  • 무한 스크롤: 체험 목록의 페이지네이션 최적화

추가로 여러 기능을 구현하기 위해 React Portal을 활용해 모달을 효과적으로 렌더링하고, React Hook FormZod를 함께 사용해 폼 검증과 상태 관리를 효율화했으며, Framer Motion을 통해 인터랙션에 자연스러운 애니메이션 효과를 더했습니다. 또한 Recharts를 사용해 통계 데이터를 시각적으로 표현하고, Three.js를 통해 3D 뱃지를 구현하는 등 서비스 완성도를 높이기 위해 다양한 기술을 적극 활용했습니다.

3. 기획

프로젝트 개발에 앞서 가장 먼저 진행한 작업은 기술 명세서 작성과 Figma를 활용한 UI 디자인이었습니다. 기술 명세서는 노션을 통해 프로젝트 에픽과 사용자 스토리 구조로 정리했으며, 초기 설정부터 공통 컴포넌트 구성, 배포까지 총 14개의 에픽으로 설계해 개발의 큰 흐름을 명확히 했습니다.

피그마

UI/UX는 Figma를 통해 화면 설계와 사용자 플로우를 함께 작업했으며, 최종 프로젝트인 만큼 모바일 중심의 사용자 경험을 구현하기 위해 많은 고민과 노력을 기울였습니다. 특히 메인 페이지의 필터 및 검색 기능, 그리고 로그인/회원가입 화면의 흐름과 직관성을 개선하는 데 집중했습니다.

image.png

image.png

API

API 문서는 Swagger를 활용해 팀원 간 효율적인 테스트와 데이터 구조 파악이 가능하도록 했습니다.

image.png

폴더 구조

폴더 구조는 Next.js App Router 기반으로, 기능 중심(feature-based) 폴더 구조를 채택하여 페이지, 컴포넌트, 서비스, 상태 관리, 훅 등을 역할별로 분리하였습니다. app/ 디렉터리에서는 각 기능(로그인, 체험, 프로필 등)에 따라 라우트를 구성하고, components/, services/, hooks/ 등은 공통 요소와 로직을 모듈화하여 유지보수성과 확장성을 높였습니다.

1MEOWHERE/ 2├── public/ 3├── src/ 4│ ├── app/ 5| ├─ layout.tsx 6| ├─ page.tsx # 메인 페이지 7| ├─ not-found.tsx 8| ├─ middleware.tsx 9| ├─ account/ # 로그인 페이지 10| │ ├─ page.tsx 11| │ └─ components/ 12| ├─ activities/ # 체험 상세 및 예약 13| │ ├─ page.tsx 14| │ └─ [id]// 15| │ ├─ page.tsx 16| │ └─ components/ 17| ├─ profile/ # 사용자 정보 관리 18| │ ├─ page.tsx 19| │ ├─ components/ 20| │ ├─ my-info/ 21| │ ├─ reservations/ 22| │ ├─ my-activities/ 23| │ ├─ favorites/ 24| │ ├─ notifications/ 25| │ └─ my-reservations/ 26| └─ api/ 27| 28│ ├─ components/ 29| ├─ layout/ 30| │ ├─ navbar/ 31| │ └─ Footer.tsx 32| └─ common/ # 공통 컴포넌트 33│ ├─ constants/ 34│ ├─ providers/ 35│ ├─ services/ 36│ ├─ store/ 37│ ├─ hooks/ 38│ ├─ lib/ 39│ ├─ types/ 40│ ├─ utils/ 41│ └─ styles/

역할

이번 프로젝트에서 저는 공통 모달과 바텀시트, 공통 토스트 컴포넌트 개발을 비롯해 Next.js API Route 구성, 로그인 및 회원가입 기능, Zustand를 활용한 상태 관리, 카카오 로그인 및 공유 기능, 찜 기능, 404 페이지 구현, 그리고 인증 미들웨어 개발을 담당했습니다.

4. 협업 경험

image.png

스프린트

저희 팀은 스프린트 방식으로 개발을 진행하며, 매일 데일리 스크럼을 통해 각자의 작업 진행 상황과 문제점을 공유했습니다. 이 방식은 단기간에 빠르게 서비스를 개발할 때 특히 유용하다고 판단했고, 실제로 각자의 작업 내용을 빠르게 파악하고 필요한 수정이나 협업이 즉시 이뤄질 수 있어 효율적인 개발에 큰 도움이 되었습니다.

Jira

프로젝트 관리 도구로는 Jira를 사용했습니다. Jira는 스프린트 기반의 작업 흐름을 지원하기 때문에, 스프린트 방식과 매우 잘 맞았고, 에픽과 스토리 단위로 작업을 정리하기도 수월했습니다. 스프린트 별 업무 관리와 진행 상황 확인이 쉬워서 전체 개발 일정 관리에 큰 역할을 했습니다.

업무 분담 및 일정 관리

업무는 먼저 공통 컴포넌트를 중심으로 나눈 뒤, 페이지 단위로 세분화하여 분배했습니다. 이렇게 역할을 나누면 각자 맡은 범위가 명확해져 협업이 더 수월했고, 실질적으로도 가장 깔끔한 분배 방식이라고 판단했습니다. 전체 개발 기간은 총 4주로 계획했고, Jira 상에서 이를 4개의 스프린트로 나누어 각 스프린트별로 작업을 분배하고 관리했습니다.

Git

버전 관리는 Git Flow 전략을 바탕으로 진행했으며, GitHub 이슈와 PR 기능을 적극 활용했습니다. 모든 PR은 2명의 코드 리뷰어가 승인해야만 머지할 수 있도록 설정했고, 각 PR에는 리뷰어를 지정해 활발한 코드 리뷰가 이뤄지도록 했습니다. 또한, Gemini Code Review를 활용해 기본적인 AI 리뷰를 함께 받아, 코드 품질을 더욱 향상시킬 수 있었습니다.

5. 문제 해결 경험

HttpOnly 쿠키와 Next.js API Route 처리

첫 주에는 HttpOnly 쿠키와 Next.js API Route를 다뤄야 했는데, 이게 생각보다 까다로웠다. HttpOnly 쿠키는 보안상 클라이언트에서 직접 접근할 수 없어서 모든 API 요청을 Next.js의 API Route를 거쳐 처리해야 했다. 처음에는 각 API마다 쿠키 설정을 일일이 해줬는데, 이게 너무 반복적이고 실수하기 쉬워서 apiProxy라는 헬퍼 함수를 만들어 자동화했다. 그런데 API마다 GET, POST 방식이 다르고 헤더나 바디 처리 방식도 제각각이라 결국 여러 케이스에 대응할 수 있는 헬퍼 함수들을 추가로 만들어야 했다. 각 API를 하나씩 테스트하면서 응답과 에러를 확인하는 과정도 꽤 시간이 걸렸다. 이 경험을 통해 HttpOnly 쿠키를 사용할 때는 정말 세심하고 반복적인 구현이 필수라는 걸 깨달았고, API 구현에서 인증이나 헤더, 바디 같은 세부 사항들이 얼마나 중요한지 체감할 수 있었다.

모달 상태 관리와 팀 협업 이슈

두 번째 주에는 모달 상태 관리와 타입스크립트, 그리고 팀 협업 문제가 동시에 터졌다. 가장 골치 아팠던 건 모달 안에 또 다른 모달이 떠야했던 문제였다. 처음 모달 설계를 한번의 하나의 모달만 표시될 수 있게 구현을 했지만, 모달의 종류에 따라 동시에 2개의 모달이 떠야했기 때문에 상태 관리를 완전히 분리해야 했다. 따라서 Zustand를 활용해서 따로 openModal, closeModal 함수를 만들고 React Portal과 Provider 패턴을 조합해서 해결했다.

팀 협업 측면에서는 한 팀원이 react-hook-form을 사용하면서 controlled 방식으로 바꾸려고 해서 고민이 됐다. 이렇게 하면 오히려 라이브러리의 장점을 잃게 되는 상황이었는데, 설득을 통해 uncontrolled 방식을 유지하면서 UI와 에러 처리 부분을 함께 조율했다.

리액트 쿼리 도입과 컴포넌트 구조 개선

세 번째 주는 리액트 쿼리 도입과 서버 컴포넌트 이해에 대한 문제가 주를 이뤘다. 리액트 쿼리를 팀에 도입하려고 했는데 팀원들이 적극적으로 사용하지 않아서 PR에서 직접 코멘트를 달아가며 쿼리 사용을 권장해야 했다. 한편으로는 서버 컴포넌트에서 클라이언트에서 처리해야 할 데이터 패칭을 시도하다가 역할이 혼동되는 상황도 있었다. 코드 리뷰를 하면서 컴포넌트에 로직이 너무 몰려 있는 경우가 많아서, 훅이나 유틸 함수로 분리하도록 제안하는 일이 잦았다. 이 시기에는 기술적인 문제보다는 팀의 코드 품질과 구조에 대한 고민이 더 컸던 것 같다.

찜 목록 로컬 저장소 구현의 한계

마지막 주에는 찜 목록 기능을 구현하면서 로컬 저장소의 한계를 실감했다. 찜 목록 API가 제공되지 않아서 클라이언트에서 로컬 스토리지를 직접 사용해야 했는데, 여러 사용자가 로그인할 수 있는 상황이라 유저 ID를 기준으로 찜 목록을 구분해서 저장해야 했다. 구현은 했지만 로컬 저장 방식의 한계가 명확했다. 다른 기기나 브라우저에서는 연동이 안 되니까 사용자 경험 측면에서 아쉬움이 많이 남았다. 게다가 API fetch 주소가 일관되지 않아서 나중에 수정할 때 더 힘들었다. 이런 경험을 통해 초기 설계의 중요성과 일관된 API 구조의 필요성을 절실히 느꼈다.

전체적인 깨달음

전체적으로 보면 처음에는 단순한 기능 구현에 집중했다가, 점차 팀 협업과 코드 품질, 그리고 사용자 경험까지 고려하게 되는 과정이었다. 특히 기술적 문제를 해결하는 것만큼이나 팀원들과의 소통과 설득도 중요하다는 걸 깨달았고, 완벽한 해결책이 없을 때는 현실적인 타협점을 찾는 것도 개발자의 중요한 역량이라는 생각이 들었다.

6. KPT 회고

Keep (잘한 점, 계속 유지할 것)

  • 미팅 시간을 모두 잘 지키고, 일정한 루틴을 유지하며 협업에 집중했다.
  • 새로운 제안에 대해 열린 태도로 의견을 나누어, 팀 내 소통이 자유롭고 유연했다.
  • 매일 데일리 스크럼을 통해 진행 상황과 이슈를 투명하게 공유했다.
  • 문제가 생겼을 때 혼자 오래 끌지 않고, 바로 다음날 팀원들과 공유하며 해결하려는 태도가 좋았다.
  • 각자의 역할에 대한 책임감이 강해, 주어진 업무를 안정적으로 수행했다.
  • PR과 코드 리뷰를 꾸준히 작성하며 코드 품질에 대한 피드백 문화가 잘 정착되었다.
  • 리뷰 내용이 구체적이어서 빠르게 문제를 파악하고 해결할 수 있었다.
  • 중간 회고를 통해 리팩토링 방향을 정리하며 구조 개선에 도움이 되었다.
  • 초기 폴더 구조, GitHub 세팅 등 기술적 기반을 잘 마련해 협업 속도가 빨라졌다.
  • API 분리와 react-query 연동을 깔끔하게 처리했으며, UI/UX 세부 요소까지 신경 써 완성도를 높였다.

Problem (문제점, 개선이 필요한 것)

  • 의견이 나뉠 때 결정을 애매하게 내리다 보니, 같은 논의가 반복되며 회의 시간이 길어졌다.
  • 피그마 디자인이 불명확해, 기능 구현 중 혼란이 생기는 경우가 있었다.
  • 커스텀 훅과 타입 파일이 많아지면서 폴더 구조 정리에 어려움이 생겼다.
  • 서버 컴포넌트 활용 기준이 모호해, 팀원 간 일관성 있게 사용하기 어려웠다.
  • 리팩토링에 시간이 많이 소요되어, 기능 개발 속도가 늦춰지는 상황이 발생했다.
  • PR 리뷰가 지연되거나 책임감이 불명확해, 리뷰 피로도가 높아지는 경우가 있었다.
  • 하나의 브랜치에 많은 양의 코드가 몰리며 서로의 작업 흐름을 파악하기 어려웠다.

Try (시도해볼 것, 개선 방안)

  • 회의에서는 두괄식 화법을 적극 활용해 시간 낭비를 줄이고, 결정된 내용은 반드시 기록으로 남긴다.
  • 폴더 구조와 파일 역할 기준을 다시 논의하고, 통일된 구조로 리팩토링한다.
  • 페이지마다 서버 컴포넌트와 클라이언트 컴포넌트를 명확히 구분해 개발 기준을 정립한다.
  • PR은 기능 단위로 세분화해 자주 머지하고, 이후 리팩토링은 별도로 진행하는 방식으로 전환한다.
  • 리뷰는 가능한 빠르게 진행할 수 있도록 책임감을 갖고 참여하며, 급한 경우 디스코드 등으로 리뷰 요청을 명확히 전달한다.
  • 브랜치 이름과 내용이 잘 맞도록 관리해 코드 흐름을 명확히 하고, 리뷰 피로도를 줄인다.

7. 개인 성장

이번 최종 프로젝트는 그 어느 때보다 많은 시간과 에너지를 쏟아부은 경험이었다. 특히 프로젝트 후반부에는 자잘한 오류나 예상치 못한 버그를 거의 전담하다시피 하며 수정했고, 마감 직전까지 코드를 붙잡고 있던 날들이 많았다. 정신적으로도 체력적으로도 쉽지 않았지만, 그 과정에서 실력적으로 많은 성장을 이뤘다고 느낀다. 단순히 기능 구현에 그치는 것이 아니라 사용자 경험을 고려해 자연스럽고 매끄러운 로그인·회원가입 흐름을 직접 설계하고 구현한 점은 개인적으로도 만족스러운 성과였다. 또한 UI와 UX적인 부분에서도 여러 디테일을 고민하며 팀원들과 의견을 주고받다 보니, 디자인 감각과 사용자 관점의 사고도 한층 발전할 수 있었다.

개발 프로세스에서 PR 리뷰를 주고받는 경험은 처음에는 다소 부담스럽게 느껴졌지만, 점차 여러 팀원의 코드를 읽고 피드백을 주고받는 과정에서 코드의 다양성과 스타일에 대한 이해가 넓어졌다. 특히 코드 품질과 협업 방식에 대해 더 깊이 고민하게 되었고, 리뷰를 통해 어떻게 더 명확하고 효율적인 코드를 작성할 수 있을지도 배울 수 있었다. 이전보다 더욱 체계적으로 문제를 분석하고 해결하는 습관이 생겼고, 협업과 커뮤니케이션의 중요성 또한 몸소 느낄 수 있었다.

이번 프로젝트는 단순한 과제나 결과물이 아니라, 실제 서비스처럼 운영하고 싶은 마음으로 임했던 만큼 개발자 개인으로서의 역량뿐만 아니라 팀원으로서의 책임감과 태도까지 모두 한 단계 성장하게 해준 의미 있는 경험이었다.

문의 사항이 있으시면 언제든지 개인 메일로 연락 주시기 바랍니다.

메일 보내기

© 2024. kimyoungho all rights reserved.