ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 퍼스트 프로젝트(Golden Time) 회고록
    TIL (Today I Learned)/회고 2021. 1. 10. 21:15

    1. 기획

    1-1. Intro

     - 부족한 실력과 2주라는 짧은 시간으로 아쉬움이 많이 남는 프로젝트였다. 커리큘럼상에도 해당 프로젝트는 뭔가를 만들기보다는 프로젝트를 어떻게 진행해야하는지 배우는 것이 목적이었다. 그래도 타팀에 비해서 우리 팀 결과물이 꽤나 잘 나왔고, 많은 것을 배웠기에 마냥 실망스럽지는 않다.

     - 2주 프로젝트에서는 팀장과 프론트엔드 그리고 발표까지 담당하게 되었다. 나의 아이디어가 프로젝트로 주제로 선정되었고, 팀장과 발표까지 맡게되다 보니 짧은시간에 많은 것을 경험했던 것과 동시에 이 역시도 아쉬움이 남는다. 그래도 프로젝트 기간동안 매일 TIL 및 스터디 노트를 작성하였고, 실력적인 부분에서도 정말 많이 성장하는 기간이었다.

     

    1-2. Golden TIme?

    Golden Time PPT 일부

     - Golden Time은 지역을 기반으로한 우리동네 경매 플랫폼이다. 평소 중고나라, 당근마켓 등 중고거래를 애용한다. 이렇게 개인매물일 경우 판매 혹은 구매하려는 상품의 적정가가 얼마인지 측정하기가 어려운 경우가 있다. 또한, 말도 안되는 금액을 네고하거나 거래를 약속했지만 더 높은 가격에 구매하려는 사람이 나타날 때는 거래를 캔슬내기도 한다. 이렇게 개인거래 시에 나타나는 어려움을 해결하기 위해 기존 플랫폼에 경매 시스템을 도입해보자는 생각을 해보았다.

     - 이름은 환자를 살릴 수 있는 시간을 의미하는 의료용어인 Golden Time에서 따왔다. 프로젝트명이 정해지고 나서 골든 타임에서 24k라는 팀이름을 따올 수 있었다. 이날은 뭔가 머리 속 아이디어가 팡팡 도는 하루였나보다. 무엇보다도 내가 머리 속으로 생각했던 것들이 실제로 반영되고 구현된다는 것이 설렜다.

     

    2. 설계

    2-1. Flowchart, Wireframe, DB schema, API

     - 프로젝트가 처음이다 보니 처음 설계하는 단계가 제일 힘들었던 것 같다. 그리고 프로젝트 아이디어부터 설계까지 모든 것을 단 3일안에 끝내야했기에 시간적으로도 상당히 부족했었다. 처음으로 Flowchart, Wireframe, DB 스키마, API 등을 짜봤으며, Miro, DBdiagram, gitbook 등 다양한 협업툴을 사용해봤다.

     - 프로젝트를 끝내고 나니 설계에서 부족한 부분이 많았던 것을 느꼈다. 무엇보다도 설계를 빨리 끝내고 프로젝트를 진행하다 보니, 중간중간에 바뀌거나 추가되는 부분이 엄청나게 많았고 이 부분에서 정말 시간을 많이 잡아먹었던 것 같다. 예를 들어 A라는 로직과 방향으로 진행을 하다가 급작스럽게 B로 방향을 바꿔버리면 기존 코드들을 다 갈아엎어야 했다. 그렇다보니 자연스럽게 코드들이 더러워질 수 밖에 없었다. (이 부분은 리팩토링을 보완을 해야할 듯 싶다.) 이처럼 탄탄한 설계는 무엇보다 중요하며, 설계에 많은 시간을 투자하는 것이 결국은 전체 프로젝트 기간을 줄이는 방법이다.

     - 짧은 시간 안에 협의하여 결론을 돌출해내는 것도 어려웠다. 아무래도 내 아이디어이다 보니 애착도 가고 많은 기능들이 구현되었으면 하는 마음이 컸다. 그래서 이것저것 기능 제안을 많이 하였지만, 우리가 2주라는 짧은 기간과 프로젝트가 다들 처음이라는 점 등 제한사항들이 많이 존재하였다. 결국 현실적인 부분을 고려하여 정말 필수적인 기능들만을 중심으로 결론이 났다. 적어도 쪽지 혹은 채팅 기능이 빠진 것으 너무 아쉽다.

    Flowchart (Miro)
    Wireframe 일부분
    DB schema (DBdiagram)

     

    2-2. Git (Projects, Milestones, Taskcard)

    Git Projects

     - 이전까지 페어 프로그래밍에서는 push & pull로 단순히 1:1로 코드를 주고 받거나, 단순히 개인 repo 관리, upstream으로 pull request만 하는 형태로 git을 활용하였다. 하지만 이번 프로젝트부터 제법 git을 협업툴로써 활용할 수 있었다.

     - 칸반보드 스타일로 project를 활용하고, milestones와 issues를 활용하여 Task card를 만들어 분업을 하였다. 또한, upstream 및 local, master와 dev, 각 task에 따른 branch까지 별도로 관리하며 누구나 알아볼 수 있도록 깔끔하게 git을 활용하였다.

     - 실제 현업이나 큰 프로젝트에서는 이 점이 매우 유용하지만, 2주 프로젝트에서 실제 개발에 쏟을 시간은 약 1주일밖에 안됐다. (3일을 기획 및 설계에, 3일을 배포 및 목업 테스트 등) 그렇기에 함수 단위 등 엄청나게 Task card를 세분화 한다던지, 개발 소요시간 단위로 나누는 것에서 비효율적인 측면이 많았다. (하루만에 엄청나게 많은 기능들이 진행되기에) 그래도 어떠한 로직으로 프로젝트를 하는지 스터디 하는 것이 목적이기에 라벨링 등도 붙여가며 열심히 하였다.

     

    3. 기술 스택

    Golden Time PPT 일부

    3-1. State 관리

     - 이번 프로젝트는 서비스 구현보다도 스터디에 초점을 잡았다. 그렇기에 react를 보다 심도있게 공부함과 동시에 hook과 context API, redux의 필요성을 절실히 느낄 수 있도록 순수하게 react만을 사용하기로 하였다. 그리고 느꼈다. 이 3가지 스택이 얼마나 강력하고 편하고 좋은지를. 순수 예전 리액트만으로 구성하려다보니 코드가 너무 더러워지고, 코드를 정말 많이 갈아 엎었다. context API 정도는 쓸걸 하는 후회가 된다.

     

    * 독립된 Container

    react props drilling & lifting state up

     - 특히, state 관리 때문에 전체 프레임짜는 것에 큰 고생이 되었다. Container & Presenter 패턴으로 전반적으로 틀을 잡았지만, context API나 redux를 활용하지 않으면서 여러 컨테이너에서 공유하는 state를 어디서 생성하고 관리하고 뿌려줄지가 가장 큰 고민이었다. 현재 프로젝트 서비스에서 로그인 상태, 지역 정보, 상품 정보 등은 state로 관리하여 life cycle로 다뤄줘야 하기 때문이다.

     - 원래는 app이나 router 컴포넌트를 모체로 잡고, react의 전형적인 특징인 "props drilling", "lifting state up"으로 라우터에서 props로 모든 컴포넌트에 뿌려주는 쪽으로 설계를 했었다. 그러다보니 전체 로직 및 코드도 너무 더러워지거나, 모체 component가 상당히 무거워지는 불상사가 생겼다. 또한, 각 container에서 별도로 다루는 state가 있거나 모체가 아닌 곳에서 전달해주는 props가 있을 시에는 컴포넌트마다 데이터가 다르거나 life cycle이 깨져버리는 상황이 일어날 수도 있었다.

     - 그래서 굳이 모체 component에서 대부분의 state를 관리하면서, 각 container마다 연결된 life cycle 관를 해줘야 할지에 대해서 고민을 해봤다. 서비스 로직과 state가 꽤나 단순하기에 굳이 그럴 필요가 없었다. 암호화된 토큰 정보는 localstorage에 저장하고, 특정 몇 컴포넌트에서 필요한 위치정보는 필요할 때 요청하고 각 container에서 상태관리를 하면 각 container마다 완벽하게 독립적으로 완성되어서 꽤나 코드와 로직이 깔금해졌다. (지금 생각해보면 그냥 한 컨테이너에서 받고 localstorage에서 관리하는 것이 더 깔끔하지 않았을까 생각이 든다.)

     

    * AccessToken

     - 인증방식은 설계 당시 백엔드 담당하신 팀원분의 의견으로 JWT로 암호화된 AccessToken을 프론트에서 관리하는 것으로 하였다. 그렇기에 프론트에서는 state 혹은 localstorage에 토큰값을 저장하여 매번 인증이 필요한 요청 header로 보내주었다. 이렇게 프론트에서 별도로 관리하는 것은 프론트 로직상도 보안상도 그렇게 현명한 방법은 아닌 듯 싶다. 근래에 토큰값 자체는 쿠키로 자연스럽게 관리하는 것이 국룰인 듯 싶다.

     

    3-2. lifecycle

     - 중간에 문제가 됐던 것은 로그인 상태, 검색어, 위치 정보, 상품 정보의 상태 및 비동기 처리 결과에 따른 분기처리였다. useState와 useEffect 등 hooks를 활용하였으면 정말 편했을 텐데, 순수하게 react life cycle만으로 이를 처리하였고 덕분에 life cycle 및 관련 메서드까지 빠싹하게 공부할 수 있었다.

     - 위치 정보가 없을 시에는 회원가입 불가, 위치 정보를 응답받았을 경우에만 상품 정보를 요청, 위치가 성공적으로 왔을 때는 해당 위치 상품정보를, 비로그인 혹은 위치 응답 실패시에는 전체 상품 정보를, 그리고 위치 및 상품정보의 변경 시에 재렌더링, 그리고 해당 로직에서 검색어가 있는 경우 해당 위치의 검색어 상품을 랜더 해주는 등등 state 상태에 따라, 비동기 로직 처리 결과에 따라 life cycle 분기처리를 하느라 많이 고생했던 것 같다.

    * shouldComponentUpdate

    react lifecycle

     - 이전까지는 componentDidMount를 주로 사용하고, 기껏해야 componentDidUpdate, componentWillUnmount 정도를 활용했다. 하지만 이번에는 보다 확실한 분기처리를 하기 위해 shouldComponentUpdate를 활용해보았다.

     - 리액트가 “virtual DOM"이 활용하여 변경된 DOM 노드만 업데이트하더라도 모든 변경사항에서 리렌더링을 하게된다. 또한, componentDidUpdate에 비동기 로직이 들어가 있을 시에는 굳이 필요하지 않는 비동기 로직도 다시 한 번 수행하게 된다. 이러한 비효율성을 shouldComponentUpdate를 통해 줄일 수 있다.

     - 또한, map 등의 함수가 랜더될 때에는 요소 수 만큼 componentDidUpdate가 발생되기에 엄청난 비효율이 발생된다. 이때, shouldComponentUpdate를 통해 특정 state 혹은 props 변경 시에만 componentDidUpdate가 처리될 수 있도록 설정할 수 있다.

     

    * 갑자기 나타난 검색기능

     - 설계 당시 생각하지 못한 검색기능이 개발 단계에서 나왔다. 대부분의 웹 서비스에서 검색은 쿼리파라미터로 처리하지만 새로운 API를 만들지 않는 쪽으로 협의가 되었다. 그렇기에 기존 상품 데이터 요청하는 API 바디 파라미터에서 'search'라는 속성 값을 추가로 하기로 하였다. 자연스럽게 검색어를 state로 관리하게 되었고, 검색어가 없는 경우, 있는 경우, 바뀐 경우 등에 대한 분기처리까지 해줘야 하는 불상사가 일어났다.

     - 이렇듯 설계를 잘해야 불필요한 혹은 잘못된 로직이 탄생되지 않는다. 예전 유튜버에서 실력있는 개발자도 똥코드를 작성하는 이유라는 주제의 영상을 본 적이 있다. 해당 환경에서 올바른(?) 로직을 설계하려면 기존 레거시 코드를 싹다 갈아 엎어야 하는 상황이 오기에 좋지 않은 로직임을 알고서도 어쩔 수 없이 구현시킬 수 밖에 없다고 한다. 가볍게 넘겼던 이 영상이 절실히 공감되는 순간이었다.

     

    3-3. Geolocation & kakao API & HTTPS 

    * 위치 기반 서비스

     - 사용자 위치 기반으로 이뤄지는 서비스이기에 사용자의 장소를 얻어내는 것이 핵심이었다. 사실 이러한 위치 기반 서비스는 데스크탑의 웹 환경보다도 GPS가 내장된 모바일 환경에 적합하다. 그래도 브라우저 상에 Geolocation과 같은 내장 함수를 활용하면 ip기반으로 해당 사용자의 좌표값을 알아낼 수 있었다. 실제 지도 사이트나 피자헛 등 배달 사이트도 같은 방법을 활용하는 듯 싶다.

     - 카카오, 네이버 등 지도 관련 API들이 너무 잘 나와있어서 해당 좌표값을 알아내면 손쉽게 주소값을 구할 수도 있다. 어디까지를 같은 지역으로 묶을지 고민을 해보았다. 당근마켓의 경우는 기준을 '동'으로 나눠서 기준 지역과 거리 상으로 계산을 했던 것 같다. 비슷한 알고리즘을 짜고 싶었지만, 백엔드 분들이 힘들어하시기에 간단한게 동일한 '구'를 기준으로 잡게 되었다.

     - 당근마켓의 경우 철저하게 자신의 지역 상품만 볼 수 있다. 다른 동네 상품들까지 볼 수 있으면 더 좋겠다라고 생각할 수도 있겠지만, 이런 작은 차이가 당근마켓의 아이덴티티이자 성공하게 만든 차별점이라고 생각든다. 이처럼 골든타임도 우리동네를 기반으로 한다는 것에 초점을 잡았기에, 현재 지역의 상품들만 볼 수 있도록 구현해냈다. 다만, 목업 데이터가 많지 않은 관계로 포트폴리오로 구현할 때는 전체 지역으로 표시하거나 지역 카테고리를 넣어야하지 않을까 싶다.

     

    * HTTPS 배포 (+ Google OAuth 2.0)

    CloudFront (출처:cloud.hosting.kr)

     - 개발 테스트 단계에서는 문제없이 되던 것이 실제 배포 환경에서 작동이 안되었다. 뒤늦게 찾아보니 Google 측에서 보안 문제로 더 이상 http 환경에서는 크롬 Geolocation 메서드를 구현시키지 않기로 하였던 것이다. 엎친 데 덥친 격으로 Google OAuth도 http 환경에서는 구현되지 않았다.

     - 부랴부랴 도메인을 사야하나 싶었는데, 프론트는 AWS Cloudfront로, 백은 무료 도메인과 Router53으로 https 환경 배포를 구현해낼 수 있었다. 처음 써보는 서비스라 첫 셋팅이나 웹캐시, 엔드포인트 등을 설정해주는 파트에서 고생 좀 했지만 성공적으로 마칠 수 있었다. 이처럼 배포환경에서 예상치 못한 에러 및 버그를 발견할 확률이 정말 높기에, 어느정도 틀이 잡혔을 때부터는 배포환경에서의 테스트가 중요함을 느꼈다.

     

    3-4. Git work flow

    project git flow

     - 위에서도 한 번 언급했듯이 이번 프로젝트를 통해서 git을 협업툴답게 제대로 활용할 수 있었다. 단순히 혼자서 레포를 관리하는 것이 아닌 여러 명이서 여러 브랜치로 나눠서 활용하며 하나의 프로젝트로 완성될 수 있었다.

     - 처음에 힘들었던 것은 모체 component(app과 router)에서 상태 및 메서드 관리를 하다보니깐, 프론트를 맡은 둘이서 같은 문서를 작업하는 일이 잦았다. 그렇기에 당연히 merge할 때마다 해당 문서에서 충돌이 일어나 일일이 하나하나 잡아주는 것이 정말 곤욕이였다. 나중에는 각개의 container를 독립적으로 만들어주고, 역할 분담이되서 크게 충돌은 없었지만, 빠르게 진행되는 프로젝트 초반에 같은 문서를 동시에 수정하는 경우의 이러한 충돌은 어쩔 수 없는 부분인듯 싶다.

    Project Network graph

     - 처음에는 단순히 upstream에서 땡겨오는 것만으로도 긴장이 되었는데, P/R 보내고 머지하는 것 까지 제법 익숙해져서 git이 편해졌다는게 2주 동안의 큰 수확 중 하나이다. 물론 이것 말고도 git으로 할 수 있는 기능들이 무궁무진 하겠지만, 제일 기본 뼈대가 되는 기능들이 몸에 익었다는 것만으로도 만족한다.

     

    4. 프로젝트를 마치며.

    4-1. 설계의 중요성

     - 프로젝트가 처음이기도 하였고, 2일이라는 짧은 설계 기간이였기에 탄탄치 못했던 설계가 나왔던 것 같다. 그렇기에 개발을 진행하면서 만들었던 차트플로우나 와이어프레임 및 스키마 API까지 수정되는 일이 빈번히 발생되었고, 탄탄한 설계가 얼마나 중요하고 개발 및 전체 프로젝트 진행을 보다 효율적으로 만들어줌을 절실히 느꼈다.

     - 그러다보니 코딩했던 것을 다시 뒤엎고 다시 짜고, 변경에 따른 충돌이 발생하였을 때 디버깅하고 잡는 것에 많은 시간이 소요되었던 것 같다. 혼자서 하는 프로젝트라면 바로바로 바꾸고 바로 코드 바꾸고 바로 디버깅하는 식으로 손쉽게 잡을 수 있겠지만, 일단 프론트와 백이 나눠진 상태에서 아무리 소통한다고 하여도 같이 옆에 붙어서 코딩하지 않는 이상 이러한 변경을 협의하고 merge하고 맞춰 가는 추가 작업과 시간이 꽤나 많이 필요하였다.

     

    4-2. 2주라는 짧은 시간의 아쉬움

     - 짧은 개발 기간이기에 몇몇 기능들을 많이 제외시킨 것이 제일 아쉽다. 지금 생각해보면 몇 가지 기능구현에 큰 시간이 들지 않았을텐데, 설계 당시 이 부분을 팀원들에게 잘 설득시키지 못했던 듯 싶다. 1:1 채팅 및 쪽지, 데이터베이스에서의 입찰 상태 관리, 위치 카테고리 등 아쉬운 부분이 많다. 나중에 시간이 된다면 팀원들하고 같이 리팩토링 하면서 추가시키고 싶다.

     - 기간이 짧다 보니 설계 당시 디자인 및 모바일이나 타 환경에서 구현되는 것에 크게 신경쓰지 않고, 일단 기능 구현에만 초점을 잡는 것으로 목표로 하였다. 그렇기에 flex와 grid를 활용하긴 하였지만 제대로된 CSS 디테일 및 반응형웹을 구현시키지 못한 것이 아쉽다. (그래도 덕분에 flex, grid, position 그리고 단위에 대한 이해 등 CSS 공부를 상당히 많이 할 수 있었다.)

     - 마지막으로 코드 퀄리티의 안타까움이다. 완전한 설계가 끝난 상태에서 프로젝트가 진행된 것이 아닌, 하나 구성하고 바뀌고 혹은 어떤 계획된 부분이 수정되거나 추가되는 것을 반복하다 보니깐, 일단 기능 구현되는 코드만 계속해서 추가되는 식의 코딩이 진행된 듯 싶다. 그러다보니 전체적인 코드 컨벤션 및 로직이 개똥이 되어버렸다. 리팩토링 작업때 깔끔하게 정리 할 수 있었으면 좋겠다.

     

    4-3. 협업 그리고 성장

     - 프로그래밍 공부를 시작하고 처음으로 진행했던 프로젝트였다. 개발은 혼자하는 일이 아니기에 무엇보다 협업이 중요하다고 늘 들어왔던 말이다. 그런 의미에서 프로젝트 결과물 외에도 많은 부분에서 배우고 배우고 성장한 느낌이다. 팀장으로서 팀원으로서 소통, 프론트엔드 개발자로서 백엔드 개발자들과의 소통, 그리고 스터디 메이트로서 부족한 부분을 서로 도와주며 학습까지.

     - 협업을 하게되면 추가적으로 해야하는 업무들이 생긴다. 의견 협의를 위한 토론, 진행상황 보고, 팀 규칙에 따른 업무 처리, 에러나 변동사항에 대한 피드백, git이나 notion 처리 등 많은 시간과 노력을 필요로 한다. 하지만 사회도 회사도 개발도 혼자 힘으로 하기보다는 협업을 했을 때 보다 효율적이고 시너지 효과를 낼 수 있게된다.

    퍼스트 프로젝트 개인 스터디 노트

     - 무엇보다 프로젝트를 진행하면서 공부가 정말 많이된 것 같다. 인터넷의 "프로그래밍 공부하는 법"와 같은 부류의 글을 보면 "직접 서비스를 한 번 구현시켜봐라"라는 내용이 많았다. 내가 머리 속으로 기획한 것들을 어떻게 구현시킬 수 있을지 공부해보고, 직접 구현하면서 겪는 문제들도 대면하고 해결하면서 많은 것을 공부할 수 있었다. 그리고 이렇게 공부했던 내용 및 에러 상황들을 별도의 개인 스터디 노트로 만들어 관리하니, 반복되는 실수를 줄일 수 있었다.

     - 또한, 팀내에서 규칙을 정하고 git, notion, figma, miro, gitbook, zoom 등의 협업툴을 매일 활용하기였기에, 이러한 협업툴을 다루는 기술 및 이해도 같이 성장할 수 있었다. 아쉬움도 많이 남았지만, 2주 동안 정말 열심히하였고 많이 성장하였다. 다시 한 번 믿고 함께 고생한 팀원들에게 고맙다는 말을 하고 싶다. 

    댓글

Designed by Tistory.