Ask-It 프로젝트 회고

이지호·2024년 12월 31일
1
post-thumbnail

Ask-It은 네이버 부스트캠프 그룹 프로젝트 과정에서 진행한 프로젝트다. 6주 간 열정을 쏟았던 프로젝트 과정을 회고해보려 한다.

Ask-It 프로젝트 링크

💡프로젝트 배경

1. 그룹 프로젝트에 대한 기대감

내가 부스트캠프에 지원한 이유 중 하나가 바로 이 그룹 프로젝트에 있었다. 사실 나는 학교에서 작은 프로젝트를 경험해봤다. 학술제에 출품할 서비스를 만들다보니, 내부 구성보다도 시연하기 좋은 걸 만들어내는 데에 주안점이 있었다. 버그가 많고, 비효율적인 엉터리 코드를 작성했더라도 시연 영상이 보기 좋은 게 중요했다. 게다가 학기 중에 진행되었다보니, 중간에 시험 등의 이슈가 발생하면 쉬어가게 되었는데, 이렇게 흐름이 끊기는 게 좀 아쉬웠다. 결과적으로 학술제에서 좋은 성적을 거두긴 했으나, 서비스의 완성도 측면에서 아쉬움이 남았다.

네이버 부스트캠프를 통해 정해진 기간동안 팀원 다함께 몰입해서 완성도 높은 프로젝트를 해보고 싶었다. 지원할 때부터 이 그룹 프로젝트를 고대해 왔고, 실제로 지원 서류에 다음과 같이 썼을 정도였다.

Q. 부스트캠프에서 이루고자 하는 목표를 구체적으로 서술해 주세요.
A. 단순히 기능 구현에만 주안점을 두어 프로젝트를 진행했던 과거와 달리, 바로 유저를 받아 운영이 가능할 정도의 완성도 높은 프로젝트를 하고 싶습니다.

2. 팀 편성 및 주제 선정의 배경

이번 9기에서 팀은 선호하는 주제 기반으로 랜덤 편성 되었다. '실시간 관리 시스템', '영상 스트리밍', '위치 기반 서비스', '클라우드 서비스', '저작 도구', 자유주제 중에서 하나를 고를 수 있었다.

나는 이 중 '실시간'을 골랐다. 사실 나는 위 리스트에 나온 모든 주제를 경험해본 적이 없는 사람이다. 그 중 실시간을 고른 이유는 실시간 기능 자체가 현대 웹 서비스의 필수 요소이므로, 이번 기회에 경험해보면 언제든 큰 도움이 될 거라고 생각했기 때문이었다.

뿐만 아니라 다른 도메인의 경우에는 러닝 커브가 예상되었다. 6주 내에 '완성도 있는 프로젝트'를 만들겠다는 나의 목표를 이루기 위해 도메인 난이도를 현실적으로 조절할 필요가 있었다. 대신 얼른 완성한 뒤 추가적인 기능을 붙이거나 최적화를 시도하는 방향으로 발전시키고자 했다.

주제 기반 팀 편성 결과 우리 Web07 팀은 '실시간'을 주제로 4명이 모이게 되었다. FE 1명, BE 3명으로 구성되었고, 나는 백엔드를 맡았다.

💡핵심 경험

1. 불편함을 해결하는 서비스를 기획하기

1.1 마스터 클래스의 불편함

Ask-It은 실시간 Q&A 서비스이다. 이는 우리가 속한 부스트캠프 생활 과정에서 겪은 불편함을 해결해보고자 기획하게 되었다.

부스트캠프에는 <마스터 클래스>라고 불리는 수업 시간이 있다. 이 때에 마스터 분들께서 질의응답 시간을 열어주시곤 했는데, 그 과정에서 다음과 같이 구글 스프레드시트가 사용되었다.

스프레드 시트

