2차 프로젝트 회고록

김민재·2021년 11월 7일
1

Archive Project

목록 보기
3/5
post-thumbnail

1. 💻 Team Linked_IT 📡

  • 안녕하세요 저희는 'Linked_In' 사이트의 클론 코딩을 진행하게 된 Linked_IT(링크드 잇)입니다.

1_1> 👇 아래 시연 영상이 재생됩니다. (Linked_IT)

Linked_IT 유튜브에서 보러가기

1_2> 🌟 프로젝트 소개

  • 프로젝트 사이트 소개 : 링크드잇은(Linked_IT) 개발자들의 소셜 커뮤니티 역할과 개발 관련 채용 관련 정보들을 조회하고 검색할 수 있는 비즈니스 인맥 사이트 입니다.
  • 프로젝트 목표 : 저희는 링크드인의 SNS와 RECURIT 서비스를 중점에 두고 해당 서비스를 개발자라는 타겟 유저들이 이용할 수 있는 사이트를 구축해보기로 했습니다.
  • 진행기간 : 2021년 10월 25일 ~ 2021년 11월 5일(12일, 프론트 5명과 백앤드 2명이 참여)
  • 진행기간 : 2021년 10월 25일 ~ 2021년 11월 5일(12일)
  • 프로젝트 참여자

2. 🛠 기술 스택

2_1> ⛏ FrontEnd 기술 스택

  • React Hook
  • Router
  • Style component
  • Git & GitHub

2_2> 🔧 BackEnd 기술

  • Node.js
  • Express
  • MySQL
  • Restful API
  • Bcrypt, JWT
  • Git & GitHub
  • Social Login API

3. BackEnd 구현 기능

3_1> ⛓ 프로젝트 역할 및 구현 내역

  • 프로젝트 역할 : 프로젝트 PM 및 백앤드 리드 역할
  • 프로젝트 구현 내역:

1> 백앤드 초기세팅 및 DB 모델링 설계 및

2> 채용공고 페이지 API, 피드 페이지 API, 검색 API 생성

3_2> 🔧 역할 상세 내역

  • 2_0. 백앤드 초기 세팅 및 모델링 전체 설계
  • 2_1. 채용 공고 데이터 가져오기 기능
    • 채용공고 리스트 API
    • 채용공고 디테일 리스트 API
    • 필터가 적용된 채용공고 데이터 가져오기 기능
      - 포스팅 기간, 고용형태, 간편지원 여부, 근무형태, 회사명등의 필터링이 적용된 채용 공고 리스트 데이터 API
  • 2_2. 검색에 따른 회사, 회원 데이터 가져오기 기능
    • 검색하는 키워드에 해당되는 회사 + 회원 정보를 검색 창에 보여주는 API
    • 해당 검색어로 검색하면 검색어와 관련된 유저와 회사 리스트를 3명씩 보여주는 API
    • 검색 결과에 따른 유저 페이지 페이지네이션을 위한 전체 유저 수와 offset 설정이 된 API
  • 2_3. 포스트 데이터 읽어오기, 만들기, 수정하기, 삭제하기 기능
    • 유저가 작성한 글과 친구 관계인 회원의 글 읽어오는 API
    • 새로운 글 작성하는 API
    • 작성한 글 업데이트 하는 API
    • 본인이 쓴 글을 삭제하는 API
    • 무한 스크롤을 위한 offset이 들어간 API
  • 2_4. 댓글 데이터 읽어오기, 만들기, 수정하기, 삭제하기 기능
    • 포스트에 달린 모든 댓글과 총 갯수 읽어오는 API
    • 새로운 댓글 작성하는 API
    • 작성한 댓글 업데이트 하는 API
    • 본인의 댓글을 삭제하는 API
  • 2_5. 포스트와 댓글에 달린 좋아요 기능
    • 글에 달린 좋아요 생성 및 삭제하기 API
    • 댓글에 달린 좋아요 생성 및 삭제하기 API

4. 📐 modeling

4_1> 설계했던 MODELING DB DIAGRAM

MODELING DB DIAGRAM 보러가기


4_1. 모델링의 목표

  • 두 번째 프로젝트의 경우 모델링을 좀 더 섬세하게 진행해보는 것을 목표로 두었습니다. 탄탄하고 정교한 모델링 설계는 향후프로젝트 진행 중 기능이 추가되거나 변경되는 상황에서 꽤나 중요한 요인이 될 수 있음을 알고 있었습니다.
    따라서 가능하면 저희가 목표한 LinkedIn의 소셜 SNS 그리고 채용 서비스에 있어서 기능 구현에 필요한 테이블들을 만들어내고 관계를 맺어줌으로서 꼼꼼하고 정교한 모델링 설계를 목표로 삼고 작업을 진행했습니다.
  • 실제 사이트를 구현하는 과정에서 사용하지 않는 테이블 관계라도 모델링 설계시 반드시 고려해할 3가지 키워드를 중심으로 (1> 중복성 [정규화, automic column, 부분 및 이행적 종속성 제거] 2> 유연성(확장성) 3> 일관성) 설계 작업을 하는 것 역시 이번 모델링 작업의 목표 중 하나였습니다.

