본문 바로가기

프로젝트/오심테(오늘의 심리테스트)

[Vercel & NextJS] Vercel로 NextJS 배포하기(feat. 5시간 + 음주코딩)

반응형

오늘은 지금까지 약 한 달 조금 덜 되는 시간 동안 애정 깊게 만들었던 오심테를 Vercel을 사용해서 배포해 보았다. 약 5시간이 걸렸고, 계속 듣지도 보지도 못한 에러(찾아보니 NextJS와 Vercel의 버그인 듯)가 나를 끊임없이 괴롭혀서 진짜 배포는 포기할까 싶었다. 하도 이거 저거 수정해 보고 구글링 한 건 다 적용해 봐서 특정한 어떤 것을 수정했을 때 성공했는지 모르겠지만, "진짜 이것만 해보자"하고 마지막으로 수정했던 것이 해결책이었던 것 같다. 정말 너무 답답해서 저녁 먹고 술 꺼내와서 마시면서 했다. 엄마가 술 냄새난다고 한심하게 쳐다보셨지만(?) 배포 성공했을 때의 그 감동은 잊히지가 않는다. 

 

맨 처음에 문제가 되었던 것은 node의 버전이었다. 내가 사용하던 노드 버전은 20번대였고, 다음과 같은 에러가 계속 떴다.