기존에 사용하던 구글 스프레드시트는 공동 편집과 답변 아카이빙이 가능하다는 장점이 있었다. 하지만 익명의 누군가가 답변을 무단으로 수정하거나, 긴 문장이 칸을 넘어가면서 가독성이 떨어지고, 약 200명의 동시 접속자로 인해 일부 사용자는 편집 기능을 사용할 수 없는 등의 문제가 있었다. 이러한 아쉬움을 우리의 서비스로 해결해보고자 이 주제를 팀에 제안했다.

다행히 팀원 모두 공감해주었고, 논의를 통해 다음과 같은 핵심 기능을 구상했다:
1. 실시간 Q&A
2. 실시간 채팅
3. Q&A 세션 생성 권한 관리
4. 방문한 Q&A 세션의 아카이빙

1.2 개발 프로세스에 대한 목표

우리의 서비스는 부스트 캠프에서의 불편함을 해결하는 프로젝트였던 만큼, 빠르게 MVP를 개발하고 피드백을 받아 개선하자는 목표를 세웠다. 빠르게 만들수록 부캠 사람들에게 피드백 받을 기회가 많아지기 때문이다. 피드백을 받아 개선함으로써 '완성도'를 높일 수 있을 거라 생각했다.

뿐만 아니라 프로젝트가 얼추 완성되고 난 후에는 마스터 클래스에서 사용해달라고 제안드리자는 목표를 가지고 있었다.

2. 함께 일하기

2.1 Sprint 단위로 일하기

총 6주 동안 프로젝트가 진행되었다. 주차별로 스프린트를 나누어 진행했으며, 매주 금요일의 데모 시간에 우리의 서비스의 동작하는 모습을 보여주는 것을 목표로 했다.

일감 나누기

스프린트 1주차에는 기획을 마무리한 뒤, Epic-Story-Task 단위로 일감을 쪼갰다.

일감 쪼개기

스프린트별 백로그

다음으로는 주차별 백로그를 나누었는데, 이 때에 GitHub Projects를 활용했다. 처음엔 Jira를 사용하려 했다. 하지만 나를 포함하여 우리 팀 대부분이 Jira에 대한 경험이 없는 상황이었기에 Jira를 배우는 것도 비용일 수 있겠다는 생각이 들었다. 일단은 GitHub에서 제공하는 Projects를 사용하여 보고자 했다. Jira보다 지원하는 기능이 적다고는 하지만, 협업 툴에 익숙치 않은 우리 팀원에게는 이게 더 직관적일 수 있겠다는 생각이 들었기 때문이다. 또 GitHub Projects를 사용하면 Issue 연동이 가능하다는 장점도 누릴 수 있을 거라 생각했다.

백로그에 다음과 같이 Task 단위로 draft를 만들어 일감을 스프린트 별로 나누었다. 이후 개발할 때마다 이 draft들을 issue로 만들어 사용했다.

GitHub Projects

결과

초반에 MVP(Minimum Viable Product)를 명확히 정의하고 주차별 일감을 체계적으로 정리한 것이 프로젝트의 성공적인 진행에 큰 역할을 했다. 특히 Epic-Story-Task 구조로 일감을 세분화하면서 팀원 모두가 기획 의도를 정확히 이해할 수 있었고, 이는 개발 과정에서 소통 비용을 크게 줄이는 결과로 이어졌다.

백로그를 명확히 하고, 핵심 기능부터 만든 덕분에 우리 팀은 4주차에 이미 핵심 기능을 완성하고 시연할 수 있었다. 주요 기능인 Q&A 시스템, 실시간 채팅, 인증 시스템 등을 모두 구현했으며, 특히 Socket.IO를 활용한 실시간 통신 기능까지 안정적으로 작동하는 것을 확인할 수 있었다. 이후 5, 6주차에는 사용자 피드백을 바탕으로 UX를 개선하고, 테스트 코드 작성과 성능 최적화에 집중할 수 있었다:

