노래번호부(SNB) 개발로그

flobeeee·2021년 3월 26일
1

프로젝트

목록 보기
2/7
post-thumbnail

⚝ 프로젝트 기간

2021.03.15 ~ 03.26 (약 2주)
팀원 4명

⚝ 기획

  • 프로젝트 아이디어 선정
    노래번호부
    TJ 미디어 서버에서 노래 검색
    노래 검색 결과 가져오기(노래 제목, 가수 등등)
    노래를 체크해서 나만의 노래 리스트 작성
    노래 리스트를 다른 사용자와의 공유

  • Team
    팀 이름: SSP (Sadly Singing People) 우리는 슬플때 노래를 불러
    프로젝트 이름: SNB (Song Number Book) 노래번호부

  • 기능 구현

    • [client]
      • 로그인 페이지(OAuth2.0)
      • 회원가입 페이지
      • 회원가입 정보 서버에 전달
      • 마이페이지
      • 노래 검색 시스템
    • [server]
      • 로그인 시스템(OAuth2.0)
      • 회원 가입을 통해 받은 회원 정보 저장
      • 노래 스크래핑(크롤링)
  • 도메인
    songnumberbook.shop
    도메인은 기본적인 노래번호부를 영어로 넣었고, 노래 '가' 의 의미로 ga를 붙였다.
    (무료 도메인이라 와이파이에 따라 접속불가 문제가 생겨서 .shop 로 변경함)

  • 시스템 아키텍처 설계
    https://miro.com/app/board/o9J_lP9gz7s=/
    메인과 스크랩 두개의 서버를 두었다.
    각각 다른 기능을 한다.
    메인은 인증관련이나 데이터베이스에 연결된 데이터를 보내주고,
    스크랩서버는 태진미디어의 사이트에서 데이터를 가져온다.

  • 스키마 작성

  • API 문서 작성
    https://app.gitbook.com/@monanazzang/s/snb/

  • 발표 슬라이드
    구글 슬라이드

⚝ 개발과정

나는 백엔드를 맡아서 주로 메인서버를 구현했다.
서버를 구현한 후, 여유가 생겨서 프론트쪽을 도와줄 수 있었다.

서버

  1. 메인 서버구축
    index.js 를 만들고 https 서버를 구축하였다.
    인증서들을 package.json 위치에 두었다.
    노드몬을 설치하고, 편한 디버깅 환경을 만들었다.

  2. 세션기반인증
    세션 옵션을 설정했는데, 수정이 2번이나 필요했다.

app.use(
  session({
    secret: '@songnumberbook',
    resave: false,
    saveUninitialized: true,
    cookie: {
      // domain: true
      path: '/',
      maxAge: 24 * 6 * 60 * 10000,
      sameSite: 'None',
      httpOnly: true,
      secure: true,
    },
  })
);

domain 부분이 자주 바뀌었다.
처음에는 localhost였다.
오어스 인증으로 인해 다른 도메인에서 정보를 받으려고 true 로 변경했었다.
세션에 저장한 값이 유지가 안돼서 domain 을 아예 삭제하였다.
(세션유지방법 알아보느라 시간을 정말 많이 소모하였다)

  1. 로그인 로그아웃
    기존에 작성한 API 문서에는 로그아웃 성공과 실패 응답이 분기되어 있었다.
    또한 로그아웃할때 유저아이디를 받게 설정되어있었다.
    그런데 로그아웃이 실패하는게 말이 안된다고 생각한다.
    로그아웃버튼을 누르면, 쉽게 해당 기능이 자동되어야 한다고 생각해서, 클라이언트에서 받는 데이터 없이 로그아웃 요청이 들어오면 세션을 삭제하고 로그아웃하게 구현했다.
  1. Oauth 2.0
    원래는 클라이언트에서 코드를 받고, 해당 코드로 깃허브에게 토큰을 받아와서, 다시 클라이언트에게 보내주는 걸로 했었다. 그러면 클라이언트가 엑세스토큰으로 깃허브 서버에서 유저정보를 받아올 수 있다.
    하지만 나는 모든 유저정보를 서버에서 관리하고 싶었다. 그래서 서버에서 토큰을 받고 해당 토큰으로 유저정보까지 받아와서, 유저정보를 클라이언트에게 보내주는 방식으로 구현하였다. 이 방식이 유저정보관리에 대한 통일성이 부여되어서 좋았다.

  2. 회원가입
    findOrCreate 를 이용해서 데이터베이스에 추가했다.
    .then으로 파라미터에 새로 추가가 되었는지 아닌지 받아올 수 있을 거라고 생각했는데, 받아 오지 못했다. 문법사용이 미숙했다.
    다시 공부를 해서 올바른 파라미터로 결과를 받아올 수 있었다.
    created 에 결과가 있고, user.dataValues 에 db 정보가 들어있다.

const [user, created] = await UserModel
  .findOrCreate({
    where: {
      email: email,
    },
    defaults: {
      password: password,
      username: username,
    },
  });

