첫 팀 프로젝트 회고

LYM·2025년 8월 26일

프로젝트

목록 보기
1/1


UMC라는 동아리에서 팀을 구성하여 방학동안 프로젝트를 진행했다! 난 Node.js 백엔드 개발자 포지션으로 참여하였다.

프로젝트를 하는 동안 무사히 마칠 수 있을까 걱정하였지만 동아리원들끼리 으쌰으쌰하여 여유롭게 결과를 만들어 낸 것 같아 뿌듯하다.

개발기간에는 기록을 하지 못해서 프로젝트가 끝난 지금 프로젝트 과정을 돌아보고자 한다.

🎃 프로젝트 소개

  • 프로젝트 인원: 8명 (PM 1명, 디자이너 1명, 프론트 3명, 백엔드 3명)

  • 프로젝트: 스타트업 네트워킹 및 구인구직 플랫폼

  • 깃허브 링크: https://github.com/UMC-MyFit/my-fit-back

  • 협업: GitHub, Notion, Discord

  • 기술 스택

    • Frontend: React, Redux, Tailwind, Typescript
    • Backend: Node.js, Express, MySQL, Redis, Websocket, Oauth2
    • Infra: AWS EC2, RDS, S3, Nginx, GitHub Actions, PM2

👨‍💻나의 역할

  • ERD 설계 및 Prisma 스키마 작성
  • API 명세서 작성
  • 공통 응답 형식 및 에러 핸들링 코드 작성
  • 회원가입 및 로그인 기능 구현
  • 이력/활동 카드 기능 구현
  • 채팅/커피챗 기능 구현
  • 알림 기능 구현

🚗ERD 설계


프로젝트 첫 주에는 ERD 설계랑 Prisma 스키마만 작성했던 것 같다.

ERD쪽은 백엔드 팀장 형의 도움을 많이 받았다. 기획서를 보고 ERD를 빠르게 설계하는 것도 중요하구나를 느꼈다..

📄API 명서세 작성


2주차엔 일주일 내내 API 명세서만 작성했다 (작성하면서 빨리 API 구현하고 싶다는 생각밖에 없었다)

본격적으로 API를 구현하기 전에 어떤 API가 필요하고, 어떤 res, req 형태를 갖는지, 쿼리파라미터나 Params로 뭘 받아야 하는 지, 예외상황은 무엇이 있는지 설계하는 작업이다.

일주일 내내 저것만 작성하니까 이제 어떤 화면에선 어떤 API를 어떤식으로 써야할 지 자동으로 분석하게 된다😂

🧯공통 응답 & 에러 핸들링

3주차엔 일단 각 API를 구현하기 전에 공통 응답 포맷과 전역 에러 핸들링 틀을 먼저 잡았다.

API를 막 구현하기 시작하면 응답 모양이 제각각이 되기 쉬워서, 초기에 규약을 잡아두어 개발 속도를 높혔다.

🔐회원가입 및 로그인 기능 구현

3주차 부터 드디어 실질적인 API 구현 작업을 들어갔다. 로그인 방식을 세션 방식으로 구현할지, JWT로 구현할지 고민했는데 백엔드 개발자들과 회의를 통해 빠른 개발을 위해 세션 방식으로 구현하기로 했었다.

세션 방식으로 결정한 후, Passport.js Local 전략을 적용해 로그인 로직을 구성했고, 인증 성공 시 서버 세션을 생성해 쿠키로 전달하는 구조를 만들었다.

회원가입에서는 비밀번호를 bcrypt로 해시 처리하여 저장했고, 이메일 인증을 위해 Nodemailer로 인증 메일을 보내고, Redis에 인증 코드를 TTL과 함께 저장하는 방식을 구현했다.

회원가입 로직은 크게 아이디/비밀번호 입력 -> 개인정보 입력 -> 첫 이력/활동 카드 작성의 세 단계로 구성되어 있다. 그런데 여기서 구현하기 어려웠던 점이 하나 있었다. 이력/활동 카드 작성은 회원가입 단계에서만 필요한 것이 아니라, 가입 후에도 자유롭게 작성할 수 있는 기능이었기 때문에 API를 별도로 분리했고, 개인정보 입력까지만 완료하면 User 테이블에 유저 정보가 저장되도록 했다.

문제는 사용자가 이력/활동 카드 작성 화면에서 뒤로가기를 눌렀을 때 발생했다. 이미 User 테이블에 해당 이메일을 가진 유저가 생성되어 있는데, 가입이 완전히 끝난 상태는 아니어서 중복 회원으로 처리되어 중간에 멈춰버리는 경우가 생긴 것이다.

