코드잇 스프린트 고급 프로젝트 회고

2025-04-11

3월부터 시작된 마지막 부트캠프 팀 프로젝트를 최근에 마무리했습니다. 이번 프로젝트는 약 6개월간 이어진 부트캠프의 마지막 과제로, 그동안 배운 기술과 경험을 모두 녹여낼 수 있는 기회였습니다. 단순히 결과물을 만드는 것에 그치지 않고, 팀원들과 함께 기획 단계부터 서비스의 구조, 사용성, 확장 가능성까지 깊이 있게 고민하며 프로젝트를 완성해 나갔습니다.

무엇보다 마지막 프로젝트라는 부담감보다는 책임감으로 임하며, 그동안 부족했던 부분을 채우고자 스스로에게 더 높은 기준을 요구했던 시간이었습니다. 기술적으로는 단순한 구현이 아니라 왜 이렇게 구현해야 하는지, 더 나은 방법은 무엇인지 끊임없이 질문하고 고민하는 습관을 기를 수 있었습니다. 또한 다양한 이슈를 직접 해결해 나가며 특정 기술에 대해 더 깊이 이해하고 실무적으로 활용할 수 있는 자신감도 얻게 되었습니다.

이번 프로젝트는 결과물 이상의 의미가 있었습니다. 단기간에 성장할 수 있었던 이유는 팀원들과의 긴밀한 협업뿐만 아니라, 스스로 기술에 대해 진지하게 고민하고 배우려는 자세를 놓지 않았기 때문이라고 생각합니다.

지금부터는 저희 팀이 진행한 프로젝트에 대해 설명드리겠습니다. 전체적인 흐름보다는 구현 중심으로 간결하게 정리해 보여드릴 예정이며, 주요 기능과 기술적 고민이 담긴 부분들을 위주로 소개드리겠습니다.

[github repo] : https://github.com/kss761036/Epigram
[service url] : https://epigram-gilv.vercel.app/
[storybook url] : https://epigram-storybook.vercel.app/
[presentation pdf] : https://www.slideshare.net/slideshow/12-4-ppt-12-4-ppt-12-4-ppt/277795857


프로젝트 개요

에피그램 프로젝트 소개 및 선정이유

에피그램

에피그램은 명언을 공유하고, 감정을 기록할 수 있는 커뮤니티 중심의 웹 서비스입니다. 사용자는 명언을 매개로 다른 사람들과 소통할 수 있으며, 자신의 감정을 기록하고 시각화하여 감정의 흐름을 돌아볼 수 있는 기능을 제공합니다.

다른 좋은 주제들도 많았지만 에피그램을 선택하게 된 이유는, 감정 표현과 소통의 공간이 부족한 현실을 바탕으로, 감정 관리와 사용자 간 상호작용이 공존하는 플랫폼의 필요성을 느꼈고, 이를 실제 서비스 수준으로 구현해 볼 수 있는 주제라 판단하여 선택하게 되었습니다.

에피그램의 주요 기능

  • 💬 명언 공유 및 댓글 소통 기능
  • 📝 감정 기록 및 일일 감정 입력
  • 📊 감정 통계 시각화
  • 📚 명언과 태그 추가 가능 및 검색 기능 제공
  • 🔒 개인 로그인 제공 및 소셜 로그인 (카카오, 구글 지원)

개발과정

프로젝트 주요 기술 스택

  • nextjs
  • typescript
  • nextauth
  • react hook form
  • zod
  • tanstack query
  • chart.js
  • storybook
  • jest
  • cypress

내가 맡은 역활

  • 프로젝트 폴더 세팅
  • 스토리북 배포 설정
  • 디자인 토큰 설정
  • middleware 및 API proxy, axios interceptor 설정
  • 소셜 로그인 구현
  • 공용 컴포넌트 제작
  • 페이지 작업

프로젝트 폴더 세팅

