[회고] 쉘위헬스를 마치며

Creating the dots·2021년 12월 23일
2

project-3-ShallWeHealth

목록 보기
25/26

쉘위헬스

쉘위헬스는 이러한 서비스를 제공합니다

'혼자 운동하긴 심심한데, 함께 운동할 수 있는 운동메이트를 찾을 방법이 없을까..?'
라고 생각해보신 적 있으신가요?

그래서 원하는 일시에 원하는 헬스장에서 자신과 비슷한 운동수준의 사람을 구할 수 있는 '쉘위헬스'를 기획하게 되었습니다.

쉘위헬스에서는 원하는 일시에 헬스장을 선택해 운동메이트를 찾는 서비스를 제공합니다. 게시물을 업로드하면, 신청할 수 있습니다. 이때 유저는 게시물을 매칭여부, 지역, 날짜 등으로 필터링해 조회할 수 있습니다. 매칭된 유저들은 실시간 채팅으로 소통할 수 있습니다.

매칭된 유저들은 함께 운동한 이후 서로를 추천 또는 신고를 통해 서로를 평가할 수 있습니다.

기획은 다음과 같이 이루어졌습니다

데이터베이스 스키마

와이어프레임

와이어프레임 보러가기

다음과 같은 기능을 구현했습니다

📍 랜딩페이지

  • 서비스에 대한 소개와 바로가기 버튼이 있습니다.

📍 회원가입

  • 닉네임과 비밀번호 유효성 검사를 통과해야합니다.
  • 가입한 이메일은 nodemailer로 전송된 메일로 접속해 이메일 인증을 거쳐야합니다.
  • crypto 모듈을 사용해 유저가 입력한 비밀번호에 salt를 추가해 암호화된 비밀번호를 데이터베이스에 저장합니다.

📍 로그인

  • 로그인 시 jwt 액세스 토큰을 생성해 쿠키에 저장합니다. 이때 액세스 토큰에는 비밀번호 등의 민감한 개인정보를 제외한 정보를 암호화해 생성합니다.

📍 소셜로그인 (카카오, 네이버)

  • 카카오로 소셜로그인 시 회원가입이 되어있지 않다면, 카카오로부터 유저의 이메일과 닉네임을 제공받아 db에 유저 정보를 생성합니다. 회원가입이 되어있다면, jwt 액세스 토큰을 생성해 쿠키에 저장합니다.
  • 네이버로 소셜로그인 시 클라이언트Id를 전달해 네이버로부터 토큰을 전달받습니다. 네이버의 액세스토큰을 사용해 유저의 네이버 이메일 정보를 조회합니다. 조회한 이메일로 회원가입되어 있지않다면, db에 유저 정보를 생성합니다. 회원가입이 되어있다면, jwt 액세스 토큰을 생성해 쿠키에 저장합니다.

📍 비밀번호 찾기

  • 가입한 이메일로 비밀번호 변경 링크가 담긴 인증메일(nodemailer)이 발송됩니다. 해당 링크로 접속해 비밀번호를 변경할 수 있습니다.

📍 메이트 모집

  • 일시, 헬스장, 운동 레벨 등을 선택할 수 있고, 파트너에게 메시지를 남길 수 있습니다. 게시물은 동일한 날짜에 1회만 작성할 수 있습니다. 만약, 이미 동일한 날짜에 신청한 데이터가 있는 경우에도 게시물 작성이 제한됩니다.

📍 매칭 게시판 조회

  • 날짜, 지역, 마감 여부 등으로 데이터를 필터링해 조회할 수 있습니다.
  • 헬스장 이름으로 게시물을 검색 조회할 수 있습니다.

📍 게시물 조회

  • 게시물 작성자가 작성한 운동부위, 3대 운동중량, 파트너에게 남긴 한마디, 운동 일시와 헬스장 위치 정보, 작성자 닉네임과 추천수 등을 확인할 수 있습니다.
  • 참가자는 신청 또는 이미 신청한 내역을 취소할 수 있습니다.

📍 채팅 기능

  • 신청이 성공적으로 이뤄진 경우, 두 유저는 실시간 채팅으로 소통할 수 있습니다. socket.io를 사용해 구현했고, 실시간 소통과 동시에 db에 데이터가 생성됩니다. 새로고침 시 db에서 데이터를 조회해 채팅창에 보여줍니다.
  • 예약시간에서 2시간이 경과되면, 채팅방은 비활성화되어 실시간 채팅기능이 제한됩니다.

📍 마이페이지 활동로그

  • 마이페이지에서는 자신의 닉네임과 가입한 이메일 정보를 확인할 수 있습니다.
  • 그동안 신청, 취소, 업로드한 게시물 기록을 확인할 수 있습니다.
  • 운동 메이트를 추천 또는 신고할 수 있습니다.

📍 마이페이지 내정보 수정 및 탈퇴

  • 닉네임은 중복확인 후 변경할 수 있습니다.
  • 비밀번호는 유효성 검사를 거친 후 변경할 수 있습니다.
  • 회원탈퇴를 진행할 수 있습니다.