주차기간주요 내용
Sprint 110/28 ~ 11/01프로젝트 초기 세팅 (모노레포, ESLint, CI/CD)
Sprint 211/04 ~ 11/08ERD 설계, API 설계, Prisma 모델 정의, 로그인, 랜딩 페이지 구현
Sprint 311/11 ~ 11/15Q&A 기본 기능(질문/답변 CRUD), 좋아요 기능, Swagger 문서화
Sprint 411/18 ~ 11/22Socket.IO 연동, 실시간 채팅 구현, Q&A API 연동, 질문 상태별 정렬
Sprint 511/25 ~ 11/29멀티 호스트 기능, 세션 종료 기능, 모니터링 로그 추가, UX 개선
Sprint 612/02 ~ 12/06단위 테스트 작성, DB 인덱싱, 예외 처리 로직 개선, FE E2E 테스트

2.2 빠르게 만들어 시연하고, 피드백 받아 개선하기

우리 부스트캠프에서 겪은 불편함을 해결하는 프로젝트이었기에, 주변 모두가 피드백 해줄 수 있는 유저였다. 최대한 이 환경의 이점을 살리기 위해 빠르게 만들어 시연하고 피드백 받아 개선하는 것을 우리 팀의 목표로 삼았다.

실제로 4주만에 완성하여 시연함으로써 다음과 같은 피드백을 받았고, 이를 반영하는 Sprint 5, 6주차를 보냈다. 부캠 분들이 적극적으로 사용해주시고 피드백 해주셔서 너무 감사했다.

멀티호스트 기능 요청

이전 채팅 불러오는 기능 요청

UX 피드백

2.3 오프라인/온라인 병행

우리 팀은 주에 2회는 오프라인으로 활동했다. 다함께 논의해야할 기획이나 발표 등에 있어서는 오프라인에서 활동하는 게 소통에 더 유리하다는 생각이 들었기 때문이다.

오프라인 활동을 하기에 앞서 가장 고민됐던 건, 마땅한 회의 장소가 없었다는 점이었다. 운이 좋게도 네 명 모두가 대학생이어서, 각 팀원의 학교를 방문하며 회의를 진행했다. 열심히 회의하다가 힘들 때면 한 번씩 산책을 하곤 했는데, 각 학교 캠퍼스를 걸으며 리프래시 하는 게 소소한 재미였다.

오프라인 활동을 하며 가장 좋았던 건, 팀원 간 유대감을 쌓을 수 있었다는 점이다. 6주 간 총 13회의 오프라인 활동을 하였는데, 매번 맛있는 걸 많이 먹으러 다니다 보니 많이 친해질 수 있었다. 덕분에 더 적극적으로 의견을 제시할 수 있는 편한 분위기가 조성되었다!

식사 (6주간 총 27번의 식사...)

2.4 적극적인 소통

데일리 스크럼

매일 아침 10시에 모여 진행상황을 공유하고 일일 계획을 세웠다. 각자의 태스크 진행 상황을 알 수 있어 좋았다.

데일리 스크럼

페어 프로그래밍

우리 팀은 처음에 questions, replies, users 이렇게 모듈을 나누고 담당자를 두어 개발을 시작했다. 담당자를 나누어야 빠르게 만들고 시연할 수 있을 거라 생각했기 때문이다. 첫 3주 동안은 백엔드 3명이 각각의 담당 모듈을 맡아 개발을 진행했다.

하지만 시간이 지날수록 문제가 하나씩 생겼다:

  • API 응답 형식이 제각각
  • 파일명/클래스명의 단/복수형 혼재
  • path alias가 일부분만 적용
  • Repository Layer의 중복 함수 발생
  • 검증 방식의 일관성 부족 (동일한 검증 로직이 Guard와 Service Layer에 혼재)

이러한 문제를 해결하기 위해 4주차부터는 페어 프로그래밍을 도입했다. 지금까지의 혼재된 코드를 모두 수정하였으며, 백엔드 백로그 전부를 세 명이 함께 페어프로그래밍을 통해 해결했다.