프로젝트 진행에 앞서, 팀원들과 함께 유지 보수성과 협업 효율성을 높이기 위한 폴더 구조에 대해 충분히 논의하였습니다. 그 결과, 기능과 목적에 따라 역할별로 명확히 구분된 구조를 설계하였고, 각자의 작업 범위가 명확해짐에 따라 개발 과정에서도 보다 원활한 협업이 가능했습니다.

  • apis 폴더에는 각 기능별 service, type, queries 파일을 위치시켜 API 관련 코드를 모듈화
  • 페이지 전용 컴포넌트는 app 폴더 내부에서 해당 페이지 디렉터리 하위의 private 폴더에 작성

에피그램 프로젝트 폴더셋팅


스토리북 배포 설정

PR이 제출되거나 main 브랜치에 머지될 때마다, 자동으로 Storybook 프리뷰 링크가 생성되도록 GitHub Actions를 설정하였습니다. 이를 통해 각 컴포넌트의 구현 결과를 쉽게 확인하고, 빠르게 리뷰할 수 있는 개발 흐름을 만들 수 있었습니다.

에피그램 프로젝트 스토리북 배포 설정


디자인 토큰 설정

Tailwind CSS를 사용하는 프로젝트였기 때문에, 일관된 UI 구현과 유지 보수를 위해 색상, 타이포그래피 등의 디자인 토큰을 설정하였습니다. 특히 Tailwind CSS가 v4로 업데이트되면서 설정 방식에 변화가 있었고, 새로운 방식에 맞춰 @theme 지시문을 활용해 토큰을 적용했습니다. 덕분에 전체적인 스타일 관리를 보다 체계적으로 할 수 있었고, 컴포넌트 간의 스타일 일관성도 자연스럽게 유지되었습니다.


middleware 및 API proxy, axios 설정

사용자 인증이 필요한 페이지에서는 Next.js의 미들웨어 기능을 활용하여, NextAuth의 세션이 존재하지 않을 경우 자동으로 로그인 페이지로 리다이렉트되도록 처리하였습니다. 이를 통해 불필요한 페이지 접근을 사전에 차단하고, 보다 안전한 사용자 흐름을 구현할 수 있었습니다.

middleware

백엔드 API 호출 시에는 Next.js의 catch-all segment를 활용하여, 프론트엔드에서 발생하는 API 요청이 먼저 Next.js 서버를 거치도록 구성하였습니다. 이 과정에서 axios의 request interceptor를 사용해 토큰을 자동으로 헤더에 포함시킨 후 백엔드 서버로 요청을 전달하도록 처리하였습니다.

api proxy


소셜 로그인 구현

프로젝트의 전체 인증 흐름은 NextAuth를 기반으로 구성하였습니다. 사용자의 로그인 상태를 전역적으로 관리하고, 세션 기반으로 접근 제어가 필요한 페이지를 보호하는 데 활용했습니다.


공용 컴포넌트 - 아이콘

다양한 상황에서 재사용할 수 있도록 size와 color를 동적으로 받을 수 있는 유연한 구조로 구현하였습니다. 

아이콘 컴포넌트 스토리북


공용 컴포넌트 - 아바타

이미지가 없는 경우에도 사용자 정보를 직관적으로 표현할 수 있도록 유저네임의 첫 글자를 활용한 폴백 처리까지 함께 설계하였습니다. 이를 통해 예외 상황에서도 사용자 경험을 해치지 않도록 고려하였고, 안정적인 UI 구성에 기여할 수 있었습니다.

아바타 컴포넌트 스토리북


공용 컴포넌트 - 드롭다운

공용 드롭다운 컴포넌트는 확장성과 접근성을 고려하여 설계하였습니다. 기본이 되는 베이스 드롭다운 컴포넌트를 먼저 제작한 뒤, 다양한 상황에 맞는 드롭다운 UI들이 해당 베이스 컴포넌트를 상속하거나 조합하여 파생될 수 있도록 구성하였습니다.

