MMZ 일지 17. 개인 회고

1
post-thumbnail

오늘 뭐먹지 고민될 때, MMZ


기획동기

MZ 세대를 위한 레시피 공유 서비스

-> 위트있는 감성, 쉐어 문화

치솟고 있는 배달비와 물가 때문에 한동안 뉴스에서 식비 절약에 관련한 뉴스가 많았다. 그래서 간편식 밀키트를 구매하거나 직접 요리를 하는 사람들이 늘었다고 한다. 하지만 유투브 외에 요리를 공유할 수 있는 사이트가 많지 않았다. 있더라도 자취생보다 주부를 대상으로 한 듯한 메뉴가 많았고, 쇼핑몰 같은 UI가 불편했다.

주요 기능

  • 레시피 조회

  • 카테고리별 조회 가능
    오늘 뭘 먹을지에 대한 고민을 해소할 수 있도록, 메인 페이지 아이콘을 클릭하여 조회가 가능하다.

  • 자취생을 위한 간편한 레시피를 등록
    가입한 회원을 대상으로 레시피를 등록하거나 수정할 수 있다.
    초기에는 영상도을 추가할 수 있도록 설정하다가 등록할 때 사용자가 입력해야하는 부분이 너무 많음을 인지하고 해당 기능은 생략했다.


부가 기능

  • 꼭 필요한 재료 표기
    : 자취생에게는 모든 준비하기 어려운 재료 기구들이 있다. 그래서 필수인 재료와 부수적인 재료를 구분하는 UI가 필요하다. 사용자가 대체 재료는 집에 있는 다른 재료로 교체할 수 있음을 알려준다.
    e.g. 월계수잎을 넣어주세요.

  • 준비한 재료 체크표기 가능
    : 요리 재료가 많으면 준비하다가 놓치고 어떤거 더 필요한지 고민하느라 우왕좌왕하는 경우도 있다. 그래서 재료에 체크 표시를 할 수 있는 기능을 추가하기로 했다.
    e.g. 이마트 종이 영수증 대신 발급되는 모바일 영수증에 배송 후 배송 체크를 표기할 수있는 영역이 있다.



사용한 기술

신입 개발자로 범용적인 스택을 채택하되, 장단점을 비교하려했다.
아래 기술한 특징은 해당 스택을 선택한 주요한 요인이다.

Typescript

  • 컴파일 단계 즉, 런타임 전에 오류 검사가 가능하여 예상치 못한 오류를 방지
  • 구체적인 타입을 명시하여 입력값에 대한 정보 제공
    -> 유지보수 단계에서 유용

React

  • Typescript와 함께 사용하기에 Vue.js 보다 간편함
    -> 함수형 프로그래밍에서 유용

Styled-componenets

  • 컴포넌트 단위로 CSS 적용, 분리 가능

Axios

  • 자동 문자열 변환 기능과 에러처리, 브라우저 호환성에서 fetch 보다 편리
  • 커스텀 가능한 서드파디 라이브러리로 기능이 설정 가능

Redux-toolkit

  • 가장 범용적인 스택(Redux)으로 RTK가 적용되며 보일러 플레이트가 적어짐
  • 추가 라이브러리 설치 없이 비동기 처리 가능(Thunk)
  • 모두의 러닝커브를 고려하여 선택

가장 고민되었던 스택이다. 거론되었던 Recoil, React-query와 비교하여 범용적이고 pre-project에서 한번 사용해봤다는 것 외에는 두드러지게 장점을 찾기 어려웠다.(심지어 아래 사진처럼 쉽고, 간편하고 여러 기업에서 사용하는 것으로 안정성 문제도 해결된다.)
하지만 팀 프로젝트이다. 완전 새롭게 학습하기에는 현실적으로 어려울 것 같아서 심도있게 Redux를 학습하는 방향으로 선택했다. 추후 개인 프로젝트나 실무에서 적용하는 방법이 최선이었다.

리코일과 리덕스의 관계 예시


셀프 회고

Keep

(1) 스케줄 공유

  • 맡은 일의 예상 소요시간 공유
  • 일일회의에서 오늘 할일 및 스케줄 변동 공유

pre-project에서 Github 칸반으로만 일정을 조회해서 날짜별 진행상황을 알기 어려웠다. 그래서 노션에 스케줄표를 만들어 예상소요시간을 기제하고 기한 안에 끝내도록 노력했다. 예상밖의 일이 발생한 경우(중요도 변동으로 급하게 다른일부터 처리, 에러 핸들링) 일일회의에서 스케줄 변동을 공유하고 오늘 어떤 일을 할지 보고하고 스케줄을 공유했다.

어려움이 있는 경우 공론화하여 해결책 모색

