2주 프로젝트 회고

Jiwoo Joy Kim (zuzokim)·2021년 6월 20일
0

Project

목록 보기
1/1

2주 프로젝트 진행

나 포함 프론트엔드 3명, 백엔드 1명으로 팀을 구성해 2주간의 프로젝트를 진행했다. 기존에 짜여진 테스트케이스를 통과하거나 정해진 결과물을 만드는 것을 벗어나서 진짜로 내가 만들고싶은 어플리케이션, 웹서비스를 만드는 일이었다.

그동안에 프론트, 백엔드 모두를 조금씩 경험해보긴 했지만 막상 내가 지금까지 배운 것만으로 정말 뭔가를 만들어낼 수 있나? 하는 의심이 든 것이 사실이다. 배운 것들을 기반으로 나에게 더 필요한 것을 스스로 찾아내야하는 과정이 되리라 생각했고, 실제로도 그랬다.

예술대학 학부생일때 처음으로 과제가 아닌 나의 작업을 만들던 때, 미술작가로서 처음으로 외부 갤러리에 전시를 열 때가 생각이 났다. 아무도 답을 내려주거나, 방향을 잡아주지 않았다. 목표와 기준 모두 스스로 정하고, 내 자신이 나의 가이드가 되어 작업을 진행해야했다. 이번에도 마찬가지였다.

세상에 없던 뭔가를 만들어내는 과정의 지난함은 피할 수 없는 것이겠지만, 그래도 계속해서 새로운 것을 찾아 만들고픈 나의 이 알 수 없는 욕망?은 역시 동료와 함께하는 것, 완성된 결과물을 사람들과 나누는 것의 중독적인 즐거움 때문이겠지 ㅎㅎ


사전 리서치와 기획

프로젝트 기획에 있어서 제일 중요했던 건 단지 취업을 위한 포트폴리오로써가 아닌, 실제로 상용화되기에도 좋을, 평소에 필요하다고 생각한 서비스면 좋겠다는 것이었다. 하지만 역시 세상엔 완전히 새로운 것은 없다. 따라서 평소에 눈여겨보던 어플리케이션, 사이트들을 떠올려보면서 레퍼런스들을 모으고 리서치를 했다. 모든 기능을 세세히 분석해본 것은 아니지만 각각의 큰 특징들을 파악했다. 그리고 그중에서 꼭 필요한 것, 조합해보면 좋을 기능들을 추려서 우리만의 프로젝트로 만들기로 했다.

프로젝트를 같이 진행하기로 한 팀원들 모두 리서치한 레퍼런스의 기능적인 특징과 장단점에 대해서 논의하는 것에 적극적으로 동참해줬다. 혼자서 하려면 못했을 것들이다.

북마크 아카이빙 & 알림 서비스

그렇게 정하게 된 2주 프로젝트의 주제는 '북마크 아카이빙 & 알림 서비스'다.

  • 첫번째, 우선 나부터도 개발 공부를 시작하면서 공식문서, 개발 사이트, 블로그 등등 여러가지 웹문서를 찾아다녔다. 그러면서 매일 크롬탭이 수십개가 넘어갔다. 어떤 날은 탭이 너무 가늘어져서 클릭이 어려워지거나 더이상 열리지가 않을 정도였다. 그래도 너무 중요하거나, 꼭 다시 열어보고 싶거나, 시간이 부족해 나중에 정독을 하고 싶은 경우가 많아서 탭을 끄지 못했다. 이걸 해결할 수 있다면 정말 좋겠다 싶었다.

  • 두번째, 크롬에는 북마크나 읽을 목록 기능이 있지만, 북마크에 저장하더라도 갯수가 많아지면 찾기 힘들어진다. 그렇다고 폴더 안에 폴더, 또 폴더 안에 폴더를 만들어 정리를 하면 중첩된 트리구조가 되어 다시 해당 북마크를 찾으러가기 어려워지는게 문제다. 그보다는 한 눈에 보고 바로 찾을 수 있다면 좋겠다고 생각이 들었다. 이부분은 크롬 북마크 기능을 애용하는 팀원이 공유해준 경험을 바탕으로 한 아이디어였다.

  • 세번째, 개발공부를 하는 대부분의 사람들이, 아니 블로깅을 하는 많은 사람들이 자신이 쓴 글을 다시 보지 않거나 써놓고도 시간이 지나면 잊어버린다. 다들 공감하리라 생각한다. 하물며 내가 쓴 글이 아닌 경우는 다시 봐야겠다고 생각하고도 까먹어버리기 일쑤일 것이다. 이 때, 우리의 서비스가 모아둔 북마크, 다시 보고싶은, 기억해두고 싶은 콘텐츠를 잊어버리지 않고 다시 볼 수 있게 해준다면 여타 북마크 아카이빙 서비스들과는 분명 다른 차별점을 가질 수 있겠다는 확신이 들었다.

