배포를 향한 고군분투

24-06-03  |  해커톤 그 이후의 이야기

📌 "꼭 배포하겠습니다!!!!!"

1. 나작길 언제 배포해요?

해커톤 발표 때, 마지막 멘트로 한 말이 있다.
"현재 최소 기능으로만 작동하게 하여 서비스를 확인할 수 있는 링크를 제공해드렸다. (당시 캔버스에 캐릭터 선택, 도형 추가 등의 기능과 다운로드 기능까지만 하여 netplify로 배포한 링크를 공개했다.)
앞으로 글자색 변경, 스티커 선택 등 다양한 기능을 추가하고 싶다.
이후 꼭 배포를 할 계획이니, 지켜봐주세요"

위와 같은 맥락의 말을 했던 것으로 기억한다.

그래서 한동안 만나는 사람마다 나에게 "나작길 언제 배포해요?" 질문을 해왔다.

"곧 배포해요. 하하하"라고 답은 하지만, 생각보다 늦어지는 일정에 약속을 못 지킬까봐 속은 문드러져만 갔다.

결론적으로 말하자면 아직도 배포를 못 했다.

왜 그동안 배포를 못 했는지 변명 아닌 변명을 이 글을 통해서 작성해보려고 한다.

2. 여러 버전의 나작길

나작길은 여러 개의 버전이 존재한다.

1.0.0-beta

  • 해커톤에 나갔을 당시, 작성한 코드
  • 해당 코드로 임시 배포를 진행함

1.0.1

  • 1.0.0-beta 코드가 작성한 당사자가 알아보기 힘든 수준이어서, 아예 프로젝트 생성부터 다시 시작함

1.0.2

  • 기존의 React(vite)가 아닌, Next.js로 프레임워크 변경

my-precious-gil

  • 피그마 클론 코딩을 기반으로 한 나작길 서비스

지난 8월 해커톤 이후로, 이렇게 여러 버전의 나작길이 탄생하게 되었다.
그래서 각 버전마다 겪었던 어려움과 왜 다른 버전으로 변경하게 되었는지를 서술해보고자 한다.

3. 1.0.0-beta : 해커톤 나갔을 때 작성한 버전

당시 나는 멘토링을 받은 적이 있는데, 파일 구조에 대해 질문을 하자 멘토님께서 추천해주신 방식이 container-presenter 패턴이다.
지금 생각해보면 멘토님께서 이야기 해주신 바를 내가 잘못 이해한 것은 아닐까 싶기도 하다.

container-presenter 패턴을 사용하고자 아래와 같이 파일 구조를 잡았다.

// container-presenter 패턴

najakgil-client
├── public
|   └── assets
|       └── icon
|       └── image
└── src
   ├── home
   |  └── Home.container.tsx
   |  └── Home.presenter.tsx
   ├── make
   |  └── Make.container.tsx
   |  └── Make.presenter.tsx
   ├── preview
   |  └── Preview.container.tsx
   |  └── Preview.presenter.tsx
   └── mypage
      └── MyPage.container.tsx
      └── MyPage.presenter.tsx

내가 이해한 container-presenter 패턴은

  1. 서비스 로직 등을 container 파일에 담고, UI 로직은 presenter 파일에 담는 것이다.
  2. (어디서 나온 생각인지 지금은 기억이 안 남) 컴포넌트 사용 지양

잘못된 이해와 해석으로 돌이킬 수 없는 강을 건너게 되어버렸다. 핵심 페이지인 Make 페이지990줄의 코드를 가지게 되었다.
코드의 양이 많다는 것을 이야기 하고자 하는 것이 아닌,
컴포넌트 분리도 없고 스타일 코드도 다 한꺼번에 작성되어 있다보니 그야말로 스파게티 파티였다.
무엇보다 내가 읽기 힘들었다.

리팩토링이 절실하게 느껴졌고, 해당 코드 위에서 진행할 지 아니면 아예 새롭게 프로젝트를 만들지 고민이 생겼다.

3. 1.0.1 : 새로운 기술스택을 가지고, 뒤엎은 버전

1. 프로젝트 폴더 구조 변경

najakgil-client
├── public
|   └── assets
|       └── icon
|       └── image
└── src
   ├── components
   |  └── Header
   |  └── BottomNav
	 | 	└── ...
   |
   ├── home
   |  └── components
   |  └── HomePage.tsx
   ├── make
   |  └── components
   |  └── MakePage.tsx
   ├── preview
   |  └── components
   |  └── PreviewPage.tsx
   └── mypage
      └── components
      └── MyPage.tsx

기존의 container-presenter 패턴을 버리고 새로운 폴더 구조를 채택하게 되었다.
이때 알게 된 사실은 내가 container-presenter 패턴에 대한 이해를 잘못 하고 있었다는 점요즘에는 container-presenter 패턴을 사용하지 않는다는 사실이었다. 여러 아티클에서 container-presenter 패턴 사용을 지양할 것을 추천하고 있었다. 그 이유로는 container-presenter 패턴은 컨테이너 컴포넌트와 프레젠터 컴포넌트를 명확히 분리한다. 이로 인해 각각의 컴포넌트가 특정 역할에 묶이게 되며, 재사용성이 떨어질 수 있다는 것을 우려하였다. 또한 가장 큰 변곡점으로는 React Hook의 등장이라고 할 수 있을 것 같다. React Hook을 비롯하여 Context API, 그리고 Redux Toolkit과 같은 신기술들이 등장하면서 상태 관리와 컴포넌트 간 데이터 전달을 더 쉬워졌다.