그리고 협업이다보니 여러 고충이 있었다.
특히, 초반엔 스케줄 공유를 러프하게 진행해서 pre-project의 문제를 반복할 뻔 했다. 그래서 오전 각자 스케줄이 어느정도 진행되고 있는지 공유했다.
연관된 작업이 있는 경우, 예를 들어 다른 개발자가 레시피 검색 페이지 구현을 한다고 했을 때, 담당했던 정렬 기준 버튼(공용 컴포넌트)을 먼저 완성해두면 바로 서버 요청 로직을 작업 할 수 있으므로 대기시간을 줄일 수 있다. 이처럼 각자 스케줄을 능동적으로 수정할 수 있도록 했다.


(2) 새로운 언어를 습득하여 프로젝트 진행 : Typescript

  • 모두의 러닝커브를 고려하기
  • any 타입 지양, interface 등으로 타입 명시

새로 도입할 기술은 1개로 제한했다.
pre-project부터 Typescript를 메인프로젝트에서 사용하자고 이야기가 나왔었다. Typescript와 궁합이 좋으며 비교적 러닝커브가 낮은 recoil을 적용하자는 의견이 나왔지만, pre-project의 경험으로 2개 이상의 새로운 툴은 버거울 수 있을 것 같았다.(pre-project에서는 상태관리 툴을 redux-toolkit을 새로 배워서 적용했다. 기획 단계를 제외하고 열흘 정도에 구현하는데도 버거움이 느껴졌었다.)
recoil은 러닝 커브가 낮고 redux에 비해 장점이 많아보였지만 협업이니 Typescript 하나만 추가하기로 했다. 프로젝트를 진행하며 잘한 선택이라고 생각되었다. Javascript와 많이 다르진 않지만 이벤트, redux 타입 등 고려해야할 사항이 많았다. 그리고 팀원 한분이 하차를 고려할 정도로 어려움을 느꼈었다. 에러 핸들링에 어려움을 느낀 팀원을 위해 게더 타운에서 화면 공유로 원인을 추적해갔다. 다른 사람이 작성한 코드를 보기는 어려웠지만 타입 선언에 대해 더 공부하고 설명하려고 했던 계기가 되었다.

eslint와 함께 any 지양하고 구체적인 타입을 적용

  • interface, type alias로 명시

any 타입은 꼭 필요한 경우가 아니라면 최대한 구체적인 타입을 선언하여 적용했다. 덕분에 재사용할 때 잘못된 입력값으로 에러가 발생할 수 있는 상황을 방지했다.


(3) 구현하는 방식의 장/단점을 비교

메뉴바를 구현할 때 익숙한 Link 대신 NavLink 의 active 기능을 활용하여 현재 위치를 표시 했다. 그리고 이미지 미리보기 기능을 구현할 때, 처음에는 FileReader을 이용한 방법으로 적용했다가, URL 객체로 구현하는 방법도 있다는 것을 알게되었고, 이미지가 여러개인 우리 서비스에는 후자가 더 적합하다고 판단하여 리펙토링을 진행했다.


(4) 이전 직무 경험을 살려 디자이너와 협업

  • 디자인 프로세스에 대한 이해
  • 디자인 컨셉 keyword로 제시

디자이너를 따로 모집해서 협업했던 경험이 좋았다.
실무에서 디자이너와도 협업을 진행하기 때문에 의견이 나왔을 때 덥썩 물었다. 특히, 백엔드와 pre-project 진행 했을 때와 다른 문제점도 만날 수 있었고, 이 경험을 통해 스케줄 조절과 소통적인 측면에서 배울점이 많았다.

패션 디자이너로 일했던 경험 살리기

  • 원하는 컨셉은 keyword를 중심으로 전달 : 키치,

여성복, 핸드백 분야에서 일했던 경험으로 디자인이 어떤 단계로 진행되는지 알고있다. 일할 때 옆에서 웹디자이너가 어떻게 일하는지 어렴풋이 알고있는 정도지만 프로세스는 비슷했다.
디자이너분의 스케줄 상 기획을 온전히 같이 진행하지는 못했다. 개발자들 끼리 먼저 회의를 진행하고 어느정도 결정된 컨셉을 전달해야했다. 디자이너에게 빠른 이해를 돕기위해 키워드를 뽑아 컨셉을 전달했다.

키치(Kitsch)는 미학에서 보기 괴상한 것, 저속한 것과 같은 사물을 뜻하는 미적 가치이다.

