방구석에 놔둔 개발 노트

1년차 웹 / 앱 프론트엔드 엔지니어의 좌충우돌 얼렁뚱땅 앞뒤짱구 생존기

2024-02-14: ‘준비물 챙겼어?’ 이야기 (1)

💭 개인 프로젝트를 다시 시작하다.

회사에서 6개월 동안 일을 하고 계약 만료로 그만두게 됐다.

이후에는 지쳐있던 멘탈을 관리해야겠다 싶어 한동안 코드를 멀리하고 12월에는 여행을 다니고, 1월에는 많은 분들과의 커피챗을 나누면서 개인적인 시간들을 보냈다.

그렇게 기력이 조금씩 회복되니 취업도 다시 생각해야 하고, 조금씩 코드를 다시 잡아야겠다는 생각이 들면서 사고치기 주도 개발(?)에 따라 오랜만에 개인 프로젝트를 시작하기로 했다.

이번 프로젝트의 계기는 12월에 진행했던 18박 19일의 배낭 여행이었다.

하도 숙박을 여러 곳에서 머물게 되다 보니 놓고 가거나, 잃어버린 물건이 없는지 짐 체크는 여행 중의 일상이었다.

그러다보니 언제부턴가 준비물 리스트를 종이에 써서 체크하며 다녔는데, 매번 이 종이를 꺼내서 체크하는 게 나중가서는 귀찮게 느껴지기 시작했다.

여행에서 돌아오고 나니 이 때의 경험을 기반으로 프로젝트로 만들고 싶다고 생각했다.

하지만, 1월은 여전히 기력이 없어서 좀 더 다양한 분들과 이야기를 나누면서 휴식을 취했고, 2월이 되어서야 본격적으로 프로젝트를 건드리기 시작했다.

시작 전에 혹시나 있을까 싶어 레퍼런스도 찾아봤는데 여행 관련 플랫폼에서도 관련 기능을 지원해주는 곳이 없는 것 같아서 적은 수요는 그래도 있을 것이라고 판단했다. (후에 초링(@earthloverdev) 님과 커피챗에서 ‘트리플’에 관련 기능이 있다는 걸 들었다..ㅋㅋ)

트리플에서 제공해주는 여행 준비 체크리스트

이번 프로젝트의 이름은 ‘준비물 챙겼어?’이고, 이번 프로젝트의 목표는 다음과 같이 결정했다.

  • 당연히 최소 목표는 런칭이다.
  • 작업하면서 그 과정들을 블로그에 서술해보고자 한다.
  • 여행 커뮤니티에 홍보를 올리고, 1달 동안 MAU 10명 이상을 유지해볼 것.
  • 꾸준하게 고객의 이야기를 듣고 기능을 개선해나갈 것.
    • 기회가 되면 웹 앱으로의 변환도 고려해보자. (React-Native의 Webview 기능을 통해서)

이전 ‘웨잇세컨드’의 프로젝트 경험에서 많은 걸 느껴서 그런지, 기획-디자인-개발-마케팅까지 모두 혼자 힘으로 하는 프로젝트를 이번에도 이뤄내보고 싶었다.

다만 저번에는 유지에 실패한 만큼 이를 반면교사 삼아 꾸준하게 관리할 수 있는 프로젝트로 만들어보고 싶다.

✌️ 초기 기술 의사 결정