처음엔 페어 프로그래밍을 하는 것이 체력 소모가 심하고 어색했지만, 할수록 익숙해질 수 있었고, 앞서 언급한 문제들을 해결하면서도 재발을 방지할 수 있어 좋았다.

허들 문화

우리 팀은 의문점이 생기면 즉시 Slack의 허들 기능(단체 음성 통화)을 활용해 논의하는 문화를 정착시켰다.

'허갈'이라는 은어가 있을 정도로 자주 이용했다.

허갈의 의미

6주간의 허들 현황은 다음과 같았다:

주차오프라인 횟수온라인 허들 횟수온라인 허들 시간
1주차3회1회2시간 9분
2주차2회2회5시간 57분
3주차2회8회10시간 53분
4주차2회4회14시간 1분
5주차2회5회14시간 24분
6주차2회5회16시간 42분
총계13회25회64시간 06분

존중(숭배) 문화

우리 팀은 서로를 '신'이라고 부르며, 성 앞에 '신' 또는 '대'를 붙여 호칭했다.
그렇게 그라운드 룰을 정했던 건 아니지만, 그렇게 부를 수밖에 없었다!

신

'대' 호칭

2.5 문서화

우리 팀은 프로젝트의 핵심 경험을 골라내고, 그 경험을 가장 진하게 한 담당자를 정해 GitHub Wiki 기록했다. 서로가 무엇을 했는지는 알고 있었으나, 그 구체적인 과정에 대해서는 알기가 어려웠는데, 이 Wiki 문서화를 통해 서로의 경험을 읽어볼 수 있어 유익했다.

3. 기술적인 성장

3.1 근거 있는 의사 결정

프로젝트를 진행하면서 모든 기술적 의사 결정에 명확한 근거를 두고자 했다. 특히 기술 스택 선택 과정에서 많은 고민과 비교 분석을 진행했다.

예를 들어, ORM 선택 시에는 TypeORM과 Prisma의 장단점을 비교했고, 데이터베이스 선택에서도 PostgreSQL의 특성을 분석했다. 실시간 통신 구현을 위해서도 단순히 WebSocket을 채택하는 대신, Long Polling과 Server-Sent Events(SSE) 등 다양한 대안들을 검토한 후 최종 결정을 내렸다. 또 고민하고 결과를 내는 과정들을 GitHub Wiki에 기록하고자 노력했다.

또한 "꼭 필요한가?"라는 질문을 항상 던졌다. 다른 팀들이 Redis, Docker, MongoDB, Blue-Green 배포 등 다양한 기술을 도입하는 것을 보며 우리 팀도 도입해야 할지 고민했지만, 프로젝트의 상황을 고려했을 때 필요성이 낮다고 판단되는 기술은 과감히 제외했다.

이러한 접근 방식은 멘토님으로부터도 긍정적인 평가를 받았다:

Q: 발표에 대한 질문에 대해 명확한 근거와 경험을 바탕으로 답변하는 자세가 보였나요?

멘토님 답변: 궁금했던 부분에 대한 답변에서 나라도 그렇게 했을 거 같다라는 납득이 되었습니다. 질문에 대한 대답에 적절한 근거가 있어 보였습니다.

3.2 인프라 경험

CI/CD, 배포, 시스템 아키텍처 설계, https, Nginx까지... 인프라 쪽을 경험해본 적이 없었는데 이번 프로젝트를 하면서 이런 부분을 특히 많이 배울 수 있었다.

비록 내가 이 부분에 대한 담당자는 아니었지만, 아키텍처 구조도를 함께 그리고 NCP 사용 후기를 작성하면서 간접적으로 많은 것을 배웠다.

3.3 공부한 거 써먹기: index 걸어보기

Real MySQL 스터디를 통해 배운 인덱스 지식을 실제로 적용해볼 기회가 있었다.