프로젝트 Recollect

실제 나의 경험, 팀원들의 공감으로 시작된 초기 기획으로부터 자연스럽게 프로젝트 서비스명을 정할 수 있게 되었다. 그동안 미술작업을 하면서도 늘 어려웠던 게 이름짓기, 제목정하기였는데 고민에 빠져있던 새벽에 퐁! 하고 프로젝트명이 떠올랐다. 행운이라고 생각한다. 그렇게 정하게 된 프로젝트명 "Recollect" !! 팀원들도 너무 좋다고 해줘서 뿌듯했다. 아래 제작한 로고와 서비스 소개글을 붙인다.

< Recollect : re + collect >
recollect : 기억해내다, "모아서 + 다시보다"
늘어만가는 수많은 북마크, 정리해보겠다고 만든 북마크 폴더들...
혹시 읽지 않은 북마크들이 쌓여만 가고 있진 않으신가요?
걱정하지마세요. 나만의 설명을 덧붙인 북마크를 콜렉션에 담아 간직하세요.
읽지 않은 북마크들은 알림을 통해 Recollect하실 수 있습니다!


기능 리스트업, 와이어프레이밍/플로우차트 제작, 그리고 API문서 작성

시간은 2주뿐인데, 코드를 작성하기 전에도 해야할 일들이 참 많았다. 이렇게까지 다 해야하나? 만들면서 하면 안되나? 싶었는데, 지나고 생각해보면 초기 기획과 사전 준비는 확실히, 과하더라도 제대로 하는 게 100배 1000배 더 좋다고 생각한다. 왜그렇게 생각하냐고 한다면.. 저도 이렇게 뼈저리게 ! 뼈아프게 ! 느끼고 싶지 않았습니다....

처음에는 잘 와닿지 않았던 API 문서 작성의 중요성을 진행 중간쯤왔을 때 깨닫게 되었다. 생각보다 클라이언트에서 서버로, 서버측에서 클라이언트로 넘기고 넘겨받아야하는 데이터의 종류가 다양했고 그에 따른 엔드포인트 주소도 겹치지 않도록 세심히 설정해야했다.

이전에는 GET, POST 정도만 다루었다면 프로젝트에서는 GET, POST, PUT, PATCH, DELETE 거의 모두를 사용해야했는데 그때마다 보내야하는 엔드포인트 주소와 데이터의 형식, 내용을 잘 따져보고 꼭 ! 백엔드, 프론트엔드 사이에 정확한 합의를 거쳐 API 문서에 작성해야했다. 그 합의를 이루기 위해 너무 여러번의 회의를 해야했고, 수정을 하느라 시간을 많이 소비했다. (되도록이면 대소문자..까지 처음부터 정확히 정하자 ㅎ ㅏ..)

그동안 미리 작성된 API를 따라 코드를 작성하던 때는 알지 못했던, 직접 만들어보며 피부로 느낀 API 문서의 중요성..!을 느낄 수 있었다. 수고롭지만, 이번에 제대로 느꼈으니, 다음번엔 포지션간 더 정확한 소통을 통해 작성할 수 있겠지 !

목업과 UI 디자인

개발하는 사람이나 서비스 제공자 입장에서가 아닌,
유저 입장에서 생각해서 UX를 고려한 UI를 구상하자.

솔직히 고백하자면, UI 디자인을 사전에 더 구체적으로 그려놓지 못했다. 시간이 촉박해 박스와 간단한 엘리먼트 태그들로 와이어프레임만 그려놓고, css를 활용해 코드를 작성하면서 해결해보려고 했다. 하지만 철저히 실패했다고 할 수 있다.

