"제발 그 파일 좀 지우지 마세요": package-lock.json과 yarn.lock이 존재하는 이유

2025. 12. 1. 15:31·Development/JavaScript
패키지 잠금 파일 package-lock.json, yarn.lock 

 

출처: dev_hee

1. 들어가며: "내 컴퓨터에선 되는데요?"

협업 중에 이런 경험 한 번쯤 있을 것이다.

분명 내 로컬 환경에서는 잘 돌아가던 코드가, 동료의 컴퓨터나 배포 서버에서는 에러를 뿜어내는 상황 말이다. 코드는 똑같은데 왜 결과가 다를까요? 범인은 바로 '미묘하게 다른 라이브러리 버전'일 확률이 높다.

오늘은 Node.js 생태계(React, Vue, NestJS 등)에서 개발할 때 필수로 생성되지만, 귀찮은 존재로 오해받기도 하는 package-lock.json과 yarn.lock에 대해 정리해본다.

 

 

2. package.json만으로는 부족하다

우리는 프로젝트에 필요한 라이브러리를 package.json에 명시한다. 하지만 자세히 보면 버전 앞에 이상한 기호들이 붙어 있는 경우가 있다.

 

"dependencies": { "react": "^18.2.0", "axios": "~1.6.0" }

바로 Semantic Versioning(유의적 버전)을 따르는 범위 기호들이다.

  • ^ (Caret): 마이너 버전 업데이트까지 허용 (예: ^1.2.3 -> 1.9.9까지 설치됨)
  • ~ (Tilde): 패치 버전 업데이트까지 허용 (예: ~1.2.3 -> 1.2.9까지 설치됨)

이 기호들 때문에, 오늘 내가 `npm install`을 했을 때와 내일 동료가 `npm install`을 했을 때 설치되는 실제 라이브러리 버전이 달라질 수 있다. 이 작은 차이가 치명적인 버그를 만든다.

실제로 프로젝트를 개발 할 때는, ^를 제거하여 고정적인 버전이 설치되게 하고 있다.

그래서 나는 yarn.lock, package-lock.json 파일이 불필요한 줄 알았다.

 

 

3. Lock 파일의 역할

이 불확실성을 해결하기 위해 등장한 것이 바로 Lock 파일 (package-lock.json, yarn.lock)이다.

  • 역할: 현재 프로젝트에 설치된 모든 패키지의 정확한 버전, 의존성 트리 구조, 무결성 해시(Hash)를 스냅샷처럼 기록한다.
  • 효과: 이 파일이 있으면 언제, 어디서, 누가 설치하든 100% 동일한 의존성 트리가 생성됨을 보장한다.

 

비유하자면:

  • package.json: "김치찌개 끓여줘. 재료는 대충 돼지고기랑 김치면 돼." (요리법)
  • lock 파일: "2024년 12월 1일 생산된 A브랜드 김치 200g, B정육점의 앞다리살 150g..." (정확한 영수증)

 

 

4. 핵심: '중첩 의존성'까지 잠가버린다

Lock 파일이 진짜 중요한 이유는 내가 설치한 패키지뿐만 아니라, 그 패키지가 의존하는 또 다른 패키지(Transitive Dependencies)의 버전까지 고정하기 때문이다.

예를 들어, 내가 A 라이브러리를 설치했는데 A가 내부적으로 B라는 라이브러리를 쓴다면? `package.json`에는 A만 적혀있지만, lock 파일에는 A와 B의 정확한 버전이 모두 기록된다. 소리 소문 없이 업데이트된 B 라이브러리 때문에 내 프로젝트가 터지는 것을 막아준다.

 

 

5. 실무 가이드 & Best Practices

Q1. Lock 파일은 깃(Git)에 올려야 하나요?

A. 무조건 Yes.

Lock 파일이 공유되어야 팀원 전체와 CI/CD 서버가 동일한 환경을 가질 수 있다.
`.gitignore`에 넣지 말고, 공유될 수 있도록 remote에 올려야한다!

 

Q2. `npm install` vs `npm ci`

CI/CD 파이프라인(Jenkins, GitHub Actions 등)에서는 `npm install` 대신 `npm ci (Clean Install)`를 사용해야 한다.

  • npm install: package.json을 기준으로 설치하며, 필요하면 package-lock.json을 수정해버린다. (버전 불일치 가능성)
  • npm ci: 철저하게 package-lock.json만 보고 설치한다. 락 파일과 package.json이 다르면 에러를 뱉는다. 또한 node_modules를 지우고 새로 깔기 때문에 더 빠르고 안정적(Deterministic)이다.

 

Q3. Lock 파일 충돌(Conflict)이 났을 때는?

깃 머지 과정에서 Lock 파일 충돌이 나면 수동으로 JSON을 수정하지 않는다. (사람이 할 짓이 아님)

그냥 삭제 후 재생성한다.

yarn.lock / 수정할 엄두도 나지 않음..

  1. 충돌 난 lock 파일을 삭제
  2. npm install (또는 yarn install)을 다시 실행하여 락 파일을 재생성
  3. 변경된 락 파일을 커밋

 

6. 마무리

`package-lock.json`과 `yarn.lock`은 단순한 설정 파일이 아니라, 프로젝트의 안정성을 보장한다.

"귀찮은 파일"이라고 삭제하지 말고, lock 파일을 통해서 모든 개발자가 동일한 버전을 사용할 수 있도록 사용해야한다.

 


연관 키워드

  1. Flat vs Nested Dependency:
    • npm v3부터는 중복된 의존성을 최대한 최상위(root)로 끌어올려 평탄화(Flat) 시킨다. Lock 파일이 이 구조를 기억하고 있다.
  2. Checksum (무결성 검사):
    • Lock 파일 내부를 보면 integrity라는 긴 해시값이 있다. 다운로드한 패키지 파일이 위변조되지 않았는지 검증하는 보안 역할을 한다.
  3. Yarn Berry (v2+):
    • 최신 Yarn은 node_modules를 아예 없애는 PnP(Plug'n'Play) 전략을 쓴다. 이때는 .pnp.cjs 같은 파일이 Lock 파일과 함께 더 중요한 역할을 하게 된다.

'Development > JavaScript' 카테고리의 다른 글

[JS] Emotion (CSS-in-JS)  (0) 2024.03.30
'Development/JavaScript' 카테고리의 다른 글
  • [JS] Emotion (CSS-in-JS)
곽진돔
곽진돔
Developer
  • 곽진돔
    echo "곽박한 세상";
    곽진돔
  • 전체
    오늘
    어제
    • 분류 전체보기 (203)
      • Development (74)
        • Linux (13)
        • k8s (3)
        • Docker (5)
        • AWS (1)
        • PHP (35)
        • Python (21)
        • Java (1)
        • SpringBoot (4)
        • JavaScript (2)
        • React (10)
        • MySql (19)
        • MongoDB (1)
      • Daily (6)
      • Study (7)
        • TIL (2)
        • license (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 설정
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    ssh
    JavaScript
    springboot
    Linux
    SQL
    Selenium
    윈도우
    IP
    nodejs
    리액트
    스프링부트
    chromedriver
    크롤링
    Shell
    error
    Java
    CentOS7
    MySQL
    date
    react
    정규표현식
    HTML
    php
    리눅스
    db
    UTF8
    docker
    Python
    CentOS
    인코딩
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
곽진돔
"제발 그 파일 좀 지우지 마세요": package-lock.json과 yarn.lock이 존재하는 이유
상단으로

티스토리툴바