[Front-end] 개발자 공부

배포 시, NextUI 적용이 안 되는 에러 → .npmrc 파일 추가 및 pnpm을 다시 설치해 해결

MOLLY_ 2024. 11. 9. 06:52
728x90

< 목차 >
(1) 문제 인식
(2) 해결을 위한 고민과 시도들
(3) 해결
(4) 문제의 원인이었던 pnpm과 패키지 매니저에 대하여
 
 

배포 시, NextUI 적용이 안 되는 에러 → .npmrc 파일 추가 및 pnpm을 다시 설치해 해결

yarn을 사용했었던 직전 프로젝트에서는 NextUI가 잘 적용됐었는데, pnpm을 사용하는 이번 프로젝트에서는 적용이 수월하지 않아 2일 간 우울하기도 했고 고생했다. 하지만 깊게 몰입하여 문제를 해결한 경험이 하나 더 생겼다.
 
UI 관련 문제로 꽤나 시간을 보내게 되다 보니 아예 ‘다른 디자인 시스템으로 변경’하거나 ‘내가 직접 CSS를 할지’에 대해 깊게 고민하며 갈등하였다.
하지만 문제를 포기하는 것은 내키지 않아서 더욱 다양한 관점에서 바라보고, 시도를 해보았다.
 
다른 분들은 나와 같은 이슈로 헤매거나 시간 보내지 않고 바로 문제를 해결할 수 있길 바라는 마음에서 트러블 슈팅 과정을 자세히 적어봤다. 아직 나와 같은 이슈를 작성한 글을 발견하지 못해서 가능한 한 자세히 적었다.
 
 

(1) 문제 인식

이번 프로젝트의 여러 도전 중 하나는 1~2개의 기능을 구현 완료한 후, 즉시 배포하는 것이었다.
익명 채팅 기능 구현을 마치고, 즉시 배포를 진행하던 중 문제를 인식하게 되었다.

 

 
바로 위 사진처럼 배포 전/후로 UI 반영의 차이가 발생한 것이 문제다.
 
왼쪽은 배포 전으로, 로컬에서 NextUI가 반영된 화면이고,
오른쪽은 배포 이후로, NextUI가 반영되지 않고 Tailwind CSS만이 반영된 화면이다.
 
 
왜 배포 전후로 차이가 나는 것인지 도무지 알 길이 없었다.
 
빌드 타임에도 에러 안 뜨고,
Console과 네트워크 탭에서도 에러가 안 뜨고,
ESLint도,
심지어 Git에서도 로컬 개발 모드든, 빌드든, 배포 모드든 아무런 에러가 뜨지 않았다.
 
정말 무서운 것은 에러가 뜨지 않는 것임을 다시 한번 느끼게 된 때였다.
어떠한 에러가 뜨는 것도 아니기 때문에 문제의 원인과 이유를 파악하는 난이도가 많이 올라간다.
 
 
배포에서 문제가 생기는 것이라면 빌드 타임에서의 문제겠구나!’라고 처음엔 확신했다.
그래서 관련된 스택 오버 플로우, 블로그, 공식 문서 등 최대한 많이 조사해서 반영해봤다.
 
페이지(기능)에 따른 브랜치를 따로 팠기 때문에 정말 싫긴 하지만 시도를 하는 내내 PR을 계속 올렸어야 했다. 확실치 않은 해결책임에도 PR로 계속 남겨야 하기 때문에 싫었다. 하지만 그렇게 하지 않으면 시도를 해볼 수가 없으니 어쩔 수 없이 PR 및 Merge를 진행했다.
 
 

(2) 해결을 위한 고민과 시도들

사진처럼 여러 시도를 해봤다

 
CSS 커스텀을 좋아하는 나는, NextUI를 사용하는 코드에 많은 Tailwind CSS 코드를 작성했다. 혹시 커스텀에 사용한 코드 때문에 충돌한 걸까 싶어서 NextUI의 스타일 우선순위의 보장을 위해 !important를 작성해 보기도 했으나 정답이 아니었다.
 
유명한 방법인 ‘모든 캐시 삭제’도 역시 해봤다.
브라우저 캐시, 로컬에서의 .cache 폴더 삭제, pnpm store prune 명령어를 이용한 pnpm 캐시 삭제 등 모든 캐시를 다 삭제해 봤지만 이것도 정답이 아니었다.
 
하위 컴포넌트에서 ‘use client’가 사용되지 않은 게 하나 있었는데, 그 컴포넌트에도 추가해 보았으나 역시 답은 아니었다.
 

 
이렇듯 여러 시도를 반복하다가 갑자기 로컬에서도 배포 버전처럼 NextUI가 적용되지 않은 채로 뜨기 시작했다.
 
??????
배포 문제인 줄로만 알고 있었는데, 아니었다고? 문제가 더 오리무중이었다.
 
어디서부터 문제인 건지, 그 시점을 알아내기 위해 PR에 올렸던 모든 시도들을 다시 해봤으나 NextUI가 적용되었던 그때로 다시 돌아가지지 않았다.
 