이를 해결하기 위해 User 테이블에 is_profile_completed 플래그를 추가하여 첫 이력/활동 카드가 작성되기 전까지는 이 값이 false로 유지되고, 해당 상태의 유저는 "미완성 회원"으로 간주되도록 했다. 회원 정보가 User 테이블에 생성된 상태에서 뒤로가기를 눌러서 이미 해당 이메일을 가진 유저가 User 테이블에 존재하지만 is_profile_completed가 false인 경우 해당 유저의 정보를 지우고 다시 생성하도록 하도록 로직을 설계하였다. 이 방식으로 뒤로가기 시 발생하는 불완전한 회원 데이터 문제를 안정적으로 처리할 수 있었다.

💳️이력/활동 카드 기능 구현


이력/활동 카드 기능은 유저가 자신의 이력을 카드 형태로 작성하는 공간이다. 처음에는 기본적인 카드 생성, 조회, 수정, 삭제 API를 빠르게 구현했는데, 필터링이 꼭 필요하다는 요구가 나왔다.

그래서 카드 목록을 불러올 때 단순히 모든 데이터를 반환하지 않고, Params 기반 필터링을 지원하도록 설계했다.

예를 들어 특정 유저의 카드만 보고 싶을 때는 ?ownerId=, 키워드를 검색하고 싶을 때는 ?keyword= 같은 방식으로 요청을 받을 수 있게 했다.

💬채팅/커피챗 기능 구현


채팅과 커피챗 기능은 이번 프로젝트에서 가장 복잡했던 부분 중 하나였다. 처음에는 단수히 1:1 메시지를 주고받는 구조만 구현하면 될 줄 알았는데, 실제로 프론트엔드와 연결하면서 고려해야 할 사항들이 많았다.

우선 채팅은 Socket.io 기반의 실시간 통신으로 구현했다. 메시지를 보낼 때는 DB에 저장하고, 동시에 연결된 상대방에게 바로 이벤트를 전송하는 방식이다. 하지만 문제가 하나 있었는데, 채팅방에 입장할 때 모든 메시지를 한 번에 불러오면 성능이 떨어진다는 점이었다. 이를 해결하기 위해 Redis에 최근 20개 메시지를 캐싱하고, 입장 시 캐시에서 먼저 불러오도록 설계하였다. 이렇게 하니까 채팅방 로딩 속도가 눈에 띄게 빨라졌다.

커피챗 기능은 채팅과 연결된 일정 관리 기능이라고 할 수 있다. 단순한 메시지가 아니라 "만나자"라는 요청이므로 별도의 CoffeeChat 모델을 두어 구현했다. 사용자가 커피챗을 요청하면 일정(날짜, 시간, 장소)이 생성되고, 상대방은 이를 수락/거절할 수 있다. 상태는 PENDING -> ACCEPTED/REJECTED -> CANCELED로 전이되도록 설계했다.

🔔알림 기능 구현


알림 기능은 실시간 알림이나 인앱 알림이 아니라서 기본적인 CRUD만으로 구현할 수 있었다.

별도의 Notification 테이블을 두고, 네트워크 신청, 피드 좋아요, 댓글 작성 같은 이벤트가 발생하면 해당 테이블에 새로운 레코드를 추가하는 구조다.

😅 아쉬운 점

이번 프로젝트를 진행하면서 몇 가지 아쉬운 점도 남았다.

첫 번째는 회원가입에서 OAuth 로그인을 구현하지 못한 점이다. 초기 설계 단계에서 OAuth(구글, 카카오, 네이버) 도입을 고려했지만, 세션 기반 로직과 이메일 인증 구현만으로도 시간이 빠듯해 결국 적용하지 못했다. 실제 서비스라면 접근성을 높이고 가입 장벽을 낮추기 위해 OAuth는 꼭 필요했을 텐데, 이를 구현하지 못한 것이 아쉬움으로 남았다.

두 번째는 알림 기능에서 중복 처리 로직을 완전히 해결하지 못한 점이다. 같은 게시글에 좋아요나 네트워크 신청을 계속해서 생성하고 취소하는 것을 반복하면 알림이 과도하게 쌓였다. 이러한 문제를 백엔드 딴에서 해결해보고 싶었는데, 당시엔 시간이 부족하여 단순 생성·조회 로직만 완성하는 데 그쳤다.

세 번째는 프로젝트 진행 중 코드 리뷰를 체계적으로 진행하지 못한 점이다. 대부분의 개발은 각자 맡은 기능을 빠르게 구현하는 데 집중했고, 주 1회 회의에서 구두로만 공유하는 경우가 많았다.

이러한 아쉬움들은 다음 프로젝트에서 꼭 보완하고 싶은 부분이다. OAuth 로그인 같은 핵심 기능은 간단한 토이 프로젝트를 진행하면서 꼭 적용해보고 싶다.


내 첫 팀 프로젝트는 좋은 팀원들을 만나 함께 했기에 끝까지 완주할 수 있었다고 생각한다.

개발 과정에서 나의 부족한 점도 많이 깨달을 수 있어서 더 성장하고 싶다고 느낀 계기가 된 것 같다.

profile
열정 열정 열정

0개의 댓글