Command npm install error exited with 1...
node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by node)...
node: /lib64/libm.so.6: version `GLIBC_2.28' not found (required by node)...

구글링을 계속해보니 버셀에서 사용하는 노드 버전은 18번대였고(프로젝트의 settings 탭에서 확인 가능), 확실하진 않지만 내가 사용하는 노드 버전도 18번대로 다운그레이드해 주니 해당 에러는 없어졌던 것 같다.

current: { node: 'v18.16.0', npm: '9.5.1' }

그리고 또 한 가지, package.json에 node 관련 항목을 지워주었다(지피티가 하라고 했다). 참고로 package.json을 수정하면 저장 후 npm i을 해줘야 한다.

 

이제 에러 끝판왕이 나온다. 

info Generating static pages TypeError: Cannot read properties of null (reading 'useContext')

나는 useContext를 쓴 적도 없고, 내 리코일 코드에도 아무 문제가 없는데 계속해서 이 에러가 뜨면서 build가 안되었다. 진짜 이 에러 때문에 몇 시간을 삽질했는지 모른다. 깃허브 이슈면 이슈, 스택 오버플로우면 스택 오버플로우까지 다 찾아봤고 정보가 그리 많지도 않았다.

vercel의 깃허브 이슈를 보니 나와 같은 에러가 뜨는 사람이 많았다. 다들 next의 버전이 문제라며, 이건 버그고 어쩌고 저쩌고.. 13번대 노드 버전은 된다 14번대 노드 버전은 안된다.. 사람들마다 말이 다 달랐다. 확인해 보니, 나도 처음엔 14번대 버전을 쓰고 있었고, 글에 나와있는 된다는 버전대는 다 도전해 봤다. 노드 모듈 파일도 계속 지우고 캐시도 없애주고 npm i도 다시 해주는 등 정말 무한한 시도를 했다.

이게 해답일지는 모르겠으나, 

"next": "^13.3.4",

위의 버전으로 바꿔주니 되긴 되었다. 이해가 안 되네;;

 

그다음으로 한 것은 react와 react-dom의 dependencies를 peerDependencies로 옮기는 것이었다. 이건 효과가 있었는지 잘 모르겠다. 이것만 했을 때는 효과가 전혀 없었던 것 같다. 구글링에서 한번 해보라길래 해보았다...

"devDependencies": {
    "autoprefixer": "^10.4.14",
    "eslint": "^8.40.0",
    "eslint-config-next": "^13.4.2",
    "postcss": "^8.4.23",
    "tailwindcss": "^3.3.2"
  },
  "peerDependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },

 

다음으로 시도한 것은 next.config.js에 다음과 같은 코드를 추가하는 것이었다. 이것은 vercel의 깃허브 이슈에서 보았다.

 experimental: {
    appDir: false,
  },

https://github.com/vercel/next.js/discussions?discussions_q=is%3Aopen+can+not+use+property+useContext 

 

vercel/next.js · Discussions

Explore the GitHub Discussions forum for vercel next.js. Discuss code, ask questions & collaborate with the developer community.

github.com

 

누가 버전 앞에 ^도 다 붙여줬더니 됐다고 하길래 나도 해봤다. 

 

여기까지 해도 안 돼서 에러 메시지에서 참고하라는 페이지를 읽었다.

https://nextjs.org/docs/messages/prerender-error

 

prerender-error | Next.js

Prerender Error While prerendering a page an error occurred. This can occur for many reasons from adding non-pages e.g. components to your pages folder or expecting props to be populated which are not. Make sure to move any non-pages out of the pages folde

nextjs.org

딱히 수정할 만한 것은 없어 보였다... 다 제대로 한 것 같은데...

 

마지막으로 지피티에게 물어보았다. 

제공해 주신 코드를 기반으로 한 번 확인해 보았을 때, 주요한 오류나 수정이 필요한 부분은 보이지 않습니다. 하지만, 오류 메시지에 따라 몇 가지 주의할 점이 있을 수 있습니다. 

1. `fallback: true` 설정 확인: `getStaticPaths` 함수에서 `fallback` 옵션이 `true`로 설정되어 있습니다. 이는 동적 경로에 대한 정적 페이지가 미리 생성되지 않았을 경우, 요청이 들어올 때 페이지를 생성하도록 하는 옵션입니다. 만약 모든 동적 경로에 대해 미리 정적 페이지를 생성하고 싶다면 `fallback` 값을 `false`로 설정하시면 됩니다. 다만, 이 경우에는 모든 동적 경로에 대한 정적 페이지를 미리 생성해야 하므로, 성능 및 빌드 시간에 영향을 줄 수 있습니다.

2. `fallback: blocking` 옵션: `fallback` 옵션을 `true`로 설정한 경우, 추가적으로 `fallback: blocking` 옵션을 사용하면 초기 요청 시 서버 사이드 렌더링을 통해 페이지를 생성하고 반환할 수 있습니다. 이를 통해 초기 로딩 시에도 페이지의 완전한 콘텐츠를 제공할 수 있습니다. `fallback: blocking` 옵션을 사용하려면 `next.config.js` 파일에서 `experimental: { fallback: true }` 설정을 추가해야 합니다.

3. `getStaticPaths` 함수 수정: `getStaticPaths` 함수에서 현재는 `fallback: true`로 설정되어 있어 모든 동적 경로에 대해 정적 페이지를 생성하도록 되어 있습니다. 만약 특정 문서에 대해서만 정적 페이지를 생성하려면, `fallback: true`를 `fallback: 'blocking'`으로 변경하고, `paths` 배열에 해당하는 동적 경로만 추가해야 합니다.

이 외에는 제공해 주신 코드에서는 큰 문제나 수정이 필요한 부분은 보이지 않습니다. 하지만, 전체적인 프로젝트 구조나 설정 등을 파악하지 못하였기 때문에, 다른 부분에서의 오류 가능성은 배제할 수 없습니다. 필요에 따라 오류 메시지와 함께 더 자세한 정보를 공유해 주시면 더욱 구체적인 도움을 드릴 수 있습니다.

아.. 동적 경로에 대해 미리 정적 페이지를 생성하고 싶다면 fallback 값을 false로 해야 했었다. 나 무슨 정신으로 true로 해놓은 거지? 진짜 사람 아니다.. 미리 정적 페이지 만들어놓고 빠르게 가져오려고 NextJS 쓰는 거 아니었냐고 ㅠㅠ광광

거의 희망도 다 사라진 상태였지만 마지막 도전이라고 생각하고 fallback을 true에서 false로 수정해 주었다. 

export async function getStaticPaths() {
  const listsCollectionRef = collection(db, "testList");
  const data = await getDocs(listsCollectionRef);
  return {
    fallback: false,
    paths: data.docs.map((doc) => ({
      params: { testId: doc.id },
    })),
  };
}

 

그런 다음, 스택 오버플로우 글에서 next build 보다는 npm run build가 더 정리된? 깔끔한 에러 메시지를 제공한다고 하길래 지금까지 썼던 next build를 버리고 npm run build를 해보았더니, 

꿈에 그리던 그 광경을 볼 수 있었다. 사실 이것도 좀 나중에 확인했다. 거의 포기한 상태에서 스택 오버플로우를 둘러보던 중, 빌드가 완료된 것을 나중에 알았다. 진짜 소리 지를 뻔^^ 혼자서 외로운 싸움을 했다. 그래도 하루 안에 끝난 게 어디냐.

vercel에서는 한 번 프로젝트를 연결해 놓으면 수정 사항을 반영해 자동으로 빌드해 주므로, 위의 수정 사항을 git push 해주니 아주 아름답게 배포가 된 것을 확인할 수 있었다. 

진짜 배포 포기하고 gif만 따서 리드미에 올려놓아야 하나 어째야 하나 별의별 생각을 다했다. 원래 배포할 때 의도치 않은 에러가 상당히 많이 나타난다고들 하는데, 이렇게 듣지도 보지도 못한 + 구글링해도 잘 안 나오는 에러가 나를 괴롭힐 줄 몰랐다. 이번주 토요일에 sqld 시험인지라 시험공부도 해야 하는데 배포 빨리 될 줄 알고 쉬는 시간에 배포 시작한 내 잘못이지 암암... (sqld 시험도 만만한 시험은 아니다. 나는 전공이지만 한 달가량의 기간 동안 매일 공부했다. 지금 아니면 백엔드 쪽 지식 공부할 시간이 없을 것 같아서.)

누가 vercel 간단하다고 했냐^^ 배포는 다 어려운 것 같다. 예전에 코스 들을 때 AWS 배포할 때도 하루 종일 커피 마시고 초콜릿 먹고 난리도 아니었다. 깃허브 액션 등록할 때도 하루 걸렸었던 것 같다. 데브옵스 개발자분들 진짜 존경한다. 나중에 나도 데브옵스 쪽을 잘할 수 있으려나... 제일 어려운 게 데브옵스 같다(현재로서는);;

멘털 터지지 않게 멘탈 관리하면서 5시간 내내 에러 붙들고 해결해 보려고 노력한 결과는 달다. 정말 달다. 그래도 혼자만의 싸움은 퍽 외로웠다. 팀원과 함께 했다면 힘들지만 조금 더(?) 재밌었을 것 같다. 역시 개발은 팀플이지?

이제 토이프로젝트도 마무리했으니 시험 멋지게 합격하고 스터디원 분이랑 이쁜 프로젝트 하나 딱 만들고 싶다. 기대된다.

반응형