📍 관리자 페이지

  • 관리자는 업로드된 게시물을 삭제할 수 있으며, 닉네임으로 게시물을 조회할 수 있습니다.
  • 관리자는 회원을 강제탈퇴시킬 수 있으며, 닉네임 또는 이메일로 유저정보(이메일, 닉네임, 모집횟수, 매칭횟수)를 조회할 수 있습니다.
  • 관리자는 접수된 신고내역을 확인할 수 있습니다.

📍 페이지네이션

  • 부모 컴포넌트에서 프롭스로 전달한 페이지 정보에 따라 페이징되며, 클릭된 페이징에는 'active' 클래스가 적용됩니다.
  • 다음,이전 버튼이 있으며 각각 클릭시 페이징이 1씩 커지거나 작아집니다.
  • 처음으로, 마지막으로 버튼이 있으며 각각 클릭시 첫 페이징과 마지막 페이징으로 이동합니다.

📍 다크모드 / 라이트모드

  • 로컬 스토리지에 테마 정보를 저장해 새로고침하거나 브라우저를 닫아도 유저가 적용한 테마가 유지됩니다.

맡은 역할

이번 프로젝트에서 백엔드 포지션을 맡았고, 다음과 같은 역할을 수행했습니다.

✅ 프로젝트 서버 세팅

npm init부터 필요한 모듈과 라이브러리 설치, 디렉토리와 파일 생성, sequelize 설정과 seed 파일을 생성하고 마이그레이션했습니다.

✅ api 작성

gitbook을 활용해 24개의 api를 작성했습니다. 서버에서 응답으로 보내줄 데이터에 대해서는 프론트 팀원들과 의논하며 정했고, 응답 예시를 작성해두어 기능 구현을 진행하며 프론트 팀원과 빠르게 소통할 수 있었습니다.

지난 2주 프로젝트와 다르게, 이번 프로젝트에서는 status code에러 핸들링에 중점을 두었습니다. 따라서, 상황에 따른 적절한 상태코드를 전달하기 위해 상태코드에 대해 공부했고, 에러가 발생한 경로와 메시지를 작성해두었습니다.

이는 실제로, 프로젝트에서 기능구현하며, 에러가 발생한 원인과 경로를 빠르게 파악하는데 도움이 되었습니다.

✅ 필터링 구현

매칭 게시판에서 유저는 게시물을 원하는 조건에 맞추어 필터링할 수 있습니다. 날짜와 매칭여부, 지역을 선택할 수 있습니다. 조건을 설정하지 않은 경우, 오늘 날짜로 예약된 모든 데이터를 조회합니다.

✅ 페이지네이션 구현

리액트 페이지네이션을 참고하여 프론트와 백을 구현했습니다. 프론트에서는 이전다음, 그리고 처음으로마지막으로 버튼에 페이징을 변경하는 이벤트를 구현했습니다. 페이징은 최대 5개가 노출됩니다.

유저가 페이징의 숫자를 클릭하거나 이전, 다음 등의 버튼을 클릭해 현재 페이지가 변경된 경우, 클라이언트에서는 해당 페이지가 포함된 url로 서버에 axios GET 요청을 보내게 됩니다.

따라서, 서버에서는 특정 개수만큼의 데이터를 클라이언트에 전달합니다. 이는 sequelize의 offsetlimit 옵션을 활용해 구현했습니다.

✅ 유사검색 구현

게시물 또는 유저를 검색할때, 검색어와 완전히 일치하지 않더라도 유사한 데이터를 조회할 수 있습니다. sequelizeoperatorOp.orOp.substring을 활용해 구현했습니다.

✅ 실시간 채팅 기능구현

소켓아이오를 사용해 실시간 채팅 서버 부분을 구현했습니다. 매칭된 두 유저는 생성된 에서 대화를 나눌 수 있습니다. 동시에 유저가 작성한 채팅은 데이터베이스에 생성되어 페이지 새로고침 시 데이터베이스에서 대화기록을 시간순서로 조회합니다.

✅ 배포자동화 및 https 배포

AWS의 ec2, s3, rds, codepipeline를 활용해 클라이언트와 서버의 배포 자동화를 구현했고, cloudfront, loadbalancer, acm, codedeploy를 사용해 https로 연결했습니다.

느낀점

이번 프로젝트에서 제가 중요하게 생각하며 느낀 점은 다음과 같습니다.

에러가 발생한 위치와 원인을 빠르게 찾자

많은 경우, 코드를 작성하는 시간보다 에러를 찾아 해결하는데 시간을 많이 보내곤 합니다. 따라서, 백엔드에서 할 수 있는 최선은 클라이언트로 하여금 에러가 발생했을때, 어떤 경로에서 무슨 이유로 발생했는지를 알려주는 것이라고 생각했습니다. 따라서, 서버 코드에서 분기를 나누어 status code와 에러 메시지를 구분해 응답했습니다.