4_2> 모델링 설계 작업 기간 :

10월 25일 ~ 10월 27일 (3일)

4_3> 모델링 내용 설명 :

  • User & Company(= 일반 계정 및 기업계정)을 중점으로 Post Comment 테이블이 관계를 이루고 있습니다.
    채용공고의 경우 Company 계정으로 Post를 작성하거나 User 중 채용 담당자가 Post를 작성한 경우에 해당하므로 User와 User간 혹은 User와 Company와의 관계를 활용하여 채용 관련 서비스와 그 외에 유저 및 채용공고 그리고
    회사 검색과 같은 서비스를 구현할 수 있었습니다.
  • 또한 User 테이블간의 친구 관계를 설정하기 위한 Friend 테이블을 활용하여 User간의 관계 설정을 맺을 수 있었고 이를 활용하여 SNS 서비스 구조를 설계할 수 있었습니다.

4_4> 이외에 설계한 테이블 관계들

1) Post - *Hashtag, 포스트와 포스트 해쉬태그 테이블
2) Users - *follows, 유저와 팔로우 테이블(follower - following 관계)
3)User - *Profile(contact_informations, position_careers, introductions, educations), 유저 프로필 관련 테이블들 (연락처, 직책, 소개, 학력)
4) Countries - states - cities, 나라와 주 그리고 도시 테이블
5) College - degrees - majors 대학과 학위 그리고 전공 테이블
6) User - *application - Companies 유저와 회사 계정의 중간 테이블인 지원 테이블(채용공고 게시물 지원하기)
7) *ScopeOfPublic - (contact_informations, position_careers, introductions, educations, Post, Comments), 연락처, 직책, 소개, 학력, 포스트 및 댓글 공개 범위 관련 테이블

4_5> 모델링 설계 과정 중 아쉬웠던 점과 잘한 점

모델링 작업과 관련되어서 프로젝트 전반적으로 아쉬웠던 부분이 크게 두가지 정도였다.

  • 아쉬웠던 던 점 ❌

  • 첫 째, 모델링 작업을 혼자 맡아서 진행한 점(소통의 부재)

    • 프로젝트 시작 당일, 초기세팅을 마친 뒤 모델링 설계 작업을 팀원과 함께 진행하기로 계획했었다. 그러나 링크드인 사이트에 여러 서비스를 담은 테이블들에 관계 설정에 있어 팀원들 간의 의견조율이 단기간에 쉽게 되지 않았고 결국 모델링 설계 작업을 내가 전반적으로 맡아서 진행하게되었다.
    • 이러한 선택은 결국 내가 직접 설계한 테이블 관계를 다른 팀원들에게 설명하는 과정에 있어서 어려움이 있었고 다른 팀원들이 실제 모델링 관계를 이해하기까지 꽤 오랜 시간이 필요했다. 특히 백앤드 개발자 함께 프리즈마를 작성하는 과정에 있어서 커뮤니케이션이 어려워 많은 시행착오를 겪을 수 밖에 없었다.
  • 둘째, 완벽한 모델링 설계라는 목표의 덫에 사로잡혀 프로젝트 진행 과정 중에도 모델링 수정을 진행한 점

    • 혼자서 모델링 설계를 하다보니 순간 잘못 판단하여 설계한 테이블 관계가 있다면 전반적인 내용을 고쳐야하만 하는 때가 있었다. 만약 이러한 상황에서 팀원들과 함께 모델링을 설계했었다면 모델링을 수정하는 방향 외에도 다른 여러가지 대책을 마련해볼 수 있었을 것이다.
    • 잘못된 모델링 설계의 상황을 개선하기 위한 해결책으로 나는 프리즈마를 수정한 뒤 주석을 남겨 수정 상황이 생기게 되면 팀원에게 알려주었지만 실제로는 소통이 아닌 일반적인 방향의 통보를 할 수 밖에 없었기에 여러 아쉬움이 남기도 했다.
  • 잘한 점 ⭕️

    • 모델링을 설계하는 과정에 명확한 정답은 없음을 께닫게되면서 최대한 링크드인이 가지고 있는 서비스를 테이블을 관계로 표현해보려고 노력했던 점에 대해서 스스로에게 칭찬해주고 싶다.
    • 실제 사이트를 구현하는 과정에서 사용하지 않는 테이블 관계라도 모델링 설계시 반드시 고려해할 3가지 키워드(1> 중복성 (정규화, automic column, 부분 및 이행적 종속성 제거) 2> 유연성(확장성) 3> 일관성)들에 대해서 알게되었으며 이를 고려한 방향으로 설계 작업에 들어간 것에 대해서는 잘한 점으로 꼽고싶다.

