새로운 회사로 이직하면서 기존과 다른 개발 경험을 많이 접하게 되었습니다.
프론트엔드 개발자가 없었기 때문에 초기 세팅부터 팀 문화까지 전부 결정해야 했기 때문입니다.
이전 회사의 경우에는 인프라부터 신규 프로젝트를 구성할 때에도 크게 관여할 수 있는 부분이 적었습니다. 아무래도 경력이 많은 개발자가 많기도 하였고 리드직이 아니였기 때문에 제안까지는 가능하지만 신규 세팅이나 CI/CD 부분에서 기존세팅을 활용하는 경우가 많았기 때문입니다.
하지만 지금의 경우에는 혼자 결정하고 진행하여야 했기 때문에 프로젝트 세팅부터 고민할 거리가 많았습니다. 앞으로 어떤 프로젝트들이 추가될지 고려하여야 했고 현재 개발하는 서비스에 맞게 프로젝트를 세팅하고 현재 개발팀의 환경까지 생각하여야 했기 때문입니다. 추가적으로 기획팀이나 마케팅팀의 고려사항도 반영하는 건 당연했습니다.
이런 여런 상황들을 반영하여 문서로 정리하고 신규 서비스를 개발하면서 정리한 내용들을 간략하게 소개해보려고 합니다.
많은 내용이 있을지 모르겠지만 작게 나마 도움이 되었으면 좋겠습니다.
가장 먼저 개발해야 했던 프로젝트는 '크로스샵' 이라는 외국인을 위한 이커머스 쇼핑몰 이였습니다. 크로스 플랫폼을 회사에서 원했었기 때문에 기존 크로스 앱에서 크로스샵으로 연결되는 웹뷰 페이지, 웹에서 접근 가능한 모바일 페이지를 개발하는 것이 목표였고 다른 이커머스와 다른점은 다국어를 적용해야 한다는 점 이였습니다.
신규 세팅이였기 때문에 SEO와 추후에 프론트 엔드 개발자의 채용을 위해서 개발언어는 Next14의 app router를 사용하기로 생각했습니다. SEO 측면에서도 쉽고 빠르게 개발할 수 있었고 정적 페이지의 경우 RSC를 활용하여 빠르게 렌더링할 수 있는게 장점이라 생각했기 때문입니다.
또한 빠르게 변하는 프론트 엔드 생태계에서 신규 기술을 안정적으로 도입하는 것이 큰 장점으로 다가올 것이라 생각했습니다.
다른 패키지의 경우 간력하게 아래에 선정 이유를 작성해두었습니다.
물론 추후 vite로 세팅하거나 프로젝트를 추가 하였을 때에도 추가 세팅만 마무리되면 바로 적용할 수 있도록 레포지토리 세팅을 구성 해두었습니다.
개발언어
React 18, Typescript프레임워크
Next.js v14 (app router)서버상태관리
TanStack Query v5상태관리
Zustand유틸리티 css
css module , TailwindCSSCI/CD
Gitlab, Jenkins, nginx, pm2다국어 지원 관련
next-intl, 회사 다국어 api서비스 모니터링 및 로깅
: Sentry, Grafana개발언어
React 18, Typescript프레임워크
Next.js v14서버상태관리
TanStack Query v5상태관리
Zustand유틸리티 css
css module , TailwindCSSCI/CD
Gitlab, Jenkins, nginx, pm2다국어 지원 관련
- next-intl, 회사 다국어 api모노 레포지토리의 경우 현재는 turborepo가 적용되어 있지만 초기 구성 당시에는 pnpm-workspace 세팅을 통해서만 모노 레포지토리로 구성을 해두었습니다.
프로젝트가 1개인데 구성을 할 필요가 있었나? 싶을 수도 있지만 다른 프로젝트를 추가로 진행할 일이 무조건 생길거라는 확신이 있었고 실제로 현재에는 플랫폼이 확장됨에 따라 현재의 구성을 잘 활용하고 있습니다.
1개의 서비스만 운영을 할 때에는 개발 당시에 공통으로 사용할 수 있는 컴포넌트를 고려하여 상위의 packages 폴더안에 기능별로 폴더를 나누어 미리 root단에서 패키지로 구별을 해두었습니다.
컴포넌트의 경우 공통으로 구별할 button이나 loading, layout관련 등 미리 분리가 가능했고 eslint, tailwind 같이 공통 세팅을 가져가는 부분도 쉽게 분리가 가능했습니다.!
rsc에서 리액트 쿼리를 충분히 활용할 수 있다고 생각했습니다. 물론 fetch를 활용하면 되지 않나? 싶을 수 있지만 서버 컴포넌트에서도 prefetchQuery 를 통하여 쿼리를 사용할 수도 있고 미리 불러온 쿼리를 재사용하여 api 호출을 최대한 줄이고 유저들로 하여금 렌더링 속도를 최적화 시킬 수 있다고 판단 했습니다.
물론 무조건적으로 쿼리를 활용하는 것이 아닌 캐시를 좀더 손쉽게 사용하거나 mutation의 활용이 필요한 부분에서만 사용할 수 있도록 반영 해두었습니다.
프로젝트 폴더 구조의 경우 next의 app router 폴더구조를 기본으로 가져가고 root단의 구조의 경우 모노 레포지토리의 구조를 가져가 추후 다른 개발자가 확인 하였을 때에도 큰 문제없이 구조만으로 이해가 되도록 구조를 만드려고 노력했습니다.
현재는 vite 프로젝트의 경우 next와 폴더 구조가 다르기 때문에 이러한 문제를 해결하기 위해서 vite-plugin-next-react-router
패키지를 통하여 next와 동일한 구조로 개발을 진행하였습니다.
apps // 각각의 모노레포를 담는 폴더
└── monorepo // 하나의 레포지토리
├── app // app 라우터
│ ├── api // Route Handlers 처리
│ └── shop // 하나의 페이지 - '/shop' url로 설정
├── components // 공통으로 사용될 컴포넌트 폴더
│ ├── common // 사이트 공통 컴포넌트
│ ├── feature // 특정 페이지에서 사용하는 공통 컴포넌트
│ ├── service // 외부 라이브러리에 의존하는 공통 컴포넌트
│ ├── ui // 레이아웃 영역의 공통 컴포넌트
│ └── (item) // () 라우팅 그룹 - 같은 목적의 파일 그룹 처리
│ └── _layout // private 폴더로 라우팅 처리되지 않음
├── constants // 공통으로 사용하는 상수 정보 관리
├── hooks // 공통으로 사용되는 리액트 훅 정리
│ └── queries // 공통으로 리액트 쿼리에서 사용할 쿼리 분리 (key, query)
├── public // 리소스 파일 폴더 (image, locales)
├── styles // 공통으로 사용되는 스타일
├── type // 공통으로 사용되는 타입
├── server // server에서 사용하는 함수 정의 (다국어, user-agent 등)
├── store // 해당 레포지토리 store
└── utils // 공통으로 사용되는 uitl
packages // 각각의 모노레포에서 사용할 패키지
├── components // 각각의 모노레포에서 사용할 컴포넌트
│ └── src
│ ├── etc
│ ├── flex
│ ├── grid
│ └── loading
├── config // 각각의 모노레포에서 사용할 config
│ ├── tailwind-config
│ └── ts-config
├── constants // 각각의 모노레포에서 사용할 constants
│ ├── colors // tailwind 커스텀 색상
│ └── iso // 다국어 설정
├── ui // 각각의 모노레포에서 사용할 ui관련 컴포넌트
│ ├── colors // scss 커스텀 색상
│ ├── font // web 공통 font
│ └── layout // mobile, pc, reset 스타일
└── utils // 각각의 모노레포에서 사용할 utils
src
└── flex
├── index.js
├── flex.jsx
├── flex.test.js
└── flex.module.scss
export { default } from './flex';
import flex from '../flex/index.js';
// 하지만 자바스크립트에서는 /index.js가 기본값이기 때문에 아래처럼 작성 가능
import flex from '../flex';
글을 작성하다 보니 설명할 내용들이 너무 길어져 각 부분별로 상세하게 작성을 못한거 같아 아쉬움이 많이 남지만 최대한 기술적인 내용보다 실제로 프로젝트에 적용을 한 이유나 개발을 하면서 구조를 정할 때의 목적을 작성하려고 노력했습니다.
긴글 읽어 주셔서 감사합니다. :)
https://velog.io/@baby_dev/Next.js-13-폴더-구조-이쁜-잡기술
https://aierse.tistory.com/4 - 리액트 폴더 구조 설계 5단계
https://nextjs.org/docs/getting-started/project-structure - next 라우팅 규칙