이번 프로젝트의 초기 기술 선택은 아래와 같이 했다.

  • TypeScript
    • 요즘은 어느 모집 공고를 봐도 필수로 적혀있는 것 같다.
    • 앞으로도 TypeScript와는 계속 친해져야 하고, 잘 이해하면서 쓰고 싶어서 선택했다.
  • Vite
    • 폴더명으로 라우팅을 구축하는 Next.JS보다는 Create React App과 React-Router-Dom을 이용해 원하는 path와 원하는 컴포넌트를 연결짓는 방식을 선호한다. 그래서, 이번 프로젝트는 빌드 도구를 통해서 직접 React 환경을 구축하기로 했다.
    • Vite를 쓴 이유는 Webpack과 달리 프로젝트를 구축하는 시간이 덜하다는 점이었다.

      Webpack으로 초기 세팅을 했을 당시, 세세한 옵션들까지 다 설정하는 것 때문에 시간이 오래 걸렸는데, Vite는 필요한 라이브러리만 결정하면 기본 세팅을 완료해주니 React 프로젝트를 시작하는 게 굉장히 편했다.

    • 아울러 Webpack보다 빌드 시간이 더 빠르다는 특징도 많이들 언급해주셔서 Webpack 기반인 Creact React App을 이용해 프로젝트를 진행했던 사항과 달리 이번엔 Vite를 기반으로 React 프로젝트를 진행해보고 싶었다.

  • Jotai
    • 상태 관리는 지금도 고민중이지만, 지난 경험을 돌이켜볼 때 이번 프로젝트에서도 클라이언트 내에서 관리할 값이 많지 않을 것이라고 생각했다.
    • Recoil은 저번 프로젝트에서 써봤으므로 이번엔 Jotai를 써보기로 했다. (zustand나 Redux Toolkit은 이번 프로젝트에서 쓰기엔 store로 관리할 만큼 큰 규모가 필요하지 않을 거라고 판단했다.)
  • Firebase
    • 한 번 먹어본 맛이 가장 익숙하고 좋은 맛이라고 했다.
    • 사실 Supabase를 추천해주신 분들이 계셨는데, 프로젝트가 한 계정 당 2개까지만 무료로 제한된다는 이야기를 듣고 접어뒀다.
      • 본 프로젝트가 이용자가 많아져 마이그레이션에 대한 고민이 생기거나, 다른 대규모 프로젝트를 계획하게 된다면 그때 써보지 않을까?
  • styled-components
    • 이전에 CSS-in-JS를 쓰는 이유에 대해서 고민한 적이 있다.
      • 이 방식을 쓰는 건 단순히 컴포넌트의 재사용성 때문에 쓰는 거였을까?
      • 돌이켜보면 특정 값만 props를 통해서 변경하면 되는, 재사용성보다는 상태 변화에 따라 즉각적인 값 변화가 가능해서 쓴 것에 큰 장점이라고 판단했었다.
      • 그래서 이번에도 무난하게(?) styled-components를 선택하기로 했다.
    • [부제] zero-runtime css이라 불리는 vanilla extract나 panda css를 사용하지 않는 이유는?
      • prop을 통해서 특정 값만 관리하고 싶은데 classname에 배치하여 통째로 바꾸는 구조를 좋아하지 않는 것 같다, 내가.
      • 근데, 가장 큰 이유는 이런 css 라이브러리들이 Window OS에서 이슈가 있는 듯 하다..
        • 서버 컴포넌트에서 기능을 적용해봤지만 되지 않고, ‘use client’를 입력해 클라이언트 컴포넌트로 적용해야만 기능이 잘 작동됐다.
        • 원인이 궁금해서 이슈들을 찾아봤지만, 이 이슈들이 closed라고 해도 내 쪽에서는 계속 발생했으며 일부 이슈 수정 방향에 대해서 다른 사람들이 만든 패키지들을 설치하라는 것도 있었는데 이럴 경우는 package.json이 지저분해질 걸 생각하니 좋지 않다고 생각했다.
        • 그런 이유에서 사실 드랍했는데, 지금 글을 쓰면서 생각해보니 지금 작업하는 환경이 Vite이고 CSR이라서 생각해보면 문제되지 않는 이슈….잖아?🤦
          • 이럴거면 진작 쓸 걸 그랬다, 으흑흑….
          • 하지만, 이미 진행이 좀 된 상태라… 나중에 마이그레이션 하게 된다면 고민해봐야겠다(…)
          • 혹시나지만 이러니 나한테 맥 쓰라는 사람 있으면 돈 없는 백수에게 사줄 거 아니면 그런 말 하지 맙시다ㅂㄷㅂㄷ
  • i18n-next
    • 이 라이브러리는 희망사항으로 설치했던 건데, 해외에도 이용자가 있으면 좋겠다는 바람이 있어서 설치해보고 적용해보기로 했다.
    • 언어 지원 기능을 구현한다는 가정 하에 기회가 된다면 해외 쪽 홍보도 해보고 싶은데.. 이건 게스트하우스 연줄을 이용해봐야겠다..(될 지, 안 될 지 모르겠지만!)

