안녕하세요! 지난번 백엔드와 프론트엔드를 모두 고통받게 하던 N+1 쿼리 폭탄은 무사히 해체하셨나요? API 응답 속도가 눈에 띄게 빨라지셨길 바랍니다! 자, 오늘은 프론트엔드 개발자들의 터미널을 붉게 물들이는 또 다른 원흉, 바로 '패키지 매니저의 배신'에 대해 이야기해 볼까 합니다.
금요일 퇴근 전까지만 해도 분명히 아주 잘 돌아가던 프로젝트였습니다. 주말을 푹 쉬고 월요일 아침에 출근해서 가벼운 마음으로 npm start를 쳤는데... 갑자기 화면에 시뻘건 에러가 쏟아집니다. ERESOLVE unable to resolve dependency tree. 아니, 나는 코드를 단 한 줄도 건드리지 않았는데 도대체 왜 이러는 걸까요? 옆자리 동료가 주말에 새로운 라이브러리를 하나 설치하고 푸시했을 뿐인데, 내 로컬 환경은 완전히 박살이 나버렸습니다. 네, 맞습니다. 바로 그 악명 높은 '의존성 충돌(Dependency Conflict)' 지옥에 빠지신 겁니다.
오늘은 블랙홀 같은 node_modules 폴더 안에서 도대체 무슨 일이 벌어지고 있는지, 이 끔찍한 충돌을 어떻게 깔끔하게 해결할 수 있는지 제 숱한 삽질 경험을 바탕으로 속 시원히 파헤쳐 보겠습니다.

1. 도대체 왜 자꾸 충돌이 나는 걸까? (a.k.a 의존성 지옥)
우리가 프론트엔드 개발을 할 때 사용하는 패키지 매니저(npm, yarn 등)는 수많은 남의 코드(라이브러리)를 내 프로젝트로 가져와 줍니다. 그런데 이 라이브러리들도 각자 살아남기 위해 또 다른 남의 코드를 필요로 합니다.
예를 들어, 내가 설치하려는 A라는 패키지는 'React 17버전'을 필요로 하는데, 이미 내 프로젝트에 깔려있는 B라는 패키지는 'React 18버전'만 고집한다고 가정해 봅시다. 패키지 매니저 입장에서는 머리가 아파옵니다. "아니, 17을 깔아야 해, 18을 깔아야 해? 둘이 싸우니까 난 모르겠다, 배째라!" 하고 설치를 멈춰버리는 현상, 이것이 바로 ERESOLVE 에러의 정체입니다. 패키지들끼리 서로 요구하는 버전(Peer Dependencies)이 안 맞아서 멱살을 잡고 싸우는 셈이죠.
2. 마법의 치트키인가 시한폭탄인가: --legacy-peer-deps
구글에 이 에러를 검색하면 가장 먼저 나오는, 그리고 가장 달콤한 유혹이 하나 있습니다. 바로 설치 명령어 뒤에 --legacy-peer-deps를 붙이는 것입니다.
이 옵션을 붙이고 npm install을 치면 신기하게도 빨간 에러가 싹 사라지고 설치가 진행됩니다. 이건 무슨 마법일까요? 사실 마법이 아니라, 패키지 매니저의 눈과 귀를 틀어막는 것에 가깝습니다. "패키지들끼리 버전 안 맞는다고 싸우는 거? 난 안 들리니까 묻지도 따지지도 말고 그냥 다 설치해버려!"라는 무서운 명령이죠. 당장 급한 불을 끄고 로컬 서버를 띄울 수는 있겠지만, 나중에 런타임에서 버전 호환성 문제로 앱이 펑하고 터져버릴 수 있는 시한폭탄을 안고 가는 것과 같습니다. 실무에서는 최대한 지양해야 할 최후의 보루입니다.
3. 가장 확실한 근본 해결책: '껐다 켜기'의 Node.js 버전
그렇다면 어떻게 해결하는 것이 가장 깔끔할까요? IT 업계 최고의 명약, "안 되면 껐다 켜라"의 Node.js 버전을 시전하면 됩니다. 바로 꼬여버린 실타래를 과감하게 싹둑 잘라내는 것이죠.

