프로젝트 후기 - Winner's Record

성훈·2021년 11월 19일
0

SEB31

목록 보기
4/4
post-thumbnail

Prologue


드디어 4주간의 피 말리는 프로젝트가 끝났다.
이번 프로젝트에서도 프론트엔드 포지션으로 참가했는데, 태스크별 소요 시간 생각을 너무 어설프게 설정해서 마감 3~4일 전부터는 아침 6~7시에 잠들곤 했다.
그래도 나온 결과물을 보니 고생한 마음과 뿌듯한 마음 사이 어딘가의 기분이 들어서 상당히 묘했다.

Winner's Record

깃허브 | 배포

위너스 레코드는 스포츠 대전기록 및 순위조회 서비스이다.
지금은 라켓 스포츠(테니스, 배드민턴, 스쿼시, 탁구)에 한정되어 있지만, 실 유저가 늘어나면 종류를 좀 늘려볼 수 있지 않을까 하는 생각이 든다.

내가 구현한 페이지는 랜딩 페이지, 메인(검색) 페이지, 포스트 조회 페이지, 참가 페이지, 대회(진행, 결과) 페이지, 채팅 페이지가 있다.

Landing

이 랜딩 페이지는 가장 마지막에 구현했었는데, SR 과정에서 이 페이지를 너무 두루뭉술하게 넘어가서 가장 머리 아프고 급하게 짠 페이지였다.😇

시안 나온 게 없어서 페이지 구조 생각 + 코드 작성 + 시간 없음 + 다른 페이지의 에러 핸들링 이렇게 네 박자가 갖춰져서 참 힘들었다.

그래도 만들고 스크롤 내릴 때 급하게 만든 페이지치고는 깔끔하게 나와서 만족스러운 그 기분이란.

이 페이지에서 메인 기능이라고 하면 아무래도 애니메이션이라고 할 수 있다.
사실 상당히 몰려있던 상황이라 마음이 약해져서 라이브러리 가져다 쓸까 고민을 엄청나게 했었다🧐

그런데 프로젝트 시작할 때 다짐한, 라이브러리 사용을 최소화하자는 생각이 자꾸 나서 결국 다른 방식을 생각해봤다.

사용한 방식은 단순하게 scrollY값과 삼항 연산자를 사용했다.
그냥 스크롤 해서 해당 지점에 오면 클래스를 추가하고, CSS 트랜지션 속성을 주는 것이다.

이렇게 해놓으니 제일 처음 페이지에 들어갔을 때 제일 상단에 있는 애니메이션이 작동이 안 되길래 가장 최상단에서 사용하는 애니메이션은 상태 하나를 선언해서, 기본값을 false로 놓고 이펙트 훅을 이용해 페이지가 불렸을 때 최초만 값을 true로 바꾸는 식이다.

Main

메인 페이지가 CSS 짤 때는 가장 신경 쓴 부분이 아닌가 싶다.
나는 퍼스트 프로젝트부터 주로 flexbox를 이용해서 렌더해왔는데, 이게 억지로 flexbox를 쓸 수는 있겠지만 아무리 봐도 그리드를 이용하는 것이 바르다는 생각이 자꾸 들었다.

그리드를 사실상 처음 프로젝트에 써보는 거다 보니, 그리드가 width에 따라 자동으로 크기를 맞춰주는 부분을 관리해주는 게 날 힘들게 만들었다. 그리드 따라 나와

이게 해결하고 나니 영 허무한 게, 처음엔 grid-column 속성을 퍼센트 단위로 사용해서 하드코딩 비슷하게 맞췄었는데, 게시글 종류 선택하는 버튼에 도저히 안 맞아서 이걸 어찌하나 발만 동동 구르고 있었다.

그런데 fr 단위를 사용하자마자 바로 해결됐을 때 느낀 그 허무함이란.

그리고 무한 스크롤 역시 구현했다. 이것 역시 스크롤 이벤트를 이용했는데, 단순 scrollY 값을 사용한 게 아닌 스크롤 하는 총 길이인 scrollHeight와 스크롤 한 길이인 scrollTop, 그리고 지금 클라이언트(브라우저)로 보고 있는 페이지의 길이 clientHeight를 이용했다.

scrollTopclientHeight의 합과 scrollHeight 길이를 비교해서 합의 수치가 더 크면 콜백 함수로 추가 데이터를 불러오는 함수를 만들고,
이펙트 훅으로 스크롤을 감지해서 위에서 만든 함수를 실행시키는 방식이다.

물론 계속해서 요청을 보내지 않고, 데이터 순서가 바뀌지 않게 데이터 받아오는 중을 나타내는 상태를 하나 만들어서 관리해 줬다.

SR 했을 때 디자인 자체를 모바일 페이지에 맞춰서 와이어 프레임을 짰기 때문에 PC 페이지는 여러 기성 페이지의 디자인을 참고해 섞어 봤는데 나름 이쁘게 잘 나온 거 같아서 만족스럽다😇