우선 기초 라이브러리는 추후에 또 변경이 있을 수는 있지만, 이렇게 시작하기로 했다.

추가로 좀 더 생각하고 있다면 만든 걸 가지고 React-Native로 옮긴 뒤 WebView로 써먹고 싶다는 건데 그건 일단 정착이 되고 나서 생각해도 늦지 않다..^^

지금은 구현하고 런칭부터 하는 것까지가 목표다.

🎨 대략적인 디자인 그려보기

요즘 여러 UI 관련 사이트에서 다양한 앱을 구경한 덕분인지, 디자인에 필요한 요소들이 어떤 것인지 판단되는 것들이 생기니까 디자인 초안은 생각보다 빠르게 그려낼 수 있었다.

다만 체크리스트니까 TodoList 기반의 웹사이트라고 해도, 이왕이면 쓰는 사람들이 좋아할 만한 디자인이었으면 좋겠다고 생각해 약간 욕심을 부렸는데, 이게 오히려 개인적으로는 화를 자초한 듯한 느낌이 든다..^^ (넣을 기능이 많아졌다는 이야기이다…😭)

색상에 대해서는 파란색으로 테마를 잡았는데, ‘도전’이나 ‘자유’를 의미한다고 해서 여행을 준비하는 사람들의 이미지와 어울릴 거라 생각하고 이쪽으로 결정했다.

현재 디자인은 아래 링크를 통해서 구경할 수 있다. 많이 부족하지만 일단 현재는 이 정도로 하고 추가할 게 있으면 조금씩 늘려갈 예정이다.

https://www.figma.com/file/p7uM1yZSHFh05LIsu5L0tj/%EA%B0%9C%EC%9D%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8?type=design&node-id=12%3A45&mode=design&t=WIrWKTVSY1NqLCB1-1

기획서는 공책에만 써두고 디지털로 옮겨놓지 않았는데, 요 figma 문서에 모든 기획 내용이 다 담도록 할 예정이다.

어느 정도 가닥이 잡힌 뒤에는 추후 README나 github wiki를 통해서도 작성해 두려고 한다.

👍 1주차에 한 작업들

  • 기본 요소 페이지 제작

    웹 사이트에서 기본 요소라고 했을때 떠오르는 것들이 몇 가지가 있다. (물론 사람마다 다르겠지만…)

    • 로그인, 회원가입, 비밀번호 찾기, 비밀번호 변경

    이번 주는 디자인 초안을 완료한 뒤, 바로 위의 페이지들의 구현을 진행했다.

    figma의 Dev Mode가 결제자들을 대상으로만 지원해준다는 걸 듣고 좀 아쉬웠는데..

    어차피 기획, 디자인, 개발까지 다 하는 입장에서 생각해보면 사실 혼자서 모든 정보를 다 알고 있으니 큰 문제는 되지 않으리라.

    그래서 필요한 값들은 figma에 별도로 메모해서 기록해뒀다.

  • 폴더 및 파일 구조에 대해서

    1. 케밥 케이스

    이번 폴더 구조에서 특이점이 있다면 파일명이 ‘케밥 케이스’로 되어있다는 건데, 처음에는 카멜 케이스나 파스칼 케이스를 쓰려고 했지만 이런 부분에서는 어디는 대문자로, 어디는 소문자로 쓰여서 통일성이 없다는 생각이 계속 들었다.

    이 부분에 대한 고민을 하고 있었는데, 마선생(@horse_sensei) 님께서 케밥 케이스를 말씀해주셨다.

    확실히 이 방식을 차용하니 생각했던 고민들이 다 해결되어서 만족스러웠다. 고마워요, 마선생 님!😄

    1. 같은 파일명

    이번 프로젝트에선 하나의 컴포넌트와 엮어있는 사항들은 전부 같은 이름을 차용하기로 했다. 아래의 이미지처럼 말이다.

    위와 같이 컴포넌트명이 동일하다면, 엮어있는 hooks나 styles, types 등도 같은 파일명을 쓰도록 했다.

    이런 식이라면 해당 컴포넌트는 같은 이름으로 된 파일들에서만 관리된다는 걸 알 수 있고, 또 이슈 수정 시 컴포넌트를 특정하여 트래킹하기도 쉬울 거라고 판단했다.

    단, input, button과 같은 공용으로 쓰이는 요소들에 대해서는 common이라는 폴더에서 따로 관리하기로 했다.

  • 정책(policy) 폴더