그래서 위와 같은 폴더 구조를 가지게 되었다. 여러 페이지에서 사용되는 컴포넌트의 경우, common이라는 폴더 안에 모아두었다. 그리고 해당 페이지에서만 사용하는 컴포넌의 경우, 해당 페이지 폴더 안에 components 폴더를 만들어서 해당 폴더 안에 넣어두었다.

2. 기술 스택 변경

1.0.0-beta 기술 스택 : recoil, Fabric.js, styled-components
1.0.1 기술 스택 : zustand, storybook, emotion, tanstak-query

1.0.0-beta에서는 해커톤이기에 구현하기 급급하였다. 하지만 실제 배포를 목표로 하는 1.0.1 버전에서는 기술 스택 선정부터 프로젝트 세팅에도 신경을 많이 썼다.

패키지 매니저

패키지 매니저 선택부터 고민을 하였다. Yarn은 자체적인 캐시 매커니즘이 있어 Npm에 비해 패키지 설치 속도가 빨랐다. 무엇보다 yarn.lock 파일을 통해 정확한 버전의 패키지를 설치하여, 일관된 개발 환경을 유지할 수 있는 점이 매력적으로 느껴졌다. (참고)

lint 설정

prettier와 eslint를 통해 lint 설정 또한 해주었다. 일관적으로 코드를 작성할 수 있게 도와준다는 점에서 이점을 가진다고 본다.

전역상태관리 라이브러리

1.0.0-beta에서는 Recoil을 사용하였다. 당시 Redux vs Recoil vs ... 이렇게 고민을 하고 있었는데, Redux의 경우 러닝 커브가 길다는 이유로 Recoil을 채택하여 사용하였다.
라이브러리 선택 시 살펴보는 점은 npm trends를 통해 많은 사람들이 즐겨쓰고 있는지 그리고 업데이트 주기이다. 이렇게 두 가지 기준을 바탕으로 선택을 한다고 말했지만, 사실상 다음과 같이 설명이 가능하다고 본다. 라이브러리 커뮤니티의 활성도에 따라 이슈가 발생했을 때 대응 속도 등이 다를 것이라고 바라보았기 때문이다. 하지만 해당 자료에서도 확인이 가능하듯이, 업데이트 주기가 길어지고, 메모리 누수 이슈이다. 이러한 이유에서 다른 전역사애관리 라이브러리를 찾아보았다.
선택지로는 jotai, zustand 등이 있었고, zustand를 사용해보고 싶다는 마음에서 zustand를 선택하였다.

storybook 당시 테스트 코드에 관심이 많아서 UI 테스트 측면에서 용이하게 사용이 가능한 storybook을 도입하였다. 하지만 제대로 사용은 못 한 거 같아서 아쉬움이 남는다. 처음에는 호기롭게 storybook도 알차게 사용하고자 하였으나, 실제 구현에 우선순위가 밀려 등한시하게 된 거 같다.

tanstak-query 캐싱 등 다양한 이점들을 가지고 있다고 판단하여 채택하였으나... 서버와 연동을 하지 않아서 사실상 필요가 없었다.

4. 1.0.2 : 마지막 기회라고 생각한 버전

1.0.1 버전이 사실상 배포를 위한 버전이라고 생각하였지만, 결론은 제대로 되지 않았다는 것이다.
그때 기억을 되짚어보면, Fabric.js 사용의 어려움 그리고 나태함이었던 것 같다.

Fabric.js 공식 문서는 너무 읽기 힘들었다. 그리고 TypeScript 사용을 하였는데, type 에러도 발생하고(어떤 에러인지 정확하게 기억이 나지 않았음), 하지만 모든 것의 근원은 나태함이다.

8월 해커톤에 나가고, 해커톤 끝나고 9월에 첫 배포를 목표로 했다. 사진1

하지만 무산되고 새해부터 다시 프로젝트를 진행하기로 하였다.
새해가 밝았고 우리는 다시 작업을 진행하였다.
사진2

토이 프로젝트의 가장 큰 숙적은 나태함이라고 생각한다. 초반의 열정은 잊혀지고 늘어진 상태로 꾸역꾸역 이어가는 것이다. 마지막으로 불사른 것이 1.0.2 버전이었다.

1. Next.js로 변경

프레임워크인 Next.js로 변경하였다. 그동안 React를 고수한 이유는, 가천대 재학생 타겟의 서비스이니 SEO는 굳이 필요없을 것이라고 생각했기 때문이다. 하지만 당시 Next.js 공부를 하고 있고 SSR, SSG 제공, 이미지 최적화 등 React 기반에서 더 많은 이점을 제공한다는 판단이 들어 Next.js로 마이그레이션을 진행하였다.

마이그레이션이라고 표현하였지만, 다시 프로젝트를 생성하는 식으로 진행하였다. Next.js를 도입해도 아직 서버 컴포넌트에 대한 이해도가 떨어진다고 생각하여 page 라우터를 채택하였다.

2. Fabric.js 없이 Canvas 구현하기

Fabric.js 공식 문서를 읽는 것은 너무 힘든 작업이었기에, 자체 구현을 하자라는 생각이 든 거 같다.

이 내용부터는 다음 포스트에서,,,