
React 18 + JavaScript로 만든 프로젝트를 Next.js 15 + TypeScript로 옮기는 작업을 시작했다.
이런 결정을 내리게 된 데에는 몇 가지 이유가 있는데,
우선 첫번째로 React는 Vite와 함께 이미 두세 번 정도의 프로젝트를 통해 꽤 익숙해진 상태였다. 하지만 Next.js는 공부는 해놓았으나 정작 실전, 특히 큰 규모의 프로젝트에서 제대로 활용해본 경험이 부족했다. 아무래도 아는 것과 실제로 적용해보는 것은 차이가 크니까..
두번째. SEO 때문이었다. react-helmet 라이브러리를 사용해도 SEO 에 한계가 있기에 Next.js가 필요하겠다. 결정.
세번째. 언제까지 React 만 할 줄 알거야?. 그래서 결정!
물론 두 프레임워크 모두 사용해본 경험은 있지만, 이렇게 기존 프로젝트를 마이그레이션하는 것은 처음이라 솔직히 조금 긴장된다. 쉬운 일은 아니니까...
하지만 이 과정을 자세히 기록해두면 나중에 비슷한 상황에서 도움이 될 것 같아서, 앞으로 마이그레이션하면서 겪는 일들을 상세히 남겨볼 예정이다.
일단 전체 마이그레이션을 한 번에 진행하기보다는 단계적으로 접근하기로 했다.
처음에는 Next.js 프로젝트를 새로 만들고, 기존 React 코드를 조금씩 옮겨가는 방식을 택했다.
무작정 코드를 옮기는 것보다 구조를 제대로 설계하는 게 중요하다고 생각했기 때문이다.
그래서 이번 #1에서는 구조를 만들고 왜 이런 구조를 만들었는지 적어놓으려한다.
먼저 Next.js 15버전과 TypeScript를 사용하는 새 프로젝트를 생성했다.
그리고 설정은 아래처럼 했다.
✅ TypeScript 사용
✅ ESLint 사용
✅ src/ 디렉토리 사용
✅ App Router 사용
그리고 프로젝트를 구성할 큰 라이브러리들은 아래와 같다.
react-hook-form 이랑 연계해서 사용하기 좋아서이다.recoil 도 사용해봤기에 이번 기회에 한번 바꿔볼까 고민을 안해본건 아니다.Axios 를 아주 잘써왔었는데,Axios 보다 Fetch 가 이미 Next.js의 렌더링 구조와 긴밀하게 통합되어 있는 것 같아서 다음 #2 편을 적을 때 정해서 도입해볼 예정이다!Next.js App Router를 사용하기로 했기 때문에, 폴더 구조를 다음과 같이 계획했다:
src/
├── app/ # Next.js App Router 파일들
│ ├── layout.tsx # 루트 레이아웃
│ ├── page.tsx # 메인 페이지
│ └── (dynamic)/ # 라우트 그룹
│ ├── dashboard/ # 대시보드 페이지
│ ├── profile/ # 프로필 페이지
│ └── ...
│
├── components/ # 모든 컴포넌트
│ ├── atoms/ # 버튼 등 가장 작은 단위의 컴포넌트들
│ │ ├── Button/
│ │ └── ...
│ │
│ ├── forms/ # mui contorl 공용 컴포넌트
│ │ ├── formProvieder.tsx
│ │ └── ...
│ │
│ ├── layout/ # 레이아웃 관련 컴포넌트
│ │ ├── Header/
│ │ ├── Footer/
│ │ ├── Sidebar/
│ │ └── ...
│ │
│ └── features/ # 특정 기능에 관련된 컴포넌트
│ ├── auth/
│ ├── dashboard/
│ └── ...
│
├── lib/ # 유틸리티 함수 및 API
│ ├── constants.ts # 공통 상수 정의 파일
│ ├── api/ # API 관련 함수
│ ├── redux/ # Redux 관련 파일
│ ├── utils/ # 유틸리티 함수
│ └── hooks/ # 커스텀 훅
│ ├── useAuth.ts
│ └── ...
│
├── styles/ # 스타일 관련 파일
│ ├── globalStyles.tsx # 전역 스타일 프로바이더
│ ├── theme.ts # MUI Joy 테마 설정
│ └── ...
│
└── types/ # 타입 정의
├── api.types.ts
├── user.types.ts
└── ...
react 를 사용할 때는 도메인별로 폴더를 나눠서 작업하고,
가끔 도메인이 애매한 공용 컴포넌트들은 share 폴더에 넣어놓고 썼었는데,
그 안에서도 나누지 않아서 가끔 스크롤로 엄청 뒤졌더랜다.... 그래서 깨알 Atomic design 사용...
🤔 Atom 이란?
Atom은 더 이상 분해할 수 없는 가장 작은 컴포넌트입니다. 마치 화학에서 원자가 물질의 기본 단위인 것처럼, 디자인 시스템에서 Atom은 UI의 기본 단위라고 생각하면 된다.
버튼, 입력창, 레이블, 체크박스 등 기본 HTML 요소부터,
색상, 글꼴, 애니메이션, 레이아웃 등 추상적 요소도 해당될 수 있다!
특징으로는 더 이상 분해할 수 없고
단순하고
재사용성이 높고
다른 컴포넌트에 의존하지 않도록 독립적이여야한다.
atom/ 폴더 외에 forms/ 폴더가 따로 있는 이유는
forms/ 폴더 안에 들어가는 input 등의 경우 순수한 atom 단위가 아니기 때문이다.
mui 와 react-hook-form 을 사용해서 만든 input 이므로
react-hook-form 의 컨트롤러를 사용하여 폼 상태 관리와 결합되어 있기 때문이다.
그래서 엄밀히 말하자면 Atom 보다는 Molecule에 가깝기에,
따로 폴더를 만들었다.
우선 이렇게 초기 작업을 마쳤다. 다음 편에는 axios 와 fetch 중에 어떤걸 사용할지, 사용한다면 왜 사용해야할까 등을 고민해서 적어봐야겠다.. ~!
🚩 참고 문서