프로젝트 루트 폴더로 가서, 무지막지하게 무거운 node_modules 폴더 전체와 package-lock.json (또는 yarn.lock) 파일을 미련 없이 삭제해 버리세요.
# 맥/리눅스 환경의 경우 시원하게 날려버립시다!
rm -rf node_modules
rm package-lock.json
# 그리고 다시 새 마음 새 뜻으로 설치!
npm install
lock 파일은 패키지들의 정확한 버전 트리를 족보처럼 기록해 둔 파일입니다. 이 족보가 꼬였기 때문에 충돌이 나는 것이니, 족보와 설치된 폴더를 모두 날리고 package.json 명세서만 믿고 처음부터 다시 깨끗하게 설치를 진행하는 것이 가장 근본적이고 확실한 해결책입니다.
4. 제발 부탁입니다, npm과 yarn을 섞어 쓰지 마세요!
마지막으로 실무에서 정말, 진짜로 자주 일어나는 대참사 하나를 짚고 넘어가야겠습니다. 어떤 동료는 습관적으로 npm install을 치고, 어떤 동료는 yarn add를 치는 팀이 있습니다. 이렇게 되면 하나의 프로젝트 안에 package-lock.json과 yarn.lock이라는 두 개의 서로 다른 족보가 생겨버립니다.
두 패키지 매니저는 의존성을 해석하는 방식이 미묘하게 다르기 때문에, 결국 로컬 환경마다 설치되는 패키지 버전이 달라지는 끔찍한 나비효과를 낳게 됩니다. 팀 내에서 회의를 거쳐 반드시 **'우리 프로젝트는 무조건 npm(또는 yarn, pnpm) 하나만 쓴다!'**라고 규칙을 정하시고, 사용하지 않는 매니저의 lock 파일은 .gitignore에 넣거나 즉시 삭제하셔야 합니다.
마무리하며
오늘은 어제까지 잘 되던 프로젝트를 하루아침에 뻗게 만드는 패키지 매니저의 의존성 충돌 문제에 대해 알아보았습니다. 빨간 에러를 마주하더라도 당황해서 --legacy-peer-deps 같은 치트키를 남발하기보다는, node_modules와 꼬여버린 lock 파일을 과감하게 날려버리고 처음부터 다시 셋업하는 용기를 가져보세요. 또한 팀원들과 패키지 매니저를 하나로 통일하는 작은 규칙 하나만 지켜도, 월요일 아침을 망치는 충돌 지옥에서 영원히 벗어나실 수 있을 겁니다! 오늘 제 삽질 기록이 여러분의 평화로운 로컬 서버 구동에 큰 도움이 되었길 진심으로 바랍니다.
[다음 포스팅 예고] 터미널에서 벌어지는 의존성 지옥을 무사히 탈출하셨나요? 다음 글에서는 프론트엔드 개발자라면 렌더링 최적화와 함께 가장 신경 쓰이는 UI/UX 문제, '글꼴'에 관한 이야기를 해볼까 합니다. 폰트가 늦게 로딩되면서 기본 폰트가 보였다가 확 바뀌거나, 아예 텍스트가 안 보이다가 짠! 하고 나타나는 끔찍한 화면 깜빡임 현상을 겪어보셨나요? 바로 "폰트 깜빡임(FOUT/FOIT) 현상 없이 웹 폰트 완벽하게 로드하기" 편으로 돌아오겠습니다. 예쁜 폰트를 적용하고도 유저 경험을 깎아먹고 싶지 않으시다면, 다음 글도 절대 놓치지 마세요! 오늘도 버그 없는 평온한 하루 보내시길 응원합니다!
[실무에서 복붙해 쓰는 에러 해결 및 트러블슈팅 가이드 #08] 텍스트가 번쩍? 폰트 깜빡임(FOUT/FOIT)
안녕하세요! 지난번 터미널을 새빨갛게 물들였던 의존성 충돌 지옥에서는 무사히 빠져나오셨나요? node_modules를 시원하게 날려버린 용기에 박수를 보냅니다! 자, 오늘은 프론트엔드 개발자라면
code-bricks.tistory.com