키치의 사전적 정의는 위와 같지만 디자인쪽에서 받아들이는 의미는 '젊고, 개성적, 컬러풀' 등의 의미로 받아들여진다. MZ 세대를 대상으로 했기 때문에 레퍼런스를 종합해 봤을 때, 원색의 대비감이나, 컬러풀한 이미지로 귀결되어 해당 키워드를 다시 언급하여 원하는 방향을 알려주었다. 후에, 디자이너가 제안한 무드보드 중 레드로한 감성이 더해져서 좋은 결과물 낼 수 있었다.

개발자로서 협업은 처음이므로 아주 좋은 경험이었다.




Problem

클론코딩 pre-project와 같은 팀구성으로 회고를 하며 느꼈던 문제를 줄여보자는 생각으로 프로젝트를 진행했다. 허나... 변수가 많았다.

(1) 구현할 화면의 기능 확정이 안되어서 마크업에 많은 시간 소요

  1. 담당한 와이어프레임 작성 페이지와 구현 페이지가 달랐다.
  2. 기능에 대한 이해도가 각자 달랐다.
  3. 와이어프레임 작성 전 모든 구성원의 소통이 부족했다.
  4. 애매하게 결정된 사항이 많았다.
  • 해결방안 : 전체 회의 필요 + 필수 구현 기능 확정

이 문제가 발생한 큰 요인은 크게 4가지였다고 생각한다.
반복되는 수정, 번복은 이해도가 달랐기 때문에 발생한 것 같았다. 다 모인 자리에서 컨셉에 맞춰 필수 구현 기능을 확정해야할 것 같아서 전체 회의를 잡았다. 기획 초반에 회의로 틀을 잡아야 구현 단계에서 불필요한 과정이 생략됨을 느꼈다.

담당 역할

  • 와이어프레임 : 로그인 관련 페이지, 레시피 조회 페이지
  • 기능 구현 : 레시피 등록, 수정 페이지, 메뉴바 등

연휴 및 스케줄 조율 문제로 와이어프레임을 프론트단에서 작성하고 그 틀에 맞춰 디자인을 조금 수정하는 방향으로 얘기했다.
와이어프레임을 수정하며 기능 구현 담당자를 정하는데, 로그인은 pre 때 담당했던 분이 하게되었고, pre-project의 경험으로 보아 인터렉션이 많아보이는 등록/수정페이지를 구현해야할 것 같았다. 안해본 이미지 전송 관련 기능도 구현해 볼 수 있었고, 다른 분이 담당하기엔 버거워보였다. 그래서 등록, 수정을 구현하게되었는데... 디자인 시안이 나오기 전에도 고려할 사항이 많았다.

상이한 이해도 : 간편한 레시피 vs 많은 필수 입력란

  • 각자 생각하는 구성이 달라서 발생한 문제
  • 배려심 넘치는 우리팀 😂

기획하는 페이지는 자취생, MZ 세대를 위한 '간편' 레시피인데 유투브 링크도 필수 입력이고, 유투브 링크를 등록하면 썸네일이 어떤 파일로 노출되는지 의문이 생겼다. 그래서 개발자 회의때 안건을 올렸는데, 계속 보류가 되는 느낌이었다. 수시로 회의가 진행되는데, 각자의 스케줄로 모든 구성원이 모일 수 없었고, 회의 때마다 마크업이 달라졌다. 개발자끼리 회의에서 A->B로 수정되었는데, 디자이너와 회의 때는 B->A'로 수정되는 것이 반복이었다. 확정되기 전까지 작은 컴포넌트를 구현하며 조금씩 수정했는데, 그마저도 사용하지 않게되는 상황이었다.
시간은 흐르고, 기능 구현에 많은 시행착오가 발생할 것인데, 마크업에 많은 시간을 투자하는 것은 문제가 될 것 같았다. 회의는 많았지만, 의미있는 회의가 필요했다. 빠른 시일내에 모든 구성원들이 모여서 기능을 정리해야 확정이 될 것 같았다.

백, 프론트, 디자이너가 한 자리에 모여서 기능 확정

더이상 보류는 없습니다!

역시나 각자 생각했던 방향성이 달랐다. 배려심이 깊은 우리팀은 상대방의 의견을 우선시하는 경향이 강했다. 그래서 허심탄회하게 의견을 내고, 구현해야할 기능을 확정했다.
이 후, 작은 수정만 발생해서 스케줄 예측이 가능했고, 불필요한 컴포넌트를 제작하는 등의 비효율적인 작업이 사라졌다.


(2) Props-drilling 으로 복잡해진 코드

  1. 문제점을 인지했지만 안고 갔다.
  2. Props 방식 때문에 수정이 어렵다.
  • 해결방법 : 상태관리 라이브러리 적용(리펙토링 필요)

이 문제는 1번에서 비롯되었다. 문제가 될 것임을 인지했지만 원론적인 개념에 갇혀 프로젝트 단계에서 해소가 되지 않았다. 기능 구현은 되었지만 컴포넌트간의 높은 의존도로 인해 유지보수가 어려워 에러 핸들링에 많은 시간이 들었다.