그리고 리팩토링할 부분도 몇 부분 있는데, 페이지 줄어들 때 반응해서 게시물 크기도 줄어드는 부분과 모바일 반응형이 그것이다.

반응형 같은 경우는 PC에 호환되겐 해놨는데, 모바일 반응형 고려를 미숙하게 해놔서 영 보기 싫게 나온다.
이제 누구 쫓아오는 사람도 없겠다, 원래 없었다 천천히 고민해보며 개선해보려고 한다.

Post

엄지는 내 엄지다

이 페이지에서 기억에 남는 부분은 아무래도 세 부분으로 나눌 수 있는데,
바로 이미지 카로셀 부분과 지도 부분, 그리고 좋아요 버튼이다.

사실 이 이미지 카로셀 부분도 리액트 슬라이더라는 라이브러리를 사용할까 하다가 앞서 말했던 다짐 때문에 만들어 봤는데 생각보다 만족스럽게 나온 것 같다.

저 인디케이터가 특히 귀엽지 않은가? 내 새끼라 그런지 더욱 이뻐 보인다.

지도 부분은 카카오 지도 API를 사용했다.
아마 이 부분이 프로젝트 진행하며 공부를 가장 오래 한 부분이 아닌가 싶은데, 공식문서가 워낙 잘 되어있어서 쓰는 데 큰 문제는 없었다.

다만 공식문서에선 돔에서 직접 찾아 선택하던걸 리프훅을 이용한 거 차이랄까.
그리고 커스텀 오버레이만 설정해놨는데, 커스텀 마커를 못 써본 게 아쉽다.
이게.. 손이 영 말을 안 들어서 마커를 만들어보려고 해도 만족스러운 게 나오지 않는데 별수 없지 않은가 🥲

지도 API 같은 경우는 카카오의 우편번호 찾기 서비스와 연계해서 해당 주소를 지도로 넘겨받고 geocoder를 이용해서 좌푯값을 반환해 지도에 렌더하는 방식으로 구현했다.

다만 이 카카오 우편번호 찾기 서비스가 영 아쉬운 게, 근본이 우편번호 찾기 서비스이다 보니까 검색하는 게 영 시원찮다.
이 부분은 개선이 매우매우매우 필요하니 고민을 좀 해봐야겠다.

그리고 애증의 좋아요 버튼.
사실 좋아요 버튼 자체 구현은 매우 쉽게 됐다.
그런데 퍼스트 프로젝트 때 이 북마크 기능에 시간을 너무 많이 뺏긴 기억이 있어서 기억에 오래 남는 것 같다.

구현은 별거 없다.
백엔드에서 유저에 따라서 좋아요 여부를 보내주기 때문에 그걸 그대로 렌더하고, 그 좋아요 여부에 따라서 버튼 누를 때 AJAX 요청을 다른 식으로 보내준 후에 버튼 색을 바꿔주면 되는 것이다.

두려운 기억 때문에 구현한 후 시연할 때 좀 걱정했는데, 생각보다 별거 없어서 허탈했다.

Entry

참가 페이지 역시 기능 자체는 별거 없을지 몰라도 예외 처리할 게 많아서 생각보다 에러가 많이 생겼던 페이지다. 물론 지금은 다 처리했다. 아마도...

페이지 자체를 대회할 때 같이 쓰는 데다가, 이 화면을 보는 사람도 호스트와 참가자 두 분류로 나눴어야 했기 때문에 신경을 제법 썼다.

위에 올린 구현화면에선 안 나오지만, 참가자는 본인 옆에 제거 버튼만 떠 있고, 호스트만 모든 유저에 대해 확정하기, 제거하기 버튼을 확인할 수 있다.

그리고 대회의 경우는 7명까지 선택할 수 있고, 1대1 매치의 경우는 두 명 이상 선택하려고 하면 에러 모달을 발생시킨다.

이 페이지 역시 SR 과정에서 너무 소홀하게 넘어가서 코드 칠 때 조금 고생한 케이스이다.

이렇게 겪어봐야 SR 계획의 소중함을 안다니 참 😇

Tournament

그리고 에러가 가장 많이 발생하던 이 토너먼트 페이지.

분명 짤 때는 문제 없이 잘했었는데, 어째 다른 팀원들이 하나씩 눌러볼 때 이상한 버그가 생겨서 어지러웠던 페이지이다 🤯

이 페이지 역시도 호스트 유무를 따지고, 진행 라운드 여부를 따져서 옆에 나오는 수정 버튼을 보이는지 마는지를 따져야 하므로 고민을 조금 했었다.
결국 불리언 타입을 배열로 가지고 있는 상태를 하나 만들어서 호스트인지 따져보고, 호스트라도 이미 종료된 라운드에 대해서는 결괏값을 수정할 수 없게 처리했다.