또한, 컴파운드 패턴과 Context API를 활용하여 드롭다운 내부의 상태 및 동작을 유연하게 관리할 수 있도록 하였고, W3C의 WAI-ARIA 패턴 가이드를 참고하여 키보드 내비게이션, 포커스 등 접근성 관련 기능도 함께 개선하였습니다.

  • 베이스가 되는 드롭다운을 설계하고, 파생되는 UI들이 해당 베이스 드롭다운을 상속하도록 함
  • 컴파운드패턴과 콘텍스트를 이용하여 컴포넌트를 제작
  • W3C WAI를 참고하여 접근성 관련 기능 개선 (https://www.w3.org/WAI/ARIA/apg/patterns/)
<Dropdown>
  <DropdownTrigger>버튼</DropdownTrigger>
  <DropdownMenu direction='horizontal'>
    <DropdownItem>아이템1</DropdownItem>
    <DropdownItem>아이템2</DropdownItem>
    <DropdownItem>아이템3</DropdownItem>
  </DropdownMenu>
</Dropdown>

공용 컴포넌트 - 감정차트

감정 차트 컴포넌트는 Chart.js를 커스터마이징하여 도넛 형태의 차트로 구현하였습니다. 단순히 데이터를 내부에서 처리하는 방식이 아닌, 외부에서 데이터를 주입받아 렌더링하는 구조로 설계함으로써 컴포넌트의 재사용성과 테스트 용이성을 높였습니다.

또한, 데이터 전달에 혼선이 생기지 않도록 명확한 데이터 인터페이스를 정의하였고, 다른 팀원들도 쉽게 사용할 수 있도록 타입 구조를 구체화하였습니다.

  • chart.js를 커스텀하여 도넛차트 구현
  • 데이터를 내부에서 가져오는 것이 아니라, 주입하는 데이터를 노출하는 방식으로 컴포넌트를 설계
  • 데이터 주입에 혼선이 없도록 데이터 인터페이스를 구체적으로 작성하여 다른 팀원이 사용해도 문제가 없을 정도로 작성

감정차트


페이지 작업 - 검색페이지

  • zustand의 persist를 활용하여, 최근 검색한 키워드를 기억하도록 제작
  • tanstack query의 infinite query를 사용하여 무한 스크롤을 구현

페이지 작업 - 피드 리스트 페이지

  • zustand의 persist를 활용하여, 사용자가 최근 선택한 리스트 타입을 기억하도록 제작

페이지 작업 - 피드 상세 페이지

오픈그래프 이미지


문제 해결 경험

프로젝트 기간이 비교적 길었던 만큼, 단순한 기능 구현에 그치기보다는 기술적인 흐름을 더 깊이 이해하고, 문제를 직접 해결해보는 경험을 쌓는 데 집중하고자 했습니다.

문제가 발생했을 때는 단순히 검색에 의존하기보다는 공식 문서와 레퍼런스를 꼼꼼히 읽고, 지금 구현하고 있는 기능의 동작 원리와 구조에 대해 스스로 질문하며 풀어보려는 태도를 유지했습니다. 이러한 과정 속에서 단순한 구현 이상의 통찰과, 문제를 마주했을 때 어떻게 접근하고 해결할지를 고민하는 습관을 기를 수 있었습니다.


배운 점, 성장 포인트

이전보다 성장했다고 생각하는 부분

  • PR제출 시 내용을 상세하게 적으려고 했습니다.
    • 단순히 작업 내역만 나열하는 것이 아니라, 해당 코드를 작성하게 된 이유와 설명을 함께 적으려 노력했습니다.
    • 제가 고민하고 풀어낸 내용들이 다른 팀원들에게 도움이 되고, 공유될 수 있다면 좋겠다는 생각으로 문서화에 더 신경을 썼습니다.
  • 코드리뷰에 적극적으로 참여
    • 이전 프로젝트보다 조금 더 저의 의견을 내는 것에 두려워하지 않고, 코드 리뷰에 적극적으로 코멘트를 달았습니다.
    • 덕분에 단순한 피드백 이상의 기술적인 대화를 나눌 수 있었고, 더 많은 소통을 통해 팀 전체의 퀄리티를 높일 수 있었습니다.
  • 인증의 흐름을 제대로 파악한 점
    • 소셜 로그인을 구현하면서 NextAuth를 깊이 있게 학습하게 되었고, 이를 통해 프로젝트의 인증 흐름을 명확히 이해할 수 있었습니다.
    • 단순한 사용에 그치지 않고, 구조를 이해하고 직접 응용해보는 경험을 통해 기술적 자신감도 키울 수 있었습니다.
  • nextjs의 런타임환경까지 고려한 코드 작성
    • 프로젝트를 배포하는 과정에서 런타임 환경 차이로 발생하는 문제를 직접 겪어보며, 런타임 환경이 개발과 배포에 어떤 영향을 미치는지 이해할 수 있는 좋은 기회가 되었습니다.
  • 직접 구현한 UI에 웹접근성을 체크함
    • 퍼블리셔로 근무중일때에는 접근성을 기본적으로 지켜왔지만, 이번 부트캠프 프로젝트에서는 놓친 부분이 많다는 것을 느꼈습니다.
    • 이를 계기로 뒤돌아보는 시간을 가졌고, 직접 만든 UI에 접근성 기준을 다시 적용해보며 개선할 수 있었습니다.
  • 문제를 스스로 해결하기 위해 고민하는 시간을 가져본 것
    • 막혔을 때 단순히 해결 방법을 검색하기보다는, 공식 문서를 꼼꼼히 읽고 기능의 동작 원리를 파악하려고 했습니다.
    • 이러한 과정들이 쌓이면서 문제를 대하는 시선이 달라졌고, 혼자서 구조적으로 접근해보는 연습이 되었습니다.

아쉬웠던 점

  • 테스트코드가 익숙하지 않아서, 서툴렀던 점
    • 어떤 부분을 테스트해야 효과적인지 판단하는 감각이 부족했습니다.
    • 불필요한 테스트를 작성하거나, 반대로 꼭 필요한 부분을 놓치는 일이 있었고, 그만큼 테스트 코드도 설계처럼 고민이 필요한 작업이라는 점을 체감하게 되었습니다.
    • 다음 프로젝트에서는 더 전략적으로 테스트를 작성하는 연습을 해보고 싶습니다.
  • 더 많은 리팩토링을 많이 하지 못한 점
    • 개선하고 싶은 부분이 있었지만, 프로젝트에는 기한이 있다는 원칙을 설정했고
      일정 내에 기능 완성과 안정성을 우선으로 두었습니다.
    • 아쉬움도 있었지만, 정해진 시간 내에 우선순위를 판단하고 결정을 내린 점은 잘한 선택이라고 생각합니다.

협업 프로젝트를 하면서 얻은 느낀 점

  • 지난 5개월간 팀원들이 눈에 띄게 성장해온 만큼, 각자가 새롭게 알게 된 기술이나 개발 경험들을 자연스럽게 공유하는 문화가 정말 좋았습니다.
    • 다른 팀에서 활동하던 팀원들과 한 팀이 되어, 각자의 팀에서 좋았던 개발 경험들을 공유하고
      이를 합의에 따라 채택해 나가는 과정이 쌓이면서, 점점 ‘진짜 팀 프로젝트’를 하고 있다는 느낌을 받았습니다.
  • 내가 선호하는 방식이 모두에게 정답은 아니라는 것을 체감했습니다.
    • 프로젝트는 나 혼자만의 방식으로 진행할 수 없기에, 다른 팀원들도 쉽게 이해하고 납득할 수 있는 방향을 찾으려는 과정 자체가 매우 의미 있었고, 그것이 이번 프로젝트 기간 동안 얻은 가장 큰 배움 중 하나였습니다.