팀원 각각 리스트업한 기능들과 컴포넌트,페이지 단위로 분업을 하고 합치는 식으로 작업을 진행했는데, 반복적으로 사용되는 버튼,로고,푸터 등의 컴포넌트를 만들고, 중간에 사용자화 css를 만들어 지정했는데도 서로가 만든 부분의 UI가 통일되지 못하는 문제가 있었다. 프로젝트 후반에 어느정도 수습을 하긴 했지만, 다음에는 꼭 ! ! 미리 UI를 철저하게 구상하고 그에 맞게 컴포넌트화해서 작업을 해야겠다는 뒤늦은 깨달음을 얻었다.

또한, 폰트 크기나 한 페이지에서 보이는 기능들의 위계설정도 중요하다. 팀원인 우리 4명은 자연스럽게 클릭할 수 있었던 부분을 외부인인 친구에게 기능 설명없이 보여줬을 때는 혼동하는 모습을 보이기도 했다. 절대 개선해야할 부분이라고 느꼈다.


내가 맡은 기능 구현

프론트엔드를 맡은 3명은 각자 구현해보고 싶은 페이지나 컴포넌트, 기능들을 맡아 진행했다. 나중에는 결국 각자 구현한 기능과 페이지를 서로 보완,수정하는 방식으로 작업했지만, 나의 손길이 가장 많이 닿은 부분을 꼽자면 크게는 아래와 같다.

전체적인 컬러칩 구성, 폰트 선정, 파비콘 설정

  • 로고 제작에 이어서, 로고에 어울리는 컬러칩과 폰트설정은 자연스럽게 내가 맡게 된 것 같다. 사용자화 css를 css 루트 설정으로 맞춰두고 팀원 전체가 공유할 수 있도록 했다. 그리고 꼭 해보고 싶었던 상단 탭 파비콘도 구글링을 통해 어렵지 않게 설정할 수 있었다. 이런 소소한 것에서 즐거움을 느끼는 편이다. ㅎㅎ

기본 랜딩페이지 & 로고, 로그인 버튼, 푸터 컴포넌트 제작

  • 랜딩페이지에서는 사실 비회원인 경우에도 서비스를 체험해볼 수 있도록 하는 것이 좋지만, 2주프로젝트에서는 메인 기능 로직 구현에 집중하기 위해서 아쉽지만 과감히? 포기를 하고, 로고와 서비스 설명 정도만 표기하기로 했다. 다음 프로젝트에서는 스크롤 애니메이션이나 서비스를 직관적으로 이해할 수 있도록 소개하고, 유저 유입을 가능하게 하는 랜딩페이지를 꼭 만들어볼 예정이다. 그래도 랜딩페이지를 만들면서 재사용성을 위해 로그인버튼과 푸터를 컴포넌트로 따로 분리해 제작한 것은 잘 한 선택이었다고 생각한다.