문제해결이 곧 설득력이었다.

결론적으로 이 문제점은 추후 리펙토링 과정에서 해결해갈 문제이다.

전역 상태는 프로젝트 전체에 영향을 끼치는 상태이다.

라는 전역 상태에 대한 원론적인 개념에 갇혔었다. 여러페이지 == 전역이라는 생각으로 상태관리 툴의 필요성을 느꼈지만, 억지로 props 방식으로 구현해갔다. 작은 구조의 pre-project에서 Redux-toolkit을 적용하니 더 복잡해졌던 문제도 있었고, 주변에서도 전역상태는 페이지 단위라는 이야기를 들어서 힘든 과정을 택했다.
특히, Typescript에서 drilling은 엄청나게 유지보수가 어려웠다. 중간에 기능이 추가되면 props가 연쇄적으로 추가되어 정의한 interface 관리에도 난항을 겪었다. 복잡한 연결성 때문에 서버로 전달할 데이터 구축에도 많은 어려움이 많았다. 덕분에 에러 처리에 익숙해지고 팀원들을 도와줄 수 있었지만, Redux-toolkit을 적용해야 유지보수가 수월할 것 같다.


(3) InputValue 관련 렌더링 에러 핸들링

공식 문서와 여러 자료를 찾아보며 useEffect 렌더링 순서, setState 원리 등 React 렌더링 과정을 자세하게 알아보았다.
컴포넌트를 작게 나누려다보니 <form> 요소 아래로 여러 컴포넌트가 추가되었고, 2번 문제로 복잡한 상태였다. state 업데이트가 비동기적으로 동작하는 것은 알고있었지만, JSX와 useEffect, 하위 컴포넌트 동작 순서를 알아보아보며 마운트 등 생소한 개념을 알게되었고 react를 더 깊게 알아보려고했다.

console.log와 디버깅 병행하여 에러 위치 추적

chrome 개발자 도구로만 디버깅을 하자니 react의 추상화된 코드도 노출되어 어려움이있었다. 그래서 console.log() 사용을 병행하여 의심되는 곳의 위치를 추적했다. 덕분에 react를 깊게 학습할 수 있는 계기가 되었다. vscode로 react 디버깅 기능도 테스트 해볼 예정이다.




Try

(1) 초반에 회의 횟수를 늘리고 구현 단계에는 필요한 경우만 회의

이번 경험으로 기능 정의를 할 때, 모든 구성원이 오해 없이 이해하는 것이 중요함을 깨달았다. 초반에 서로 이해가 되면 조금 더 능동적으로 작업할 수 있었을 것 같았다. 게다가 불필요한 과정이 생략되어 효율성도 늘일 수 있을 것이다.


(2) Redux-toolkit으로 리펙토링

유지보수를 위해 props-drilling을 해결해야 할 것이다. 컴포넌트 재사용에서 typescript의 장점을 느껴봤기 때문에 typescript와 함께 사용해보는 것도 좋은 경험일 것 같다.


(3) read.me 보강

배포중이지만 만약의 경우를 대비해 png 이미지로 기능을 설명하는 내용을 추가하려한다. 게다가 백엔드 ERD 관련 내용도 안내되지 않아서 보강이 필요할 것 같다.

팀 회고를 통해 wiki에 내용을 작성하고, read.me에 바로가기 링크를 추가하기로 했다.


(4) 기타 기능 추가

  • 게스트 계정
    담당했던 등록/수정페이지에 접근하려면 가입이 필요하다. 기능을 확인하려면 직접 가입해야하는 문제가 있고 편의성을 위해 게스트 계정 버튼을 추가해면 좋을 것 같다. 우선 RTK 적용 후 진행할 예정이다.

  • 레시피 순서 드래그로 제어 기능 추가
    수정할 때 더 사용성을 개선하려면 드래그로 순서를 변경하는 기능을 추가하고 싶다. 간편한 레시피이기 때문에 요리 순서가 여러개이지 않을 수 있지만 도전해보고싶다.

  • 레시피 조회 페이지 재료준비 체크박스 수정
    발표 전에 체크박스필수 재료 안내가 다른 기능으로 변경을 요청했는데, 필수 딱지는 추가되었지만 체크 박스 디폴트 체크는 변경되지 않았다. 기타 기능도 수정해야할 것 같다.

    • 체크표시 확성화를 false로 적용
    • 사용 방법에 대한 안내문 추가
    • 모바일 환경 엄지손가락 위치를 고려해 체크박스 오른쪽으로 이동
    • CSS 정렬 수정

0개의 댓글