devops2025-05-13·7·68/348

npm package-lock.json 충돌 해결 전략

Git에서 package-lock.json 충돌이 발생할 때 효과적으로 해결하는 방법과 예방 전략을 다룹니다.

Introduction

team 프로젝트에서 package-lock.json 충돌은 빈번하게 발생하는 문제입니다. 이 파일은 npm이 의존성의 정확한 버전을 추적하기 위해 자동으로 생성하는 파일로, Git에서 병합할 때 충돌이 발생하기 쉽습니다.

Environment

# 프로젝트 환경
node --version
# v20.11.0

npm --version
# 10.2.4

git --version
# 2.43.0

Problem

feature 브랜치에서 작업 후 main 브랜치로 병합하려고 할 때 충돌이 발생했습니다:

$ git merge main
Auto-merging package-lock.json
CONFLICT (content): Merge conflict in package-lock.json
Automatic merge failed; fix conflicts and then commit the result.

package-lock.json의 충돌 내용:

<<<<<<< HEAD
    "dependencies": {
      "express": {
        "version": "4.18.2",
        "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
        "integrity": "sha512-pq..."
      },
      "axios": {
        "version": "1.6.0",
        "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz"
      }
=======
    "dependencies": {
      "express": {
        "version": "4.18.2",
        "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
        "integrity": "sha512-pq..."
      },
      "lodash": {
        "version": "4.17.21",
        "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
      }
>>>>>>> main

Analysis

충돌 발생 원인

  1. 병렬 개발: 여러 개발자가 동시에 의존성 설치
  2. 캐시 문제: npm 캐시로 인한 불일치
  3. npm 버전 차이: 팀원 간 npm 버전 불일치

package-lock.json 구조

{
    "name": "my-project",
    "version": "1.0.0",
    "lockfileVersion": 3,
    "requires": true,
    "packages": {
        "": {
            "name": "my-project",
            "version": "1.0.0",
            "dependencies": {
                "express": "^4.18.2"
            }
        },
        "node_modules/express": {
            "version": "4.18.2",
            "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
            "integrity": "sha512-pq...",
            "dependencies": {
                "accepts": "~1.3.8",
                "body-parser": "1.20.1"
            }
        }
    }
}

Solution

1. 충돌 해결 후 재설치

# 충돌 해결 후 package.json 기준으로 재설치
$ npm install

# 또는 lockfile 재생성
$ rm package-lock.json
$ npm install

# 변경사항 확인
$ git status

2. npm의 자동 해결 기능 활용

# npm v7+에서는 자동 병합 지원
$ git checkout --theirs package-lock.json
$ npm install

# 또는
$ git checkout --ours package-lock.json
$ npm install

3. .gitattributes로 충돌 전략 설정

# package-lock.json은 항상 재설치로 해결
package-lock.json merge=ours

# 또는 자동 재설치 스크립트 사용
*.lock merge=binary

4. 자동 해결 스크립트 생성

#!/bin/bash
# scripts/resolve-lock-conflicts.sh

echo "Resolving package-lock.json conflicts..."

# 충돌 파일 존재 확인
if git diff --name-only --diff-filter=U | grep -q "package-lock.json"; then
    echo "package-lock.json conflict detected"

    #OURS 버전 유지 후 재설치
    git checkout --ours package-lock.json

    # package.json 업데이트된 내용 반영
    npm install

    # 변경사항 스테이징
    git add package-lock.json

    echo "Conflict resolved. package-lock.json updated."
else
    echo "No package-lock.json conflict found."
fi

5. husky와 lint-staged로 예방

{
    "husky": {
        "hooks": {
            "pre-commit": "lint-staged",
            "post-merge": "npm install"
        }
    },
    "lint-staged": {
        "package.json": [
            "npm install --package-lock-only"
        ]
    }
}

6. Git 머지 드라이버 설정

# .gitconfig에 추가
$ git config merge.ours.driver true

# .gitattributes에 추가
package-lock.json merge=ours

7. 팀 컨벤션 설정

{
    "scripts": {
        "prepare": "husky install",
        "postinstall": "node -e \"try{require('fs').accessSync('.git')}catch(e){console.error('Not a git repo. Run git init first.')}\"",
        "preinstall": "npx only-allow npm"
    },
    "engines": {
        "node": ">=20.0.0",
        "npm": ">=10.0.0"
    }
}

Lessons Learned

  1. npm 버전 통일: .npmrc 또는 engines 필드로 npm 버전을 제한하세요
  2. 정기적 병합: feature 브랜치를 자주 main에 병합하여 충돌을 줄이세요
  3. CI/CD 검증: 파이프라인에서 npm ci를 사용하여 lockfile 일관성을 검증하세요
  4. lockfile 재설치: 충돌 해결 시 npm install로 재생성하는 것이 가장 안전합니다
  5. Gitattributes 활용: merge=ours 전략으로 충돌을 자동으로 해결하세요

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.