유저 프로필 페이지

  • 일단 기획단계에서 로그인 방식을 자체로그인 or 깃헙 소셜로그인으로 분기를 나누기로 했기 때문에, 유저 프로필 페이지에서도 자체로그인인 경우와 소셜로그인 경우를 다르게 렌더링해 보여줘야했다.

    • 자체로그인한 유저인 경우: 헤더에는 유저네임 & 가입한 이메일 표기, 유저네임 변경 & 패스워드변경 & 탈퇴 버튼 표기
    • 소셜로그인한 유저인 경우: 헤더에는 유저네임만 표기, 유저네임 변경 & 탈퇴 버튼 표기
  • 이를 위해서 기본적으로 유저네임가입한 이메일 주소 state를 상위 컴포넌트로부터 내려받아야했다. 또한, 조건문을 사용하기 위해 isSocialLogin state도 필요했다. 이 때 조금 혼란스러웠는데, state를 어디에 위치시킬지 판단해야했기 때문이다. 우리는 리덕스 없이 리액트만으로 프로젝트를 진행하고 있었고, 그에 따라 하위의 여러 컴포넌트들에서 접근해야하는 state는 공통의 부모 컴포넌트에 위치해야했다. 이 부분은 팀원들과 상의가 필요했지만, 팀원들 모두 각자 맡은 기능들을 구현하는데에 집중하고 있었고, 서로의 컴포넌트를 연결하는 작업을 그 후에 진행해야했기 때문에 이 부분을 결정하는데까지 시간이 지체되었던 점이 아쉬웠다.

  • 그리고 state 가 위치한 상위의 부모 컴포넌트로부터 쭉 내려받아오는 작업이 필요했는데, 여기서 상태관리의 중요성과 상태관리 라이브러리인 리덕스의 필요성을 절감했다.(리덕스 외에 또다른 상태관리 라이브러리도 더 찾아서 공부해봐야겠다고 생각했다.) 특히 내가 맡았던 프로필페이지는 최상위 파일인 App.js 로부터 가장 멀리 떨어진 하위 컴포넌트였다. 프로필 페이지로 props를 건네줄 중간 단계의 컴포넌트가 아직 없는 상태로 먼저 프로필 페이지를 제작하게 된 것도 state값을 가져오는 일을 한층 더 어려운 일로 만들었던 것 같다. 여기서 불편함을 크게 느꼈다. 중간 연결고리가 될 컴포넌트가 없더라도, 상태값을 활용할 수 있다면 코드적인 면에서는 물론이고, 작업의 효율 또한 올라가지 않을까하는 생각이 머리를 꽉 채웠다.

  • 물론 프로젝트 상황에 맞게, 서버로부터 필요한 유저정보데이터를 GET 요청을 통해 받아와서 Profile 컴포넌트에 state로 할당하고, 프로필페이지와 연결되는 Mypage 컴포넌트를 만들고, 팀원들과 코드 로직을 함께 공유하면서 state의 위치 설정과 props 연결 로직을 정리하는 것으로 위의 문제를 해결했다. 그리고 팀원들과 다짐했다. 리액트 상태관리를 위한 방법을 찾아 공부하고 꼭 써먹으리라고...

프로필 페이지 - 유저네임, 패스워드 변경, 탈퇴 기능 모달창으로 구현

사실 모달창은 프로필 페이지 구현의 일부지만, 회고 내용의 결이 조금 달라서 구분해서 작성해본다.

  • 처음에는 Profile 컴포넌트에서 '모달창을 띄웠을 때', 'X버튼을 눌러서 닫았을 때'를 판단하기 위한 초기 상태값을 false 로 지정하고, 그 값을 true, 혹은 다시 false로 바꿔주는 openPopupclosePopup 메소드를 각각 따로 만들어줬었다. 그런데 띄워야하는 모달창의 종류는 총 3개 - 유저네임 변경 / 패스워드 변경 / 회원 탈퇴 - 였고, 그러면 메소드는 6개가 있어야 했다. 다시 생각해도 비효율적이다. 단순히 boolean 값만 변경해주는 메소드인데 말이다.

  • 팀원이 준 힌트를 바탕으로, 초기 boolean값을 !boolean으로 뒤집어주는 메소드로 메소드 다이어트?를 시도했다. 그러면서 알게 된 것이 prevState를 활용하는 방법이었다. setState() 안에 콜백함수의 인자로 이전 상태값을 prevState로 넣어 사용하면 된다.

  • 리액트에서 setState()는 비동기적으로 실행되기 때문에, 단순히 객체 안에서 state값을 뒤집은 새로운 값을 할당해주면 안된다. 대신 이전의 state값을 기반으로 값을 업데이트해주어야하는 이런 때에는 인자로 업데이트 이전의 state값을 넣은 콜백을 사용해주는 것이 좋다. 이 방법을 사용하면서 리액트 공식문서 - setState() 를 보며 setState() 메소드에 대해서 다시 이해하는 시간을 가질 수 있었다.