잘 생각해 보니, pnpm으로 패키지를 전부 삭제하고 재설치 할 때가 영 마음에 걸렸다.
 
pnpm 사용 중 문제가 발생했을 때 가장 효과적인 방법 중 하나는 프로젝트 의존성을 초기화하고 모든 패키지를 처음부터 다시 설치하는 것이라고 해서 시도해봤다.

 
이전에 사용한 모든 캐시나 의존성을 제거해보고 pnpm의 특성에 맞게 패키지를 설치하는 것이 도움이 될 수 있다 하여, 나도 해당 명령어를 통해 삭제 후 재설치를 진행했다.
 
 
1. node_modules 폴더와 pnpm-lock.yaml 파일 삭제

rm -rf node_modules pnpm-lock.yaml

 
2. 모든 패키지 재설치

pnpm install

 
아마도 pnpm 관련 문제일 것 같았다.
그래서 처음으로 되돌아가서, 설치부터 다시 들여다보기 시작했다.
 
 

(3) 해결

https://nextui.org/docs/guide/installation#global-installation

 
NextUI 공식 문서에서 설치, 의존성, pnpm 관련 내용만 다시 읽었고, 거기서 답을 찾아냈다.
 
pnpm을 사용하는 경우, .npmrc 파일에 다음 줄을 추가하여 패키지를 루트 node_modules에 올려야 한다.
 

