워크트리의 링크 두 개가 의존성 폴더를 덮었습니다
node_modules를 빌려 쓰려고 만든 심볼릭 링크가 커밋에 들어갔습니다. 병합 후 실제 의존성 폴더가 자기 자신을 가리키는 링크로 바뀌어 npm ci로 복구했습니다.
들어가며
2026년 9월 7일, 워크트리에서 타입 검사와 테스트를 돌리려고 원래 작업 폴더의 node_modules를 심볼릭 링크로 연결했습니다. 루트와 web/ 아래에 하나씩 만들었습니다. 의존성을 다시 설치하지 않고 쓰려던 것이었습니다.
병합 뒤 생긴 심볼릭 링크 순환
작업을 마치고 git add -A로 변경 사항을 올렸습니다. 링크 두 개도 커밋에 들어갔습니다. develop에 합친 뒤에는 원래 작업 폴더의 실제 node_modules가 사라지고, 그 자리에 자기 자신을 가리키는 링크가 생겼습니다.
개발 서버가 낸 오류는 이랬습니다.
Symlink web/node_modules is in a symlink loop
같은 작업 폴더를 쓰던 다른 세션 셋도 의존성을 잃었습니다. npm ci로 다시 설치해야 했습니다.
무시 목록에 있던 이름
.gitignore에는 node_modules/가 있었습니다. 끝의 /가 문제였습니다. 이 패턴은 디렉터리에만 적용됩니다. 같은 이름의 심볼릭 링크까지 무시하는 패턴이 아니었습니다. Git 문서에도 이 차이가 명시되어 있습니다.
그래서 “이미 무시하는 이름”이라고 생각했던 두 경로가 추적 대상이 됐습니다. 이번 병합에서는 그 경로에 있던 무시된 의존성 디렉터리가 커밋 속 링크로 대체됐습니다. 워크트리에서는 원래 폴더를 가리키던 링크가 원래 폴더에 들어오자 자기 자신을 가리키게 된 것입니다.
마치며
일지에는 다음 워크트리부터 그 안에서 npm ci를 돌리기로 남겼습니다. 무시 규칙도 링크를 놓치지 않도록 슬래시 없는 node_modules를 사용하는 쪽으로 정리했습니다. 이미 커밋에 들어간 경로는 무시 규칙을 추가하는 것만으로 추적이 풀리지 않으니 따로 확인해야 합니다.
커밋 직전에는 다음처럼 스테이징된 경로의 변화를 볼 수 있습니다.
git diff --cached --summary
이 명령은 점검용 예시입니다. 당시에는 이 확인 없이 전체 변경을 올렸습니다. 링크를 만든 곳에서는 테스트가 돌아갔지만, 그 링크가 병합될 곳까지는 보지 못했습니다.