if (!created) {
  res.status(409).json({ 'message': 'email exists' });
}
  1. 유저정보 응답
    마이리스트 페이지에 들어서면 유저정보를 주도록 하려고 기획했었는데, 그렇게되면 마이페이지 버튼을 누를 때마다 데이터베이스에 정보를 받아와야 한다. 굉장히 비효율적이라고 생각했다. 유저정보를 받으면 클라이언트에서 상태로 관리하는 걸로 수정되었다.

  2. 오어스 로그인시 강제 회원가입 진행
    오어스 로그인을 한 사용자는 우리 사이트에 회원가입을 한 유저와 동일하게 취급되어야 한다. 해당 유저가 생성한 리스트와 노래목록을 데이터베이스에 저장하기 위해서는 유저정보를 저장해야 했다. 그래서 강제회원가입을 하는 걸로 의견을 냈고, 팀원들도 동의했다. 해당 방법말고 다른방법이 생각나지 않았다. (오어스 로그인시 다른식으로도 처리할 수 있는지 찾아봐야겠다.)

아래는 6번과 7번 내용과 연결되어있다.
해당부분의 문제점을 정리하여 팀원들과 공유한 내용이다.

  1. 로그인 로직 변경
    아이디와 비밀번호를 받고, 해당 정보가 데이터베이스와 일치하는 지 확인.
    -> 해당 아이디가 가지고 있는 리스트정보들을 DB에서 찾아서 보내준다.
    이 부분에서 리스트정보가 null 인경우 에러로 빠졌다.
    에러로 빠지는 경우 다시 유저정보를 받아와서 리스트는 빈배열로 넘겨줬다.
    그런데 생각해보니, 맨처음에 클라이언트에서 받아온 데이터로 유저정보를 조회한다.
    에러로 빠지는 경우 굳이 DB를 한번 더 확인할 필요가 없다고 생각했다.
    그래서 기존 정보를 조회할때 데이터를 받은 변수로 클라이언트에 보내줬다.
    이 부분을 짚어내서 더 효율적으로 만들 수 있어서 뿌듯했다.

클라이언트

  1. 비율맞추기

    번호, 제목 ,가수, 미디어, 체크박스의 비율을 맞추는데 꽤 고생했다.
    처음에는 flex 를 사용했는데, 정렬이 맞지않고 다 뒤틀렸다.
    확인해보니 데이터 크기에 따라 비율이 달라지는 것 같았다.
    제목데이터가 길면 가수데이터를 담는 박스 크기가 줄어들었다.
    그래서 width 에 % 로 조정해서 비율을 맞췄다.

  2. css 로 꾸미기 (UX)

    내가 제일 좋아하는 부분이다. 유저에게 좋은 경험을 선사한다.
    처음에는 바탕색만 조정했다가 더 시각적으로 화사함을 느낄 수 있게 글자가 빛나는 것처럼 표현했다.
    여태 css 는 너무 방대해서 공부하기 힘들다고만 생각했는데, 이 부분을 구현하면서 흥미가 생겼다.
    아래는 해당 부분의 코드이다.

