최종 발표 대본 #515
Yongmin0423
started this conversation in
Discussions
최종 발표 대본
#515
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
1팀 프로젝트 발표 대본 (수정본)
1. 안녕하세요. 1팀 발표를 맡은 유용민입니다. 지금부터 1팀의 프로젝트 발표를 시작하겠습니다.
2. 발표는 다음과 같은 순서로 진행하겠습니다.
3. (슬라이드 넘기기)
4. 저희 팀은 프로젝트 주제로 글로벌 노마드를 선택했습니다.
액티비티 플랫폼이라는 도메인의 매력과 함께, 제한된 기간 내에 구현 가능성과 완성도를 동시에 충족할 수 있는 적절한 난이도라고 판단했습니다.
5. 프로젝트에 사용한 주요 기술 스택입니다. 프레임워크는 Next.js, 스타일링 도구는 Tailwind CSS를 사용했으며, API 통신에는 ky와 TanStack Query를 활용했습니다.
6. 프로젝트는 Feature-Based, 즉 기능 기반 구조로 설계했습니다. Next.js의 앱 라우터 컨벤션을 기반으로,
app폴더에는 라우팅을 위한page.tsx파일만 배치했습니다. 각 도메인별 컴포넌트와 훅은domain폴더에서 관리하고, 여러 곳에서 공통으로 사용되는 모듈은shared폴더에 통합하여 재사용성을 높였습니다.7. (슬라이드 넘기기)
8. 저희 팀은 화면에 보이시는 것과 같이 역할과 책임을 나누어 프로젝트를 체계적으로 진행하였습니다.
9. 다음으로 프로젝트 수행 절차에 대해 설명드리겠습니다.
저희는 프로젝트 시작에 앞서 킥오프 미팅을 통해 코드 컨벤션, Git 전략, 그리고 프로젝트의 전체적인 아키텍처에 대한 표준을 수립했습니다.
11. 저희는 업무 효율성을 높이기 위해 6일 단위의 스프린트 방식으로 프로젝트를 운영했습니다. 각 스프린트마다 주요 마일스톤을 정의하였습니다.
12 스크럼은 디스코드로 진행하고, 데일리 스크럼을 통해 팀원 간 진행 상황 및 블로킹 이슈를 신속하게 파악하고 해결하였습니다.
13. 스프린트를 진행하는 동안에는 Github Projects의 칸반 보드를 적극 활용했습니다. 이를 통해 팀의 전체적인 진행 상황과 작업 현황을 시각적으로 관리하고, 태스크의 우선순위를 명확히 하여 개발을 진행했습니다.
14. 매 스프린트가 끝날 때마다 팀 회고를 진행했습니다. 회고를 통해 다음 스프린트 개선 방향을 도출하고, 브랜치 통합 후 QA/QC를 진행하여 진행 상황을 점검하고 목표 달성 여부를 파악하였습니다.
15. 이번 프로젝트에서는 단순히 요구사항을 구현하는 것을 넘어, 개발 중 마주친 문제들을 팀원들과 함께 깊이 있게 고민하고 해결하는 과정을 모두 문서로 남겼습니다. 이를 통해 개개인의 문제 해결 역량을 강화하고, 팀의 귀중한 기술 자산으로 만들고자 노력했습니다. 모든 논의 및 해결 과정은 Github Discussion에 기록되어 있습니다.
16. 또한, Storybook을 도입하여 저희가 만든 공통 컴포넌트의 UI를 체계적으로 문서화했습니다. 덕분에 팀원 누구나 각 컴포넌트의 사용법과 동작 방식을 명확하게 파악하고 일관된 UI를 유지할 수 있었습니다.
17. 이제부터 각 도메인별 주요 구현 내용에 대해 설명드리겠습니다.
18. 먼저 로그인 및 회원가입 기능입니다. 보안 강화를 위해 http-only 쿠키를 사용했으며, 회원가입 시 별도 과정 없이 자동 로그인되도록 구현했습니다. 또한, 입력 중 페이지를 이탈하더라도 세션 스토리지를 통해 작성 내용이 유지되도록 하여 사용자 편의성을 높였습니다.
20. 메인 페이지는 기존 키워드 검색만 가능했던 구조에서, 날짜와 위치 검색까지 확장해 사용자 탐색 흐름을 유연하게 만들었습니다. 검색창은 서버 선 렌더링으로 빠르게 인터랙션이 가능하고, 오토포커스나 키보드 접근성 같은 세부 UX도 함께 개선했습니다.
인기 체험 캐러셀은 서버 프리페칭 기반으로 초기 로딩 속도와 SEO 성능을 확보했고, 스크롤 위치 계산도 뷰포트 기준으로 정밀하게 처리했습니다.
액티비티 리스트와 필터는 캐러셀과 독립적인 Streaming SSR로 구성했고, URL 쿼리 기반 필터 구조로 검색 친화적인 URL 설계를 적용했습니다. 데이터 깜빡임 없이 부드럽게 전환되도록 상태 처리를 다뤘습니다.
21. 상세 페이지는 서버 컴포넌트를 기반으로 구성하여 초기 로딩 성능을 최적화하고, 상호작용이 필요한 부분은 클라이언트 컴포넌트로 분리했습니다.
체험 상세 데이터는 ISR로 렌더링하여 사용자가 페이지에 빠르게 접근할 수 있도록 했습니다.
리뷰 데이터는 **SSR 방식을 적용해, 초기 데이터를 서버에서 미리 렌더링하고 이후 추가 데이터는 TanStack Query로 비동기적으로 불러오도록 구현했습니다.
예약 가능 날짜와 지도처럼 사용자의 상호작용이 필수적인 영역은 컴포넌트화 하여 CSR 방식으로 처리했습니다.
22. 예약 달력은 일반 사용자와 호스트에 따라 다른 정보를 보여주도록 예외 케이스를 처리했으며, 이미지를 클릭하면 다이얼로그를 통해 원본 크기로 선명하게 확인할 수 있는 기능을 추가했습니다.
24. 체험 등록/수정 페이지는 정적인 콘텐츠가 거의 없고, 사용자와의 상호작용이 필수적입니다. 또한 페이지 이탈 방지 기능의 필요성을 고려하여 전체를 CSR, 즉 클라이언트 사이드 렌더링 방식으로 구현했습니다.
25. 사용자가 양식을 수정하다가 페이지를 이탈하려고 할 경우, 데이터 손실을 방지하기 위해 React Hook Form의
isDirty상태를 감지하여 커스텀 다이얼로그를 통해 재확인하도록 구현했습니다.26. 이미지 업로드 처리 방식은 클라이언트에서
createObjectURL을 사용해 이미지를 선택하는 즉시 미리보기를 보여주고, 실제 서버 업로드는 최종 '제출' 시에만 동작하도록 하여 불필요한 서버 부하를 최소화했습니다.27.
예약 내역 페이지는 여러 API 호출해야하는 페이지였습니다. 그래서 초기 페이지 진입 시, 여러 API 요청에 필요한 핵심 데이터를 SSR 방식으로 서버에서 미리 받아오도록 구성했습니다.
이렇게 받아온 데이터를 기반으로, 이후에는 실제로 필요한 시점에만 하위 API 요청이 이루어지도록 Lazy Loading 방식으로 처리했습니다. 또한 예약 승인이나 거절 같은 상태 변경이 발생했을 때, 캐시 무효화를 통해 변경된 데이터가 UI에 즉각적으로 반영되도록 구현했습니다.
28. 에러 처리는 계층별 에러 처리 구조로 설계해, 전역에서 페이지 그룹, 컴포넌트, API에 이르는 다층 에러 처리 구조로 설계하였습니다.
31. 특히 API 에러의 경우, HTTP 상태 코드에 따라 에러 메시지와 UI 피드백을 다르게 제공하여 사용자에게 일관된 경험을 주도록 처리하고, 401에러의 경우 middleware에서 전역전으로 관리하도록 하였습니다.
32. 개발 환경에서는 errorBoundary를 통해 오류 상세 정보가 나오도록 구현하여 디버깅을 쉽게 할 수 있도록 설계하고, 테스트 페이지도 .dev 확장자는 빌드에 포함되지 않도록 설정하였습니다.
34. 다음으로 저희 서비스가 실제로 동작하는 모습을 보여드리도록 하겠습니다.
37. (시연 영상 재생)
38. 이어서 프로젝트를 진행하며 저희 팀원들이 겪었던 기술적 고민과 이를 해결한 사례를 공유해 드리겠습니다.
39. [유용민] 저는 체험 등록/수정 페이지의 복잡한 폼을
useActionState로 관리하려 했습니다. 하지만 이 훅은 서버에서 페이지를 리렌더링하기 때문에, 클라이언트에서 생성한 이미지 미리보기 URL이 유효성 검사 실패 시 사라지는 문제가 있었습니다. 결국 저는useActionState를 포기하고,FormData와 일반적인 submit 함수로 전환했습니다. 이 경험을 통해 새로운 기술을 무조건 도입하기보다, 문제 상황에 가장 적합한 기술을 선택하는 것의 중요성을 깨달았습니다.40. 서연님은 알림 기능을 구현해야 했지만, WebSocket이나 SSE를 사용할 수 없는 환경이라 실시간 반영이 어려웠습니다. 이에 10초 주기로 알림을 요청하는 폴링(Polling) 방식을 대안으로 도입했습니다. 또한, Zustand를 활용해 이전 상태와 신규 상태를 비교하여 새로운 알림이 있을 때만 'red-dot'을 표시하는 시각적 피드백을 제공했습니다.
41. 재현님은 메인 페이지에서 개인화된 검색 경험을 제공하기 위해, ‘날짜’와 ‘위치’ 기반 검색 기능을 새롭게 도입했습니다. 그러나 위치 정보는 전체 액티비티 API에서 제공되는 반면, 날짜 정보는 각 액티비티의 상세 API에서만 확인 가능해, 사용자 검색 시 매번 N개의 상세 API를 호출해야 하는 비효율적인 구조였습니다.
이를 해결하기 위해 Cloudflare Workers와 KV Storage를 활용한 Edge-level ETL 계층을 구축하고, 간단한 액티비티 전용 백엔드를 Worker 내에 직접 구현했습니다. 이로써 기존 API의 한계를 보완하고 병목을 제거하여, API 호출 횟수를 O(N)에서 O(1)로 줄이고, 평균 응답 속도도 약 94.7% 개선할 수 있었습니다.
42. 시은님은 비밀번호 유효성 검사의 비효율을 개선했습니다. 기존에는 유효성 확인을 위해 서버와 통신해야 했고, 이는 불필요한 네트워크 비용을 발생시켰습니다. 시은님은 Zod의 refine을 활용하여 API 통신 없이 클라이언트 단에서 즉각적으로 유효성을 검증하도록 개선하여 빠르고 효율적인 피드백을 구현했습니다.
43. 이외에 다양한 기술 회고 및 개선이 있었지만 자세한 내용은 github의 discussion에서 확인하실 수 있습니다.
45. 마지막으로 저희가 설정했던 목표 달성도와 팀원들의 종합적인 회고를 말씀드리고 발표를 마무리하겠습니다.
46. 저희는 프로젝트 시작 전 다음과 같은 목표를 세웠습니다. 이 지표들을 기준으로 자체적으로 평가한 결과, 목표의 약 90%를 달성했다고 결론 내렸습니다.
47. 프로젝트를 진행하면서 팀의 종합적인 회고 내용을 말씀드리겠습니다.
외부 SDK 연동과 복잡한 API 조합 처리 등 실전 중심의 웹 개발 경험을 할 수 있었습니다.
OAuth 및 BFF 구조 설계, 캐싱 전략 적용 등을 실제로 해보며 보안과 성능을 고려하며 코드를 설계하는 경험을 할 수 있었습니다.
SRP,DRY,KISS 등 핵심 개발 원칙을 실제 설계와 구현에 일관되게 적용하며 책임 분리와 모듈화의 중요성을 체감했습니다.
또한 기능 구현에 기술 도입의 목적과 맥락을 명백히 하며 아키텍처 의사결정을 수행하는 경험을 할 수 있었습니다.
이상으로 1팀의 발표를 마치겠습니다.
질문이 있으시면 편하게 해 주시기 바랍니다.
감사합니다.
Beta Was this translation helpful? Give feedback.
All reactions