포켓몬빵 토이 프로젝트 CRA -> Next.js로 마이그레이션 후기

길고 꾸준하게·2023년 2월 10일
0
post-thumbnail

https://github.com/rlatlswo135/pokemon_master/blob/main/README.md

서비스링크 : https://pokemon-master-gk8p.vercel.app/

전직장에서 근무하고있을때 문득 아이디어가 떠올라 노트에만 적어놓고 만들진 않았었는데.. Nextjs학습겸 만든 토이 프로젝트다

시작은 CRA

프로젝트 구상중 User와 인터랙션하는 부분이 많이없고 라우팅시 불러와야 할 이미지가 꽤 있어 Prefetch도 필요해 Nextjs를 쓰기로 결정했고,
정확히 Nextjs를 써보지는 않았기에 시작은 CRA로 한 후 마이그레이션을 하면서 학습도 겸 할 생각으로 CRA로 시작했다.

마이그레이션 진행은 공식문서 https://nextjs.org/docs/migrating/from-create-react-app 를 참조했으며
진행중 발생한 오류등을 따로 메모해 놓으면서 블로깅을 하면서 정리를 해보려고 한다

1. react-router-dom제거 및 Script,env수정

Next.js는 파일시스템 기반 라우터를 기본 제공하기 때문에, 3rd-party 라우터인 react-router-dom을 제거했다

"dev": "next dev",
"build": "next build",
"start": "next start"

env수정 : REACT_APP -> NEXT_PUBLIC

Client-Side에 노출되는 환경변수의 접두사의 차이가 있다 -> 서버측 환경변수는 빌드타임 or API Routes에만 쓸 수 있다.

2. Custom App / Document 생성

Next.js는 기본적으로 SSG/SSR이기 때문에 서버측에서 렌더링한 html뼈대를 Client에 전송한다.

그렇기때문에 서버측에서 만들어진 뼈대는 Browser이벤트도 사용할 수 없다. -> 일단 뼈대인 _document와 _app을 만들어줬다.

_document

  • 페이지를 렌더링하는데 사용되는 태그를 업데이트해준다.
  • 여기 title태그와 meta viewport태그 등은 이곳에 있으면 안된다며 에러가 발생했다.
    -> Custom document는 서버측에서 렌더링되며 pre-render시 1번만 렌더링되기 때문에 얘기치 않은 문제가 생길 수 있어 _app에 넣어야 한다고 한다.

_app

  • 이곳에서 렌더링 되는 값은 모든 페이지에 영향을 주기때문에 공통 레이아웃, global css등이 들어간다
  • Component와 pageProps를 인자로 받으며 각각은 요청한 페이지 / getInitialProps를 통해 받은 props다

3. EsLint

작업을 하다보니 Eslint때문에 VSC가 새빨개졌다..
공식문서에 따르면 이미 airbnb plugin등으로 React / React-hooks / jsx-a11y / import plugin중 하나라도 설치되어 있다면,
EsLint설정까지 마이그레이션 해야한다고 한다..

1. Babel

컴파일 에러는 안나지만 typescript코드가 런타임 에러가 나와서 찾아본 결과
.babelrc가 이미 있다면 Nextjs쪽 기본 설정과 달라 예상치 못한 문제가 생긴다고 한다..

  • 현재 Nextjs의 컴파일은 Rust기반 SWC를 쓰는데 이게 babel설정 파일이 따로있으면 기존의 컴파일 방식을 따라서 오류를 뱉는다고 한다.
  • 하지만 CRA여서 eject를 하지 않는이상 babel설정을 만질수는 없었고, 굳이 eject를 하면서 해결한 문제가 아닌 것 같아서 lint설정을 봤다.

2.EsLint

검색결과 기존 EsLint설정 extends에 "eslint:recommended","next"를 넣어줬고, 해결됬다

"extends": ["eslint:recommended", "next", "plugin:prettier/recommended"],

4. public 디렉토리

기존 CRA는 public 디렉토리 안에 정적자산 뿐 아니라 html도 있었지만 nextjs는 오직 정적자산에만 사용한다고 한다 -> html의 진입점이 _document _app으로 바뀌었으니까 public에 있을 필요가 없다고도 이해했다.
그리고 image등 src의 기본 진입점이 이 public디렉토리로 잡혀있다.