.songdata:hover {
  text-shadow: 0 0 .1em, 0 0 .3em;
  color:white;
  background: linear-gradient(to right, rgb(229, 151, 240) 0%, #e8447d 50%, #8e44ad 100%);
  transition: background-color 0.5s, color 0.5s;
  border-radius:10px;
}

이 부분은 마이페이지에서 자신의 노래리스트를 볼 때도 적용시켰다.

  1. 게스트 로그인
    유저입장에서 로그인 해야만 서비스를 이용할 수 있다면, 대부분이 이탈한다.
    그래서 나는 게스트 로그인을 꼭 구현하고 싶었다. 프로젝트가 거의 완성되는 단계가 되도록 게스트 로그인이 구현되지 않았다.
    막상 추가를 하려니, 다른 기능들이 잘 작동되는데 굳이 수정하고 싶은 마음이 안들었다. 수정했다가 괜히 에러가 뜨면 또 많은 시행착오를 겪어야 하기 때문이다.
    어떻게 해야 큰 수정을 하지 않아도 게스트입장을 할 수 있을지 고민했고, 해답을 찾았다.
    페이지를 테스트하기위해 작성했던 가짜데이터를 이용했다.
    게스트 로그인 버튼을 누르면, 클라이언트에서 임의의 아이디와 비밀번호를 서버로 보냈다. 그렇게 하면 다른코드를 수정할 필요가 없이, 쉽게 서비스를 제공할 수 있었다.
    그대신 리스트는 public 성격을 가졌다. 누구나 생성 및 삭제가 가능했다.
    그렇기에 본인만의 리스트를 가지고 싶으면 정식 로그인을 하면 됐다.
    간단한 코드 추가로 쉽게 구현을 해내서 정말 만족스러웠다.

  2. 로그인, 회원가입 페이지 꾸미기
    마우스호버 효과에 이어 내가 또 좋아하는 부분이다.
    나는 이보다 매력적인 로그인 창은 본적이 없다. (자신만만)
    어플리케이션이 노래방과 연관이 있어서 반짝반짝하게 만들고 싶었다.

    아래는 해당 효과 코드이다.

/*로그인 창*/
.login-box {
  display: flex;
  flex-direction: column;
  width: 400px;
  height: 500px;
  border: 1px solid white(0, 0, 0);
  border-radius: 20px;
  padding: 20px;
  box-shadow:
    0 0 20px rgb(0, 0, 0),
    -20px 0 60px  var(--header-border-color),
    20px 0 60px #fff,
    inset 0 0 60px #fff,
    inset 60px 0 60px  var(--header-border-color),
    inset -60px 0 60px #fff,
    inset 60px 0 100px  var(--header-border-color),
    inset -60px 0 100px #fff;
  animation: login-pulsate 6s linear infinite;
}

@keyframes login-pulsate {
  0%{ background: #fff}
  50% {
    box-shadow:
      0 0 20px #fff,
      20px 0 60px  var(--nav-point-color),
      -20px 0 60px #fff,
      inset 0 0 60px #fff,
      inset -60px 0 60px  var(--nav-point-color),
      inset 60px 0 60px #fff,
      inset -60px 0 100px var(--nav-point-color),
      inset 60px 0 100px #fff;
  }
}

/*네온 로고*/
.login-neon {
  animation: neon1 6s ease infinite;
}

@keyframes neon1 {
  0%,
  100% {
    text-shadow: 
    0 0 0.75vw var(--header-border-color), 
    0 0 2.25vw var(--header-border-color), 
    0 0 5vw var(--header-border-color), 
    0 0 5vw #f74667, 
    0 0 .3vw #ff3399, 
    .3vw .2vw .1vw #61335e;
    color: #F5DEFA;
  }
  
  50% {
    text-shadow: 
    0 0 .5vw #8d192b, 
    0 0 1.5vw #8d192b, 
    0 0 5vw #8d192b, 
    0 0 5vw #8d192b, 
    0 0 .2vw #8d192b, 
    .3vw .2vw .1vw #c08399;
    color: #e8447d;
  }
}     
  1. 자잘한 부분 비율맞추기
    어플리케이션이 완성된 모습을 갖춘 후에도 불필요한 공간이나 비율이 맞지않는 등 자잘한 요소들이 눈에 들어와서 다듬었다.
    다 만들고 나서 아쉬웠던 점은 창을 줄이면 모양이 무너졌다.
    처음부터 신경쓰지 못해서 아쉬웠다. 친구들에게 카톡으로 자랑하고 나서도 모바일로 보지말고 데스트탑이나 노트북으로 보라고 말을 덧붙였다. (우울)

⚝ 느낀점

  1. 백엔드보다 프론트엔드가 작업시간을 더 필요로 하는 것 같다.
    -> 다음 프로젝트부터는 프론트에 더 기여해야겠다.
  2. 반응형이 아니라서 아쉬웠다.
    -> 다음 프로젝트부터는 모바일에서도 온전하게 이용할수있게 만들 것이다.
  3. 미리 설계한 비즈니스 로직을 따라 코딩하면서 왜? 라는 질문이 많이 했다.
    의심스러운 로직을 보며 왜 이렇게 설계해야하는가 질문하고 답변을 얻는 과정이 즐거웠다.
    -> 일방적으로 혼자 생각하고 팀원들한테 통보한게 많은 것 같아서, 다음 부터는 로직을 변경할 때 팀원들의 의견도 들어보고 싶다.
  4. 협업은 생각보다 즐거웠다.
    -> 팀이 발표되었을때, 팀원 모두 좋은 페어시간을 가졌던 경험이 있어서 기대감으로 시작했다. 팀원들에 대한 신뢰도가 높아서 코드를 의심하지 않았다. 모두 자신이 맡은 부분을 잘 구현해 주었고, 우리는 성공적으로 프로젝트를 마무리했다.

서버 레포
클라이언트 레포


아래는 위키에 작성한 짧은 회고록이다

내 인생 첫번째 프로젝트.
의욕은 가득했지만 기획을 하며 점점 커지는 work flow 에 부담스러웠습니다.
저희는 프론트와 백엔드 역할만 정해두고 각자 테스크카드에서 하나씩 골라서 구현했는데, 이게 좋은 결과를 불러왔다고 생각합니다.
하고싶은 부분을 고르기 때문에 흥미를 가지고 즐겁게 코딩을 할 수 있었기 때문입니다.
하루 2번 회의에서 코드리뷰를 통해 더 좋은 코드를 작성할 수 있었고, 원활한 소통으로 프로젝트의 완성도가 높아졌습니다.
이번 일을 계기로 협업하며 개발하는 것에 두려움이 사라지게 되었습니다. 그리고 우리 팀원들과 함께 할 수 있어서 너무 좋았습니다.
이 경험이 제 개발자인생의 단단한 기반이 될 것이라고 생각합니다.

profile
기록하는 백엔드 개발자

1개의 댓글

comment-user-thumbnail
2021년 3월 29일

은정님, 고생 너무 많으셨어요!! 다음 프로젝트도 기대됩니다 :)

답글 달기