또한, 백엔드 자체에서도 sequelize에서 logging 속성을 사용해 요청에 따른 raw query를 콘솔에 찍어 확인하였고, 에러가 발생했을때에도 콘솔창에서 확인할 수 있었습니다.

에러의 위치와 원인을 아는 것만으로도 에러해결 시간을 단축할 수 있었습니다.

👍잘 질문하는 방법

코드스테이츠를 하면서 30명이 넘는 사람들과 페어 프로그래밍을 진행했고, 프로젝트에서는 특히 프론트와 1대 1로 소통하는 일이 많았습니다. 에러가 발생할때, 줌에서 실시간으로 에러의 원인을 파악하고 해결했습니다. 저 또한 혼자 해결하지 못한 문제는 다른 팀원분들에게 줌을 요청해 함께 고민하고 해결할 수 있었습니다.

그런데, 줌으로 누군가의 코드를 읽고 문제를 파악한다는 것은 대면으로 하는 것보다 많은 노력이 필요한 일이었습니다. 때로는 네트워크나 음질 문제가 있기도 했고, 화면 공유라는 제한 때문에 상대방에게 디버깅을 할 때에도 상대방의 도움이 필요했습니다.

그래서 더욱 잘 질문하는 것이 중요하다고 느껴졌습니다. 저는 다음과 같이 질문을 하려고 노력했습니다.

- 현재 겪고있는 문제상황은 무엇인지 코드를 일부 첨부해 정리한다
- 이 문제를 해결하기 위해 참고한 링크들을 첨부하고 내용을 간략히 요약한다
- 문제가 발생한다고 생각하는 원인을 설명한다
- 상대방의 요청에 최대한 빠르게 응답한다

우리는 모두 배우고 있는 학생이고, 다른 사람의 코드를 보고 한번에 이해하는 것에 익숙하지 않기 때문에 코드를 보지 않고도 이해할 수 있을 정도로 충분히 설명하려고 했습니다.

잘 질문하는 것은 제 스스로 문제에 대해 충분히 이해하고 있음을 나타내기도 하며, 상대방으로 하여금 커뮤니케이션에 들일 수 있는 노력을 아낄 수 있는 꼭 필요한 태도라고 생각합니다.

앞으로도 모르는 것이 무엇인지 알고, "잘" 질문할 수 있는 주니어 개발자로 성장할 것입니다.

📝남는 건 오로지 기록뿐!

데브로그 확인하러가기
에러핸들링 확인하러가기
이번 프로젝트에서는 총 19개의 데브로그를 작성해 그날 한 일들을 기록했습니다. 또한 에러가 발생했을때, 이를 해결하는 과정을 기록해 총 8개의 에러 핸들링 로그를 기록했습니다.

그리고, 벨로그 블로깅 또한 꾸준히 작성해 25개 이상의 기록을 남겼습니다. 에러 핸들링 뿐만 아니라 공부하고 배운 내용도 잊지 않기 위해 작성했습니다.

매일 기록하면서 느낀 것은, 매일매일 내가 어떤 일을 했고, 어떤 문제를 겪고 해결했는지를 한눈에 확인할 수 있었습니다. 프로젝트를 진행하며 내가 잘하고 있는지, 그리고 과연 내가 정말 알고있는 것이 맞는지 스스로 의심될 때가 있었습니다. 그럴때마다 모두가 읽고 확인할 수 있는 공간에 글을 작성함으로써 책임감을 갖고 공부할 수 있었습니다.

기록들을 보며, 부족하지만 내가 무엇을 어려워했는지, 그리고 힘들었지만 극복해냈다는 점이 뿌듯했고, 동기부여를 얻었습니다. 앞으로도 꾸준히 기록하는 습관을 가질 것입니다.

QnA

서버에서 전달한 status code 기준은 무엇인가?
status code에 대한 기록 살펴보기

서버는 클라이언트 요청에 대해 알맞은 status code를 보내주어야합니다.

성공코드의 경우,

  • 200 Ok는 GET 요청 성공시 바디에 데이터를 보내야할때 사용했습니다.
  • 201 Created는 POST 요청 성공시 사용했습니다.
  • 204 No content는 200과 유사하지만, 바디에 데이터를 보내지 않아도 되는 경우, 사용했습니다.

에러코드의 경우,

  • 400 Bad Request는 클라이언트에서 필수로 전달해주어야할 파라미터가 부족한 경우 사용했습니다. 예를 들어, accesstoken이 없거나, body, query, path 데이터가 없을때 사용했습니다. - 401 Unauthorized는 유효하지 않은 액세스토큰을 사용한 경우 사용했습니다.
  • 403 Forbidden은 유효한 accesstoken이지만, 권한이 없는 경우에 사용했습니다.
  • 404 Not Found는 존재해야할 리소스가 존재하지 않는 경우 발생한 에러코드로 사용했습니다.
profile
어제보다 나은 오늘을 만드는 중

1개의 댓글

comment-user-thumbnail
2022년 2월 3일

안녕하세요 :) 블로그에 정말 많은 글을 정리하셨네요 ...
한 수 배워갑니다 ^^

답글 달기