// .npmrc
public-hoist-pattern[]=*@nextui-org/*

 

 
루트 디렉토리에 만든 .npmrc 파일을 수정한 후에는 종속성이 올바르게 설치되었는지 확인하기 위해 pnpm 설치를 꼭 다시 해야 한다. (다른 패키지 관리자를 사용하여 NextUI를 설치하는 경우에는 이 단계를 건너뛸 수 있다.)
 
 
나도 초반에 이 과정을 분명 거쳤지만 아마 다른 패키지와 파일을 정리할 때 .npmrc 파일도 함께 정리(= 삭제)하였다.
 

하지만 왜 NextUI는 로컬에서 여전히 적용됐을까?

.npmrc 파일을 작성하고 pnpm 재설치 → .npmrc 파일 삭제를 진행했기 때문이다.

 

재설치 할 때, 종속성이 글로벌 저장소에 저장된 듯하다.

그래서 로컬에서는 제대로 적용됐지만, 배포 시엔 .npmrc 파일이 없기 때문에 적용되지 않은 것이다.

 
사실 이것은 배포 과정에서의 이해도 필요할 것 같단 생각도 들었다.
이렇게 프로젝트를 하면 할수록 프론트엔드 개발 뿐 아니라 서버, 배포, 설계 등 다양한 부분에서 아는 게 많아야 함을 절실히 깨닫게 된다.
 
아무튼 문제의 원인이었던 pnpm에 대해서 좀 더 알아보도록 하자.
 
 

(4) 문제의 원인이었던 pnpm과 패키지 매니저에 대하여

pnpm은 JavaScript 패키지 관리자로, yarn보다 의존성 관리가 엄격해서 특정 패키지의 버전 간 불일치나 심볼릭 링크와 관련된 문제들이 발생할 수 있다는 단점이 있다.
 
하지만 동일한 파일을 저장하지 않아 디스크 공간을 절약하고, 파일을 효율적으로 관리할 수 있고, 설치 속도가 매우 빠르다는 뚜렷한 장점이 있기 때문에 pnpm을 이번 프로젝트에 도입하기로 결심했었다.
 
 
pnpm은 ‘디스크 공간 절약’과 ‘의존성 설치 속도 개선’을 목표로 개발되었다. 설치된 패키지를 글로벌 스토리지에 한 번만 저장하고, 프로젝트의 node_modules에 심볼릭 링크를 통해 연결한다.
 
 

1. ‘심볼릭 링를 활용’한다는 게 특징이다.

여러 프로젝트에서 동일한 패키지를 사용하면 디스크 공간을 절약할 수 있고, 설치 속도가 매우 빠르다. 덕분에 각 프로젝트가 패키지의 고유한 복사본을 가지지 않으면서도 각기 다른 버전을 안전하게 관리할 수 있다.
 

👾 심볼릭 링크

: 파일 시스템에서 다른 파일이나 폴더에 대한 가상의 참조(링크)
바로 가기와 비슷한 개념으로, 실제 파일의 위치를 가리키는 특수한 파일이다. 한 파일의 여러 위치에서 접근이 가능하게 만들 수 있다. 복사본을 만들지 않고도 여러 위치에서 동일한 파일을 가리키게 하는 방법이기 때문에 디스크 공간을 절약하고, 파일을 효율적으로 관리할 수 있는 장점이 있다.
 
 

심볼릭 링크와 에러

pnpm의 심볼릭 링크는 디스크 공간을 아끼고 효율적으로 패키지를 관리하는 데 도움이 되지만, 종종 특정 패키지나 의존성이 설치되지 않았을 때 에러가 발생하지 않는 것처럼 보이기도 한다.
 
그 이유는 심볼릭 링크가 잘못 연결되거나, 실제 참조하려는 패키지가 누락되었더라도, 심볼릭 링크 파일이 존재하므로 겉으로 보기에는 패키지가 설치된 것처럼 보일 수 있기 때문이다.
 
이렇게 되면, 실제 실행할 때(runtime) 문제가 생기면서 "module not found" 또는 "cannot find module" 같은 에러가 발생할 수 있다.
 
 

2. ‘엄격한 종속성 관리’도 특징이다.

pnpm은 패키지를 평평하게 설치하는 대신 트리 구조를 유지하며, 종속성 트리의 불일치에 대해서 매우 엄격하다. 이러한 특성은 종종 종속성이 누락되거나 버전이 맞지 않을 때 에러를 더 쉽게 유발할 수 있다.
 
 
나의 경우, 2가지 모두 원인이었다.
1. 처음에 글로벌로 설치했었기에 pnpm의 심볼릭 링크를 통해서 node_modules 에 연결하고 글로벌 저장소에도 저장됐을 것이다.
2. 이미 글로벌 저장소에 존재하기 때문에 .npmrc 파일을 삭제한 이후에도 로컬에서는 문제 없이 NextUI가 적용되었다.
3. 캐시, node_modules, 종속성 모두 삭제 후 재설치 하는 과정에서 글로벌 저장소에 저장된 것마저 없어졌기 때문에 로컬에서도 NextUI가 적용되지 않았을 것이다.
 
이 원인은 아래의 ‘심볼릭 링크 방식과 누락된 의존성’ 부분에서 좀 더 자세히 이해할 수 있을 것이다.
 
그렇다면 패키지의 누락이나 버전 충돌이 발생했을 때,
왜 pnpm에서는 에러가 잘 발생하지 않거나 문제를 알아차리기 어려운지 알아보자.
 
 

패키지 설치 실패 시, 에러 미발생 원인

1. 부분적으로 설치된 패키지
: pnpm, yarn, npm 모두 설치 중에 어떤 패키지는 성공적으로 설치되고, 어떤 패키지는 실패할 수 있다. 이 경우, 대부분의 경우에는 경고 메시지가 출력되며 전체 설치가 중단되지 않고 진행된다. 패키지가 부분적으로 설치되었기 때문에 런타임 중 문제가 발생할 수 있다.
 
2. 심볼릭 링크 방식과 누락된 의존성
: pnpm은 심볼릭 링크를 활용해 패키지를 node_modules에 연결한다. 만약 설치 중 특정 종속성이 누락되거나 의존성 트리가 불완전하다면, 심볼릭 링크 구조 때문에 에러 메시지가 명확하게 발생하지 않을 수 있다. 특히 일부 종속성 파일이 글로벌 저장소에 존재하지만 특정 링크가 누락된 경우, 해당 패키지가 제대로 작동하지 않을 수 있다.
 
3. 평평한 구조 vs 트리 구조
: yarn과 npm은 종속성을 평평하게 설치하므로, 일부 종속성이 전역에 존재하면 의존성의 상위 패키지에서 이를 참조하여 문제를 우회할 수 있다. 반면 pnpm은 트리 구조를 유지하므로 각 패키지가 자신의 종속성에 대한 고유한 트리를 유지하게 된다. 만약 특정 패키지의 의존성이 제대로 설치되지 않으면, 바로 에러로 나타나기보다는 런타임 시 module not found 같은 문제로 연결될 수 있다.
 
 
 
마지막으로, 다른 두 패키지 매니저도 간단히 알아보도록 하자.
 

npm

npm은 가장 기본적인 패키지 관리 도구로, Node.js와 함께 제공된다.
표준적이고 보편적인 사용을 목표로 하며, 가장 널리 사용되는 패키지 관리자다.
 
1. npm도 package-lock.json 파일을 통해 의존성 버전을 고정하고 관리한다.
2. npm은 버전 관리와 종속성 해결에 대해 yarn보다는 조금 덜 엄격할 수 있다.
3. npm은 충돌 해결 시, 프로젝트 루트에 더 높은 수준의 패키지를 배치해 종속성 설치 충돌을 피하는 경우가 많아, 중복 문제가 발생하기 쉽다.
 
 

yarn

yarn은 속도와 일관성을 중요시하여 만들어졌다.
npm의 문제점을 보완하기 위해 개발됐고, 더 나은 캐싱 메커니즘과 병렬 설치를 통해 더 빠른 설치가 가능하다.
 
1. yarn은 평평한 설치 구조를 사용하여 프로젝트의 모든 종속성을 node_modules에 직접 배치한다. 종속성 문제를 줄이고 더 쉽게 접근할 수 있게 하지만, 패키지 사이의 중복을 증가시킬 수 있다.
2. yarn은 패키지의 버전 충돌을 방지하기 위해 yarn.lock 파일을 사용하여 모든 의존성을 고정한다. 이를 통해 항상 동일한 패키지 버전을 사용할 수 있다.
 
 

 

728x90