다만 가장 문제가 됐던 문제는 결승이었는데, 8강이나 준결승 같은 경우는 그다음 라운드, 8강의 경우 준결승, 준결승의 경우 결승의 경기가 있으면 해당 버튼을 없애버리면 됐는데, 이 페이지에서 AJAX 요청을 보내서 받아오는 응답에 들어있는 건 이 매치들밖에 없었기 때문에 결승의 경우는 한 번의 요청으로는 처리하기가 어려웠다.

그래서 결국 AJAX 요청을 한 번 더 다른 엔드포인트로 보내서 이 대회의 진행 상태를 상태 값에 저장하는 것으로 해결했다.

되도록 한 페이지에서는 하나의 엔드포인트로만 요청하는 것으로 짜고 있었는데 그냥 요청을 최대한 적게 하고 싶었다. 그게 깨져서 뭔가 아쉬웠다.

Chat

이 부분은 Socket.IO 를 사용해 구현한 부분이다.
웹 소켓이 아무래도 HTTP와 다르다 보니 조금 헤맸었는데 그래도 어떻게든 포스트를 띄우는 데 성공했다.

게시글에서 채팅하기를 누르면 채팅으로 연결한 해당 게시글의 정보가 표기되는데 해당 포스트의 pk 값은 전역 객체를 하나 생성해 객체를 눌렀을 때 당시의 파라미터를 전역 객체에 담고, 그걸 채팅방에서 가져와 바디에 담아서 AJAX 요청을 보내는 것으로 처리했다.

만약 바디에 담기지 않는다면 서버에서 해당 데이터를 제외한 채팅 글만 남겨주고, 해당 데이터가 없기 때문에 이전 글 관련 데이터를 emit 하지 않는다.

그리고 여기서 조금 막혔던 부분은 socket.on으로 받았던 데이터를 바로 전개 구문으로 상태에 넣으니까 넣어지지 않던 부분이다.
꼭 콜백 함수를 사용해서 콜백 함수의 매개변수에 on 받은 데이터를 넣고, 리턴 값에 전개 구문을 이용해서 넣어주자.

왜 안되는지는 소켓을 좀 더 공부해야 할듯하다.

Epilogue

새벽 4시에 에너지드링크와 커피를 물처럼 마시며 코드를 치면서 멀어져 가는 정신을 붙잡고 코드를 치던 게 엊그제 같은데 엊그제 맞다 벌써 발표까지 하고 부트캠프 수료까지 해버렸다.

부트캠프를 수료하면 날아갈 것 같고, 어디든 떠나고 싶고, 어딘가에서 해방된 기분이 될 줄 알았는데 막상 수료하고 수료증까지 받아보니 그런 느낌은 들지 않더라.

이 친절한 듯 불친절한 부트캠프 과정이 알게 모르게 하나의 심리적 울타리 역할을 해주고 있었는가 보다.

이제 막 울타리의 문을 열어 새로운 커리어라는 길에 한 걸음 내딛는 과정에 있는데 이렇게 막연한지.

아마 같이 수료한 동기들도 다 같이 막연한 느낌이 있지 않을까 싶다.

이런 막연함과 불안함을 느끼는 건 오늘을 마지막으로 하고, 앞으로는 내 커리어 향상을 위해, 내 가치를 높이기 위해 어떻게 노력할지 궁리해보자.
여유가 생기니 이런 생각도 들지

그래도 내 다짐을 다시 한번 다지기 위해서 굳이 내가 해야 할 걸 적어보면

  1. 이력서 다듬기
  2. 노션 이력서 만들기 ( + 포트폴리오 사이트 만들어 보기 )
  3. 기술 면접 준비하기 ( + 자바스크립트 다지기 )
  4. 알고리즘 공부하기
  5. 프로젝트 리팩토링하기
  6. 타입스크립트 공부하기 ( + 넥스트 JS 공부하기 )

그리고 이후에 넥스트 JS가 좀 만만해지면 스벨트 건드려보기
머리가 띵

다시 보니 오늘 막연해할 시간도 없어 보인다.
그래도 6개월 열심히 했으니까, 오늘 밤은 맥주 한잔하면서 자신을 다독이는 시간을 좀 가져야겠다.

profile
어떻게 이걸 풀어낼 수 있을까

4개의 댓글

comment-user-thumbnail
2021년 11월 19일

와.. 저두 가입하구 서비스 이용해봤는데 너무 깔끔하고 군더더기가 없어요!!! 기능도 되게 많아서 구현하기 힘들었을 것 같은데.. 대단하십니다!! 수료 다시한번 축하드리구 취업까지 다시한번 화이팅!!!!! 🥰😍

1개의 답글
comment-user-thumbnail
2021년 11월 19일

노력했던 흔적들이 고스란히 담겨있는 포스트네요 :) 잘 읽고 갑니다 !! 고생 많으셨어요 ㅎㅎ

1개의 답글