5. SSG

PokeAPI에서 받아오는 1세대 포켓몬 정보는 사실 한번 받으면 수정될 일이 없어서 SSG로 받아온 후 해당 Recoil Atom은 지워버렸다.. 나머지는 전부 Client가 Firebase요청을 보내는 코드여서 해당부분밖에 적용할 필요가 없었다.

6. Tailwind CSS

프로젝트 구조가 바뀌었다보니 tailwind.config의 content도 맞춰서 바꿔줄 필요가 있었다.
하지만 올바르게 해도 적용되질 않아서 패키지 제거후 npm캐시를 지우고 재설치 했더니 잘먹었다.
맞는 방법인지는 모르겠다.. npm캐시가 뭔지 추가적인 검색이 필요하다

npm cache clean --force

7. Image 컴포넌트

사실 Next.js를 쓴 가장 큰 이유이기도 하다

프로젝트 특성상 image를 쓸 일이 많기도했고, pre-fetch를 통해 UX를 높이고 싶었기에 Image컴포넌트를 적극 사용했다.

5-1 외부 URL source

nextjs서버가 이미지가 담겨있는 remote서버에 직접 요청을 해서 이미지를 가져오기때문에 허용되는 접근 URL을 명시해줘야 외부 이미지 URL소스를 가져올 수 있다. -> next/image Un-configured Host에러 관련

{
	images:{
    	domains:[가져오려는 remote]	
    }
}

추가로 외부 이미지에 경우 로컬 이미지와는 다르게 빌드타임에 이미지에 접근하는 것이 불가능하기 때문에,
width, height정보를 기입해야 했고, placeholder blur이미지도 생성되지 않으므로 로드되기전 blurDataURL에 base64로 인코딩된 이미지 데이터를 작성해야 한다.

fill 레이아웃을 쓰고 외부 경로이미지를 땡겨오는 경우, 브라우저에서 해당 외부이미지의 크기를 100vw/vh를 Default로 예상해서 가져오기때문에 성능상 손해가 날 수 있다.

그래서 fill레이아웃을 사용시 sizes를 명시해 성능손해를 안볼 수 있다. -> 반응형으로 가져오는것도 가능하다

8. PrivateRoute 수정

마이그레이션 과정중 next.js의 useRouter훅을 써서 유저정보가 없을시 home으로 리다이렉트하는 같은 코드가 동작이 안되었다. 오류를 살펴보니 router훅이 브라우저단에서 실행이 안되서 나는 오류였다,
해당 리다이렉트 코드를 useEffect로 옮겨 브라우저단에서 실행되게 바꾸었다.

useEffect(() => {
	if(!uid){
    	router.push("/"
    }
},[])

9. 절대경로 Path alias 오류

왜 CRA에 멀쩡히 적용되던게 안되지.. 했는데 프로젝트 구조는 바꿧으면서 tsconfig에 트랜스파일링할 include 디렉토리는 그대로 두어서 뜬 오류였다.. ㅋㅎ

10. 최종 Vercel 배포 -> 오류

환경변수 오류가떠서 왜지? 하고 곰곰히 생각을했는데.. vercel측 환경변수는 REACT_APP으로 되어있고
마이그레이션을 하면서 NEXT_PUBLIC으로 바뀌어서 그걸 적용안해서 생긴 오류라는걸 깨달았다....

끝..

맨처음 프로젝트 구조를 바꾸면서 정신없이 뜨는오류 + 왠지모르게 안되는 tailwind CSS 및 typescript설정 등등에 애를좀 먹었는데 마이그레이션하면서 특히 이미지를 로드하는 부분에서 눈에띄게 성능향상이 이루어져서 기분이 좋았다. 하지만 좀 많이 부족한느낌이 들어서 더욱더 Next.js를 공부해야 싶겠구나 싶었다.

https://fe-developers.kakaoent.com/2022/220714-next-image/
https://nextjs.org/docs/migrating/from-create-react-app

profile
작은 나의 개발 일기장

0개의 댓글