4_5> 인상 깊었던 테이블 구조에 대해서


1> 다양한 정보(유저 정보 및 글과 댓글)들의 공개범위를 관리하는 테이블을 ENUM 테이블을 만들어서 관리해보았다.

enum ScopeOfPublic {
   NONE
   CONNECTIONS
   ANYONE
}
model post {
  id int [pk, increment]
  content varchar [not null]
  postScopeOfPublic    ScopeOfPublic  @default(ANYONE)
  commnetScopeOfPublic ScopeOfPublic  @default(ANYONE)
  @@map("posts")
}


2> 멘토님의 피드백을 받고 테이블 간의 관계를 맺어줌으로서 ENUM 테이블의 구조를 표현해보기도 했다.

model ScopeOfPublic {
  id   Int    @id @default(autoincrement())
  type String @db.VarChar(30)
  postScope          Post[]               @relation("post_scope")
  commentScope       Post[]               
  @@map("scope_of_publics")
}
model Post {
  id        Int       @id @default(autoincrement())
  content   String?   @db.VarChar(5000)
  postScopeOfPublic      ScopeOfPublic  @relation("post_scope", fields: [postScopeOfPublicId], references: [id])
  postScopeOfPublicId    Int            @map("post_scope_of_public_id")
  commentScopeOfPublic   ScopeOfPublic  @relation("comment_scope", fields: [commentScopeOfPublicId], references: [id])
  commentScopeOfPublicId Int            @map("comment_scope_of_public_id")
  @@map("posts")
}
  • 이후 마찬가지로 user가 post에 like를 선택할 수 있는 style의 수 6가지를 표현하기 위해 마찬가지로 enum 테이블 형태로 만들었다가 수정했던 코드가 기억에 남는다.
model PostLike {
  id      Int     @id @default(autoincrement())
  postLikeStyle PostLikeStyle @default(LIKE)
  user   User @relation(fields: [userId], references: [id])
  userId Int  @map("user_id")
  post   Post @relation(fields: [postId], references: [id])
  postId Int  @map("post_id")
  @@map("post_likes")
}
enum PostLikeStyle {
  LIKE
  CELEBRATE
  SUPPORT
  LOVE
  INSIGHTFULL
  CURIOUS
  @@map("post_like_styles")
}
  • 리팩토링 후 수정된 테이블, 이전보다 전체적으로 RDBS 데이터베이스의 특징을 살리면서 테이블 구조의 일관성 역시 유지할 수 있었다.
model PostLike {
  id Int @id @default(autoincrement())
  user   User @relation(fields: [userId], references: [id])
  userId Int  @map("user_id")
  post   Post @relation(fields: [postId], references: [id])
  postId Int  @map("post_id")
  PostLikeStyle   PostLikeStyle @relation(fields: [postLikeStyleId], references: [id])
  postLikeStyleId Int           @map("post_like_style_id")
  @@unique([userId, postId])
  @@map("post_likes")
}
model PostLikeStyle {
  id   Int    @id @default(autoincrement())
  type String @db.VarChar(100)
  PostLike PostLike[]
  @@map("post_like_styles")
}

5. 👬협업의 경험

  • 2차 프로젝트는 협업에 중요성을 더더욱 간절하게 느낀 계기가 되었다.
    특히 1차와 달리 백앤드만을 전반적으로 담당하게 되면서 내가 담당하게된 API를 붙이기 위해 프론트 개발자와 소통하는 과정에서 이런저런 우여곡절들이 많았다.

5_1> 우여곡절 EPISODE1.

  • 항상 내 관점에서(백앤드) 생각해오던 것들을 프론트 개발자와 함께 생각을 맞추는 과정에서 오는 큰 산을 마주쳤다.
    EX> 여러 테이블에서 컬럼을 조회하다 보니 나는 userFirstName으로 주고선 프론트에서는 firstName으로 받는 등의 동상이몽 식 협업을 펼치기도 했었다.. 😅

