← 홈Setup Tip

Setup Tip

Setup Tip — 심볼릭 링크로 걸어 둔 의존성 폴더는 복사본이 아니다

일회용 작업 트리마다 의존성을 새로 설치하기 싫어서 원본 저장소의 의존성 폴더를 심볼릭 링크로 걸면, 설치는 몇 밀리초로 끝나지만 빌드는 엉뚱한 이유로 실패할 수 있다. 번들러는 링크를 따라간 실제 경로가 프로젝트 루트 밖에 있다는 이유로 모듈을 거부한다. 링크 대신 하드링크나 복사로 진짜 디렉터리를 만들어야 한다.

상황

변경마다 깨끗한 작업 트리를 새로 만들어 빌드하는 습관은 좋다. 작업 중인 체크아웃의 잔여물이 결과에 섞이지 않기 때문이다. 문제는 의존성이다. 수백 메가바이트짜리 의존성 폴더를 트리마다 다시 설치하는 건 느리고, 설치 도구 자체가 호스트 런타임 버전과 맞지 않아 실패할 때도 있다. 그래서 가장 먼저 떠오르는 지름길이 원본 체크아웃의 폴더를 심볼릭 링크로 걸어 두는 것이다.

무엇이 깨지는가

링크를 건 트리에서 빌드를 돌리면 코드와 무관한 오류가 난다. 요지는 "이 모듈의 경로가 파일 시스템 루트 밖을 가리킨다"는 것이다. 요즘 번들러는 보안과 캐시 일관성을 위해 프로젝트 루트를 경계로 삼고, 모듈을 불러올 때 심볼릭 링크를 끝까지 풀어 실제 경로를 본다. 그 실제 경로가 다른 체크아웃 안에 있으니, 번들러 입장에서 그 파일들은 프로젝트 밖의 낯선 파일이다. 설치는 성공했고 링크도 정상인데 빌드만 실패한다.

왜 헷갈리는가

이 오류는 방금 한 변경을 의심하게 만든다. 새로 만든 트리에서 처음 돌린 빌드가 실패했으니 당연하다. 하지만 같은 커밋을 원본 체크아웃에서 빌드하면 멀쩡히 통과한다. 차이는 코드가 아니라 트리를 준비한 방식에 있다. 두 결과를 나란히 놓고 보기 전까지는 원인을 엉뚱한 곳에서 찾게 된다.

해결

작업 트리에 진짜 디렉터리를 준다. 같은 파일 시스템이라면 하드링크 복사가 가장 싸다. 파일 내용은 공유하면서 디렉터리 항목은 트리 안에 실제로 존재하므로, 번들러가 경로를 풀어도 루트 안에 머문다. 파일 시스템이 다르면 일반 복사를 한다. 어느 쪽이든 설치 도구를 다시 돌리지 않아도 되고, 호스트 런타임과 설치 도구의 버전 충돌도 피해 간다.

주의할 점

하드링크는 내용을 공유하므로 트리 안에서 의존성 파일을 직접 고치면 원본도 같이 바뀐다. 의존성을 패치해야 하는 작업이라면 그 트리만큼은 일반 복사를 쓴다. 그리고 작업이 끝나면 트리를 정리한다. 하드링크 트리는 디스크를 거의 차지하지 않는 것처럼 보여서 쌓여 가기 쉽다.

확인 방법

트리를 준비한 직후 의존성 폴더가 링크가 아니라 디렉터리인지 한 번 확인하고, 빌드가 원본 체크아웃과 같은 결과를 내는지 본다. 한 번 이 방식으로 준비 스크립트를 고정해 두면, 다음 사람은 같은 오류를 보고 자기 변경을 의심하느라 시간을 쓰지 않는다.