//실제 프로젝트에서 작성한 코드
  handleUserPopup() {
    this.setState((prevState) => ({
      showUserPopup: !prevState.showUserPopup,
    }));
  }
  • 유효성 검사는 회원가입 기능을 구현한 팀원이 미리 마련해둔 유효성 검사 유틸 함수를 끌어와서 재사용할 수 있었다. 정규식으로 작성이 되어있었는데, 정규식에 대해서는 나도 더 공부를 해봐야겠다.

  • 유효하지 않은 유저네임과 패스워드일 경우 에러메세지를 버튼 하단에 띄우는 식으로 구현을 했는데, 이때 axios를 통한 서버로의 요청을 아예 진행하지 않도록 클라이언트에서 요청 차단하는 방식으로 처리를 했다. 클라이언트에서 에러메세지(피드백)를 즉각적으로 띄우는게 가능하고, 이미 유효하지 않은 데이터를 서버로 전송하는 것은 무의미할 것이라는 판단에서 결정한 일이었다. 하지만 나중에 프로젝트 피드백을 받으면서 알게 된 사실은, 클라이언트/서버 모두에서 유효성 검증을 해주는 것이 좋다는 것이다. 제대로된 데이터를 입력받더라도 서버로 요청을 넘기면서 데이터에 변형이 생기거나 변조문제가 생길 수 있기 때문이다. 이 부분은 미처 생각치 못했는데, 양쪽 모두에서 유효성검증을 구현하도록 보완을 해야겠다고 생각했다.
    프론트에서만 유효성 검사가 문제인 이유
    JavaScript: client-side vs. server-side validation -Stackoverflow

마이페이지, 리콜렉트페이지 Alarm 컴포넌트 제작

  • Alarm 컴포넌트는 이번 프로젝트의 Key 기능이 들어간 컴포넌트 였다. 그렇기에 페이지상에서
    • 눈에 띄도록 배치해야했고,
    • 추가만 해두고 읽지 않은 북마크의 갯수를 표시해주고,
    • 해당 알람을 클릭하면 읽지 않은 북마크들만 모아서 볼 수 있는 리콜렉트 페이지로 리다이렉트해줘야 했다.
  • 추가한 북마크를 클릭한 횟수를 DB에 저장하고, 횟수가 0인 북마크의 갯수를 알람 컴포넌트 벨류값으로 넣어 보여주는 방식으로 구현했다.

마무리

2주라는 시간은 정말 짧았고, 이 짧은 시간동안 생각보다 할 수 있는 것이 적었고, 생각보다 하게 된 것이 많았다고 느낀다. 기본적인 리액트의 라이프사이클에 대한 이해 부족, 상태관리의 미숙함, 쉽지 않은 에러핸들링, 처음 시도해본 기획부터 배포까지가 2주 프로젝트를 어렵게 했던 것들이었다. 마음은 앞서가고, 구현하고 싶은 기능과 UI가 머리에는 있는데 모든 걸 제대로 구현하기란 쉽지 않았다. 그래도 자바스크립트,리액트, ajax, 비동기 등등을 어디까지 내가 이해하고 있었는지, 효율적으로 에러핸들링을 하려면 어떻게 해야 좋을지, 유저경험을 고려하며 기능을 구현하는 것이 얼마나 중요한지, 내가 쓴 코드를 어떻게 하면 잘 설명할 수 있는지, 팀원이 쓴 코드를 이해하는 것이 왜 중요한지 ! 2주 프로젝트는 나에게 많은 것을 남겼다.

아쉬움도 많고, 첫 프로젝트인만큼 뜻깊은 프로젝트였다. 마음맞는 소중한 팀원들과 배려하며 협업한 시간들은 오랜 시간이 지난 후에도 기억될 것 같다. 부족한 팀리더(나ㅎ)와 함께 지치지 않고 밤낮가리지 않고 달려준 팀원들에게 고맙다고 꼭 말해야겠다. (우리팀은 팀리더,타임매니저,레코드매니저,커뮤니케이션매니저 라는 식으로 비교적 수평적인 역할분담을 했다. 누구 한 사람에게만 부담이 가지 않도록 하기 위함이었는데, 잘한 선택이었다 !) 이제, 다음 프로젝트, 그리고 그 다음 프로젝트에서 또 발전할 수 있다고 생각하고 그 전까지는 체력회복, 부족했던 공부를 하면 되겠다.

profile
- I make something! ✍🏽👩🏻‍💻🎬🎨💖🪑🔨🔜

0개의 댓글