5_2> 우여곡절 EPISODE 2.

  • 소통이라는 큰 고개를 넘은 뒤엔 프론트 앤드 개발자가 요구하는 것(기능 개발을 위해 필요한 API 명세서)을 조금이라도 프론트 앤드 개발자에게 맞춰서 주기 위해서 백앤드 코드를 짜기 전 어느정도의 과정에 대해서 그림을 그릴 줄 알아야한다는 사실 역시 깨달았다.

    EX> - 채용공고의 생성일과 관련하여 생성된 일자를 기준으로 얼마나 지났는지(시간, 일, 주, 달 기준으로)를 프론트에서 처리할지 백엔드에서 처리할지 결정하는 과정에서 백앤드(내가)에서 처리해보겠다고 호기롭게 대답했다. 구현은 어찌어찌 하였으나 실제 로직을 짜는 과정에서 if-else문을 남발하여 좋지못한 코드를 짜게되었고 실제로 피드백으로 이런 서비스 관련 로직, 특히나 서비스 특성상 변경될 가능성이 높은 건 프론트 단에서 처리해주는게 맞다는 지적을 받게된 슬픈 코드이다...🤣
    => 그래도 이러한 경험이 나름 프론트와 백앤드 사이의 경계선을 좀 더 명확하게 알게 된 계기가 되기도 했다😊!
  • 결국 1차 프로젝트에 이어서 2차 프로젝트를 마치고 나서 느낀 건 역시나

첫째도 소통, 둘째도 소통, 셋째도 소통이다.

  • 나를 포함해서 많은 팀원들도 때론 자신이 하고 있는 생각과 그 이유에 공감하거나 따라줄 거라고 착각을 하거나 이러한 과정을 굳이 소통하지 않아도 된다고 착각하는 시점이 프로젝트를 하는 과정에 존재한다. 그러나 항상 문제나 오류가 발생하는 지점은 바로 그 이러한 오만한 생각을 하는 바로 그 순간이다.
  • 결국 이러한 문제를 해결하기 위해 필요한 건 명확한 생각을 전달하는 것과 그러한 생각을 하게 된 근거를 더 명확하고 간결하게 타인에게 전달할 수 있는 사람이 될 수 있는 것 뿐이다.
    결국 2차 프로젝트 역시 소통이 협업에 있어서 얼마나 큰 영향을 끼치는가에 대해서 다시금 깨닫게 된 계기가 되었다.

번외) 프로젝트 내 마주쳤던 Blockers와 Thoughs에 대해서~

  • 발표를 진행하면서 블로커와 프로젝트를 하며 느낀 점에 대해 적어달라하여 다음과 같은 문구를 장난스럽게 적어서 보내줬다.
  • 물론 프론트와 백앤드는 함께 가는 건 맞지만 아무래도 모델링 설계와 초기 시작하는 지점이 프론트 개발자보다 늦게 시작하다보니 프론트 개발자가 구현한 기능들에 대한 API를 모두 만들지 못하는 불상사가 생기기도한다.
  • 그럼에도 불구하고 어렵고 힘들다는건 알지만 나는 스스로에 대한 확신가 신뢰가 있기에 내가 적어도 그것들 중에 내가 할 수 있는 것들에 대해서 해낼 수 있다는 확신을 가지고 있고 이번 프로젝트 역시 100프로는 아니지만 스스로 약속한 것들은 모두 지켜냈다.
  • 그 약속은 정말 사소하게 내가 프로젝트를 진행하며 맡은 부분에 있어서 프론트 개발자가 구현한 필수 기능 있어서는 모두 구현할 수 있도록 맞추고자 노력했고 잠을 포기해서라도 이 약속을 지키고 싶었다.
    - 2차 프로젝트 때 하고싶지만 하지못한 것들과 아쉬운 것들에 대해서 지금 이순간 모두 털어버리고 지금까지 열심히 만든 코드를 누군가 함께 공유하고 협업하는 데 있어 좋은 코드를 만들기 위한 절대적인 시간을 투자해야겠다.

Reference) 이 프로젝트는 LinkedIn 사이트를 참조하여 학습목적으로 만들었습니다. 실무수준의 프로젝트이지만 학습용으로 만들었기 때문에 이 코드를 활용하여 이득을 취하거나 무단 배포할 경우 법적으로 문제될 수 있습니다. 이 프로젝트에서 사용하고 있는 사진 대부분은 위코드에서 구매한 것이므로 해당 프로젝트 외부인이 사용할 수 없습니다. © 2021 GitHub, Inc. Terms Privacy Security Status Docs Contact GitHub Pricing API Training Blog About

profile
자기 신뢰의 힘을 믿고 실천하는 개발자가 되고자합니다.

1개의 댓글

comment-user-thumbnail
2021년 11월 8일

미민님의 열정이 담긴 데이터 모델링,, 쵝오

답글 달기