사실 우리 프로젝트는 MySQL이 아닌 PostgreSQL을 사용하는 프로젝트였기 때문에 처음에는 MySQL 지식이 크게 도움되지 않을 것이라 생각했다.

하루는 Prisma가 어떻게 SQL을 보내는지 살펴보는 과정에서 DB 테이블 구조를 살펴보게 되었다. 그러다가 Foreign Key에 인덱스가 걸려있지 않다는 사실을 발견했다.

그렇다면 PostgreSQL은 왜 index를 걸어주지 않는지 등을 알아보았고, PostgreSQL의 인덱스 물리 구조 자체가 MySQL과 다르다는 사실을 알게 되었다.

이를 토대로 Foreign Key에 index를 걸어서 성능을 개선하는 경험을 했는데, 배운 걸 기반으로 탐구하고 써먹어볼 수 있어 굉장히 뿌듯한 경험으로 남아있다.

💡아쉬운 점

1. 유의미하지 못했던 테스트

Service Layer는 테스트가 꼭 필요하다고 생각해서 프로젝트 막바지에 급하게 단위 테스트를 작성하여 CI에 추가했다. 하지만 시간에 쫓겨 작성한 테스트 코드는 실질적인 의미를 갖지 못했다.

1월달 3주 동안 우리 팀은 다시 모여 리팩토링에 도전해볼 계획이다. 진정한 의미의 '리팩토링'을 위해서 이제는 정말 필요한 테스트 코드를 작성해보려 한다.

2. 부하 테스트 부재

우리는 네이버 부스트캠프에서 지원해준 NCP 크레딧을 받아 사용했다. NCP 서버에서는 제일 저렴한 서버도 vCPU 2개, 메모리 8GB의 고사양이었다. 알아보니 일반적인 스타트업들이 초기에 선택하는 서버보다도 좋은 수준이었다. 이로 인해 데모 과정 중에 서버가 힘들었던 적이 없었고, 부하 테스트의 필요성도 못 느꼈다.

하지만 백엔드 개발자로서 부하 테스트를 통한 병목 지점 발견과 개선은 중요한 과제라고 생각한다. 이 부분 역시 리팩토링 기간에 도전해볼 예정이다.

3. 권한 관리 코드의 한계

우리 서비스에는 슈퍼 호스트, 서브 호스트, 기명 참가자, 익명 참가자의 네 가지 사용자 역할이 있다. 각 역할마다 세션 종료, 질문 삭제, 답변 관리 등 서로 다른 권한을 가지는데, 이를 단순 분기문으로만 처리한 것이 아쉬움으로 남는다. 피드백을 받아 역할이 추가될 때마다 권한 관련 매 코드에 if문을 추가해야했기에 유지보수성이 떨어졌다.

프로젝트 막바지에 RBAC(Role-Based Access Control)와 같은 체계적인 권한 관리 방식을 알게 되었는데, 리팩토링 기간에 이를 적용해 개선해보고자 한다.

💡끝으로

이렇게 길고 자세한 회고록을 쓰게 된 건, Ask-It이 내게 처음으로 경험한 '딥한' 프로젝트였기 때문이다. 매 순간 치열하게 고민하고, 체계적으로 일하면서 성장하는 게 느껴져 즐거웠다. 또 완성되어가는 프로젝트를 볼 때마다 뿌듯함도 정말 컸다. 그래서 이 회고록에 더 많은 이야기를 담고 싶었고, 이 소중한 경험의 순간들을 놓치고 싶지 않았다.

이 모든 게 가능했던 건 우리 팀원들 덕분이다. 때로는 진지하게, 때로는 장난스럽게 서로를 격려하고 응원하면서 즐겁게 이 여정을 함께했다. 이런 값진 경험을 선물해준 우리 팀원들에게 진심으로 감사하다. 팀 대방인!

0개의 댓글

관련 채용 정보