이번 폴더 구조에서 특이점인 폴더가 있는데 policies, 즉 정책을 가리키는 폴더이다.

이 부분은 전에 회사를 다닐 때, 잠시 계시다 떠나신 시니어 개발자 분께서 코드는 내용이 무엇인지 읽히는 게 명확해야 한다고 말씀해주시면서 조건을 관리할 때 이런 식으로 하면 좋을 것 같다고 제안해주셨던 방법이었다.

policies 폴더에 있는 파일들은 위와 같이 조건문들을 관리하는 내용들이 대다수이다.

그리고 이런 식으로 policies에 있는 정책을 가져와 쓰면 profit.

확실히 여러가지 조건문을 놔둔 채로 있는 것보다 함수명을 명확히 작성하여 해당 코드가 뭘 의미하고 싶은지를 알 수 있도록 하는 게 보기 좋다고 생각했고, 이 방법을 언젠가 차용해서 프로젝트에 써 먹고 싶다고 생각했는데 때마침 이번에 기회가 됐으니 각 페이지 별, 그리고 common폴더에 policies라는 폴더를 만들어 따로 관리하도록 했다.

  • 코드에 대해서
    1. 합성 컴포넌트에 대해서

    이전 회사에서 같이 일했던 이트루(@lxxtrue16) 님께서 어드민 페이지를 작업했을 당시, 그 밖에도 특정 기능을 만드셨을 당시에 Object.assign 메소드를 차용한 합성 컴포넌트 방식으로 코드를 짜신 것을 본 적이 있었다.

    (Object.assign은 두 개의 객체를 합쳐 하나의 새로운 객체로 반환해주는 메소드이다.)

    당시에는 그 방식이 솔직히 귀에 들어오고, 눈에 보이던 상황이 아니었고(일에 쫓겨서 생각이 들어올 뇌의 용량이 없었다... 죄송함다…!!🤦), 나중에 작업하셨던 코드를 보고 그 때 이야기를 해주신 것이 생각나서 뒤늦게 관련 내용을 찾던 중에 아래의 글을 발견하고 읽어봤다.

    합성 컴포넌트로 재사용성 극대화하기 | 카카오엔터테인먼트 FE 기술블로그

    합성 컴포넌트의 장점은 하나의 메인 컴포넌트에 귀속되는 서브 컴포넌트들을 포함시켜, 필요한 사항에 맞춰 서브 컴포넌트들을 이용해 다양한 방식으로 커스텀 할 수 있다.

    이렇게 하면 하나의 기능에 대해서 다양한 방식으로 만드는 것이 가능하므로 재사용 하기에도 좋고, 컴포넌트 자체에도 유연성이 보장된다.

    다만, 현재 프로젝트에서는 재사용되는 컴포넌트가 위의 Description과 같은 하나의 Common 컴포넌트로 관리해서 해당 컴포넌트 자체를 통짜로 가져와 쓰고 있다보니 위에서 설명한 합성 컴포넌트의 의의가 현재 프로젝트 내에서는 굉장히 얕다는 문제점이 있다...

    그럼에도 불구하고 이 방식을 채택한 이유는 필요에 따라 예외 케이스가 발생했을 때 이용해볼 수 있다고 생각했으며, 그게 아니더라도 UI 컴포넌트 요소 자체를 그룹핑하기에도 좋은 방법이라고 판단했다.

    그런 의미에서 현재 각 페이지 및 요소에 따른 컴포넌트들은 합성 컴포넌트 방식을 차용해서 코드를 짜고 있다.

    1. Custom Hook 배치

    솔직히 말하자면 회사를 다니기 전까지 Custom Hook이라는 걸 스스로 만들어 본 적이 없었다.

    웨잇세컨드에서 했던 것은 타인이 만든 코드를 참고해서 한 것 뿐이라 어디까지나 맛보기라는 느낌이었고, 실제 업무에서 Custom Hook을 접했을 당시에는 이를 어떻게 만들어야 할 지 전혀 감이 오지 않았다.

    때문에 회사를 다니면서 다른 사람들이 코드를 짜는 방식을 보고, 직접 이것저것 시도해보고 나서야 Custom Hook에 익숙해질 수가 있었다.

    이번에 컴포넌트를 만들 때 결심한 것은 하나의 컴포넌트 위에서 return 위의 코드는 무조건 Custom Hook으로만 배치하여 컴포넌트만 보게 만들자는 생각이었다.

    이렇게 함으로서 컴포넌트 안에서는 컴포넌트만 볼 수 있고, 훅에서는 기능과 관련한 코드만 볼 수 있으니 깔끔하게 구역 정리가 가능하다.

    1. 디자인 시스템? 규격화?

    디자인 시스템? 이라고 이야기하기도 부끄럽지만, UI 등을 이번에 작업할 때 규격화를 해두면 나중에 특정 값을 모두 다 변경할 사항이 있을 때 이를 통해 다 같이 바꿀 수 있으므로 관리하기에 편할 거라는 생각이 들었다.

    이전 회사에서 퇴사하셨던 분 중에 디자이너 분과 함께 디자인 시스템을 연구하셨던 분이 계셨는데, 이분이 정리하셨던 유틸 방식이 개인적으로 엄청 좋았고 배울 점이 많았다.

    그래서인지 스스로 만들 프로젝트에서도 그분의 방식을 차용해보고 싶었고, 때마침 그 방식을 이번 프로젝트에서도 사용해보기로 했다.

    위처럼 객체에 하나의 케이스를 묶어 놓은 뒤, 스타일에서 이 객체를 불러와 특정 key을 적용함으로서 객체 속에 담겨있는 스타일 요소를 한꺼번에 불러올 수 있다.

    지금은 위처럼 폰트만 관리하고 있는데, 추후에 색상 등도 이쪽으로 해서 통일성을 가질 수 있도록 반영해 놓으려고 한다.

🎙️ 다음 이야기는…

초기 세팅은 언제나 많은 생각을 하게 만드는 것 같다.

투머치토커의 이야기는 끝이 없다..^^

만들면서 이 내용, 저 내용을 기록해두다보니 하고 싶은 말은 너무 많은데, 읽는 사람이 지루해지지 않을 정도의 글을 쓰려고 하니 분량이 참 쉽지가 않아서, 이번 글은 여기까지 쓰기로.

다음 이야기는 1주차에 하면서 몰랐던 것들, 헤멘 것들에 대한 간단한 것들을 정리해보려고 한다.

Vite의 환경 변수 설정이라던가, TypeScript의 try-catch문 내 catch 부분의 error 인자 타입에 관한 내용이라던가, 닉네임 란을 포기한 이야기 등 프로젝트를 구현하면서 고민했던 것들을 좀 더 정리하는 시간을 가져보고자 한다.

뒤늦게지만 이렇게 시동을 건 만큼, 이번 프로젝트도 좋은 결과를 만들어 낼 수 있기를.

https://github.com/DrunkenNeoguri/project-elements

Adius!