무게

형상관리도구라고 하면 대개 깃 하나만 떠올립니다. 하지만 큰 파일과 바이너리를 다루는 다른 세계에는 다른 선택지가 있습니다. 2년 반 넘게 개인 파일을 퍼포스로 관리해 온 경험을 바탕으로 이 도구가 어떤 무게를 감당하는지 정리해봤습니다.

무게

발사믹으로 그린 와이어프레임 하나에 게임 스크린샷 몇 장을 더하면 파일은 순식간에 수십 메가바이트가 됩니다. 파워포인트에 보고용 영상을 몇 개 더하면 한 파일이 몇 기가바이트에 이르기도 합니다. 이런 파일 하나를 깃 서버에 푸시하려고 하면 깃은 한참을 끙끙대다가 제가 손쓸 수 없는 에러 메시지를 내뿜고 멈춥니다. 다른 기계에서 같은 파일을 받아오려고 하면 이번에는 받다가 끊깁니다. 커밋은 로컬에서 됐지만 그 커밋을 안전한 곳으로 보내는 일은 완전히 다른 문제였습니다. 코드 한 줄을 고치는 데는 번개같이 동작하던 도구가 그림 한 장 앞에서는 결함 소프트웨어처럼 굴었습니다. 무게가 문제였습니다.

형상관리도구라고 하면 대부분 깃을 떠올립니다. 어지간한 앱이 깃으로 배포되고 깃을 호스팅하는 깃헙은 개발자라면 누구나 계정을 가지고 있습니다. 깃이 텍스트로 된 소스 코드의 세계를 완전히 차지한 것은 분명합니다. 그런데 세상에는 코드만 있는 것이 아니고 형상관리도구도 깃만 있는 것이 아닙니다. 이미지와 3D 에셋과 사운드처럼 열어 봐도 속을 알 수 없는 바이너리 파일 그리고 한 폴더가 수백 기가바이트에 이르는 거대한 저장소를 다루는 다른 세계가 있습니다. 그 세계의 표준 도구가 퍼포스입니다. 게임업계에서 일하며 이 도구를 주로 써 왔고 몇 년 전부터는 개인 파일까지 전부 퍼포스로 관리하고 있습니다. 지난 '돌고 돌아 퍼포스'에서 왜 개인 영역에서 깃을 버렸는지 이야기한 뒤로 2년 반이 지났습니다. 오늘은 이 도구가 어디에서 왔고 누가 왜 쓰며 개인이 쓰면 무엇을 얻는지 정리해보겠습니다.

퍼포스는 깃보다 한참 먼저 나왔습니다. 형상관리도구의 계보는 1972년 벨연구소의 SCCS로 거슬러 올라갑니다[^Source Code Control System]. 파일 하나를 한 번에 한 사람이 고치던 이 방식은 1980년대 RCS를 거쳐 1980년대 후반 CVS에서 여러 사람이 동시에 고치고 나중에 합치는 클라이언트 서버 모델로 발전했습니다. 크리스토퍼 사이월드가 퍼포스를 만든 것이 1995년이고[^Perforce] 원자적 체인지리스트와 대형 저장소 성능 그리고 바이너리 처리로 CVS의 약점을 메웠습니다. 2000년 SVN이 CVS를 다듬어 나왔고 깃이 등장한 것은 2005년입니다[^A Git Origin Story]. 깃은 리눅스 커널을 위해 분산 모델로 태어나 모든 클론이 전체 이력을 갖는 구조의 세상을 만들었습니다. 퍼포스는 그 분산 혁명보다 10년 앞선 중앙집중형 도구지만 분산 물결 이후에도 사라지지 않았습니다. 깃이 약한 무거운 세계를 지켰기 때문입니다. 오래된 만큼 단단하지만 오래된 만큼 이상한 잔재도 있습니다. 그 이야기는 뒤에서 다루겠습니다. 참고로 퍼포스는 여러 차례 주인이 바뀌었고 한동안 힐릭스 코어라는 이름으로 불리다가 2025년 다시 P4라는 옛 애칭으로 돌아왔습니다[^Re-Introducing P4: A Name Rooted in History and a Platform for the Future].

퍼포스가 무거운 것을 감당하는 방식은 단순합니다. 서버가 진실의 원천(SSOT)인 디포를 관리하고 사용자는 워크스페이스라는 매핑을 통해 디포의 필요한 부분만 로컬로 가져옵니다. 깃의 커밋에 해당하는 체인지리스트는 여러 파일을 포함해도 전부 반영되거나 전혀 반영되지 않는 원자적 단위입니다. 여기까지는 다른 도구와 크게 다르지 않지만 저장 방식이 다릅니다. 퍼포스는 파일의 메타데이터를 별도 데이터베이스에 두고 실제 파일은 원래 경로와 이름 그대로 디렉토리를 만들어 그 아래 리비전 번호를 붙여 저장합니다. 텍스트는 델타만 저장하고 바이너리는 매 리비전을 통째로 압축해 보관합니다. 무식해 보이지만 이 단순함이 강점입니다. 최악의 경우 도구 없이 그냥 파일시스템을 뒤져 파일을 꺼내면 되기 때문에 복잡한 복원 절차가 필요 없습니다. 여기에 두 가지 장점이 더 있습니다. 하나는 부분 동기화입니다. 거대한 디포에서 지금 필요한 하위 경로만 받아 작업할 수 있어 모든 기계에 전체 이력을 강요하지 않습니다. 다른 하나는 배타적 체크아웃입니다. 합칠 수 없는 바이너리 자산을 한 번에 한 사람만 열도록 잠가 충돌 자체를 막습니다. 이 두 가지가 큰 파일과 많은 파일이 뒤엉킨 저장소에서 결정적입니다.

그래서 코드보다 크고 무거운 것을 다루는 산업이 퍼포스를 표준으로 씁니다. 가장 큰 시장은 게임 개발입니다. 언리얼 엔진에는 퍼포스 연동이 기본으로 들어 있고 에픽게임즈는 서드파티 개발자에게도 퍼포스를 권장합니다[^What Is Unreal Engine 5 (UE5)?]. 한 게임 기술 조사에서는 응답자 절반 이상이 버전관리에 퍼포스를 쓴다고 답했습니다[^What We Learned From the Perforce 2024 State of Game Technology Report]. 이유는 이 글 첫머리의 제 개인 사정과 같습니다. 수백 기가바이트에 이르는 아트 에셋과 오디오와 영상을 다루고 합칠 수 없는 자산의 충돌을 막아야 하기 때문입니다. 영화와 VFX와 애니메이션도 마찬가지여서 DNEG 같은 대형 스튜디오가 대용량 3D 자산과 글로벌 협업을 이 도구 위에서 처리합니다[^Studio-Scale Animation and VFX Software]. 자동차는 상황이 조금 다릅니다. 소프트웨어 정의 차량으로 넘어가면 코드베이스가 폭발하고 기능안전 규제를 지켜야 합니다. 퍼포스는 2024년 힐릭스 코어가 ISO 26262 기능안전 프로세스 인증을 받아 요구사항부터 구현과 시험까지 이어지는 추적성을 뒷받침합니다[^Perforce's Helix Core Now ISO 26262 Certified for Functional Safety in Automotive Development]. 반도체는 파일 버전관리를 넘어 IP 재사용과 계보 추적이 핵심이라 퍼포스는 메소딕스를 인수해 힐릭스 IPLM으로 이 영역까지 확장했습니다[^Perforce Wiki]. 항공우주와 국방은 보안과 감사와 컴플라이언스 때문에 같은 도구를 고릅니다. 이들을 관통하는 이유는 하나입니다. 대용량 바이너리와 거대한 저장소와 잠금과 경로별 접근통제 그리고 규제 산업의 추적성입니다. 규모의 증거로 구글은 10년 넘게 퍼포스를 단일 모노레포로 쓰다가 자체 시스템으로 옮겼습니다. 옮길 무렵 그 저장소는 86테라바이트에 20억 줄 900만 파일에 이르렀습니다[^Why Google Stores Billions of Lines of Code in a Single Repository]. 세계 최대급 저장소를 그 오랜 세월 버틴 도구라는 뜻입니다.

이 업계 표준화의 이유는 개인에게도 그대로 축소되어 적용됩니다. 코드를 만드는 사람이 아니라 문서와 이미지와 사진처럼 바이너리 파일을 주로 만듭니다. 오래 전에는 SVN을 썼고 한동안은 드랍박스에 기댔고 한동안 업무에 깃을 쓰니 개인 파일도 깃에 익숙해지려 했습니다. 하지만 깃은 첫머리에 적은 그대로 큰 파일 하나조차 제대로 다루지 못했습니다. 풀을 받다 실패하면 메타데이터만 갱신하고 로컬 파일 전부를 변경된 것으로 취급해 버려 비엔지니어를 공포에 빠뜨렸고 수백 기가바이트 저장소의 첫 클론은 며칠이 걸렸습니다. 업무에서는 이미 결정된 정책이라 어쩔 수 없었지만 개인 영역에서까지 그 고통을 감내할 이유는 없었습니다. 그래서 검증된 퍼포스로 돌아왔고 지난 '개인용 퍼포스 사용기 및 영업'에서 적었듯 이 선택은 거의 후회하게 만들지 않았습니다. 드랍박스 같은 서비스와 비교하면 차이는 명시성입니다. 드랍박스는 파일이 바뀌면 알아서 동기화하지만 그 변경이 얼마나 중요한지는 알 수 없습니다. 편집이 많이 일어난 시점과 정말 중요한 변경 시점은 자주 어긋납니다. 게다가 이전 버전은 기본 30일까지만 남습니다. 퍼포스는 제가 원하는 순간에만 맥락을 적은 코멘트와 함께 버전을 만들고 리텐션 제한이 없어 제가 지우기 전까지 아무리 오래된 파일도 끄집어낼 수 있습니다.

퍼포스는 바이너리를 잘 다루는 도구로 시작했지만 쓰다 보니 용도가 계속 늘었습니다. 한동안은 웹에서 마주친 글을 익스텐션으로 저장해 한 폴더에 서브밋했다가 읽은 뒤 다른 폴더로 옮겨 스크랩과 읽음과 아카이빙을 전부 기록으로 남겼습니다. 지금 이 스크랩만큼은 지난 '스크랩 앱 Hoarder 사용기'에서 소개한 카라킵(옛 이름 Hoarder)으로 넘겼지만 그전까지는 이런 일도 퍼포스로 처리했습니다. 설정 동기화를 스스로 제공하지 않는 유틸리티는 실행파일과 설정을 통째로 서브밋해 여러 기계에서 맞춥니다. 무엇보다 업무에서 쓰는 도구를 실수해도 나만 감당하는 개인 환경에서 마음껏 다뤄 본 것이 컸습니다. 브랜치를 나누고 합치고 레이블을 걸고 이전 버전을 되돌리며 도구의 설계 철학과 저장 구조를 익혔고 이 이해가 일할 때 그대로 자신감이 됩니다. 지난 '디지털 휴먼 API (2025)'에서 적었듯 이런 기록은 평소에는 대부분 쓸모없지만 필요한 순간 저를 지옥 밑바닥에서 끄집어냅니다.

시간이 지나며 퍼포스는 파일 저장소를 넘어 제 삶 전체를 모아 두는 단일 파일 기록 공간이 됐습니다. 지난 2년 반 동안 이 서버에 쌓인 커밋은 5만 건이 넘고 저장된 파일은 수 테라바이트에 이릅니다. 여기 들어 있는 것은 코드가 아니라 문서와 사진과 블로그 원고와 스크린샷과 자작 스크립트입니다. 이 저장소에서 한 커밋은 작업 산출물 뿐 아니라 그날 제 삶에 일어난 사건에 가깝습니다. 그래서 커밋 설명도 무엇을 왜 바꿨는지 뿐 아니라 그때 무슨 일이 있었는지를 적게 됩니다. 어떤 서비스나 앱을 쓰다가 그것이 사라지더라도 제 파일과 그 변화 이력은 여기 그대로 남습니다.

여러 기계를 쓰는 문제도 퍼포스가 해결합니다. 업무용 데스크톱과 집 데스크톱과 노트북과 홈랩 서버까지 늘 서너 대를 동시에 씁니다. 이 기계들이 같은 파일을 두고 어긋나지 않아야 합니다. 그렇다고 드랍박스처럼 모든 파일이 모든 기계에 자동으로 복제되기를 바라지는 않습니다. 노트북에는 굳이 거대한 파일까지 내려받고 싶지 않고 업무용 기계에는 개인 파일을 두고 싶지 않기 때문입니다. 퍼포스에서는 기계마다 워크스페이스라는 매핑을 따로 두고 그 기계에 필요한 하위 경로만 골라 동기화합니다. 집 서버는 전부 받고 노트북은 가벼운 것만 받는 식입니다. 각 기계는 제가 명령한 순간에만 서버와 맞추고 그 사이에는 저 혼자 조용히 둡니다. 서버는 홈랩 맥미니의 도커 컨테이너 위에서 돌고 인터넷에 직접 노출하지 않고 테일스케일 뒤에 둬서 어느 기계에서든 같은 주소로 안전하게 접속합니다. 새 기계가 생기면 워크스페이스 하나를 만들어 필요한 경로만 받으면 곧바로 합류하고 대규모 이관을 할 때는 일회용 워크스페이스를 만들었다가 끝나면 버려 매핑이 지저분해지지 않게 합니다.

한 가지 예외는 모바일입니다. 휴대폰이나 태블릿에서 퍼포스 클라이언트를 쓰기는 불편해서 오가는 중에 파일을 잠깐 열어 보기에는 드랍박스가 낫습니다. 그래서 모바일 접근에만 드랍박스를 함께 씁니다. 문제는 드랍박스 무료 버전이 기기를 최대 세 대까지만 연결해 준다는 점입니다. 그래서 드랍박스 앱은 휴대폰 한 대와 홈랩 서버 한 대에만 켜 두고 나머지 기계는 전부 퍼포스로만 동기화합니다. 두 세계를 연결하는 일은 홈랩 인프라를 감시하려고 만든 자작 도구가 겸합니다. 이 도구는 홈랩 안에 나란히 있는 두 로컬 폴더를 지켜봅니다. 하나는 드랍박스 앱이 클라우드와 맞추는 폴더이고 다른 하나는 퍼포스 클라이언트가 디포와 맞추는 폴더입니다. 도구는 일정 주기마다 양쪽 폴더의 모든 파일을 해시로 비교해 어느 쪽이 바뀌었는지 가려낸 다음 바뀐 파일을 반대쪽으로 복사하고 퍼포스 쪽 변경은 곧바로 서브밋합니다. 양쪽이 동시에 바뀌면 더 나중에 고친 쪽을 택하고 판단이 애매하면 퍼포스를 우선합니다. 그래서 휴대폰에서 드랍박스 폴더에 파일을 하나 두면 클라우드를 거쳐 홈랩에 도착하고 도구가 그것을 퍼포스에 서브밋해 다른 모든 기계에서도 곧 받아 볼 수 있습니다. 반대로 데스크톱에서 퍼포스로 서브밋한 파일은 홈랩을 거쳐 드랍박스 폴더로 복사되어 휴대폰에서도 열립니다. 드랍박스는 무료로 2기가바이트를 주지만 오래 전부터 쓴 덕에 10기가쯤을 무료로 쓰고 있어 모바일에서 잠깐잠깐 열어 보기에는 충분합니다. 이렇게 세 대 제한을 퍼포스로 우회하고 히스토리 제한 역시 받지 않습니다. 드랍박스 무료 버전은 삭제한 파일과 이전 버전을 30일까지만 유지해 주지만 이 연결 덕분에 모든 파일이 퍼포스에도 들어가 리텐션 없이 아무리 오래된 버전이라도 되돌릴 수 있습니다.

모든 기계가 이렇게 서버 한 곳에 의존하니 백업도 단순해집니다. 예전에는 기계마다 따로 백업해야 했지만 이제는 퍼포스 서버 한 대만 신경써서 백업하면 됩니다. 다른 기계가 고장 나면 새 기계에 퍼포스 클라이언트를 설치하고 워크스페이스를 새로 만들어 서버에서 다시 받으면 그만입니다. 대신 그 한 대는 제대로 지켜야 해서 백업은 3-2-1 원칙을 철저히 따릅니다. 서버가 도는 맥미니는 타임머신으로 한 시간마다 로컬 디스크 두 개에 번갈아 백업하고 같은 서버를 Arq Backup으로 한 번 더 로컬에 백업하며 마지막으로 Backblaze B2 스토리지에 원격으로 백업합니다. 여기에 퍼포스 자신의 데이터베이스는 매일 새벽 체크포인트를 만들어 둡니다. 중요한 것은 백업 소프트웨어가 APFS 스냅샷 위에서 동작한다는 점입니다. 데이터베이스처럼 여러 파일이 정확히 같은 시점이어야 복원되는 자료는 스냅샷 없이 백업하면 복원할 때 어긋나기 때문입니다. 이 전략은 이론적으로만 동작한 것이 아니라 실제로 여러 번 저를 구했습니다. 데이터베이스 파일이 깨졌을 때도 스토리지가 죽었을 때도 결국 이 백업에서 되돌렸습니다. 다만 그 과정에서 전체 복원은 실제로 해 보기 전에는 모르는 함정이 많다는 것도 배웠습니다. 그래서 백업이 정말 복원되는지를 사람 손으로 확인하지 않고 자동으로 시험합니다. 홈랩을 감시하는 그 자작 도구가 주마다 백업 하나를 골라 격리된 위치에 통째로 복원하고 컨테이너를 띄워 정상 동작까지 확인한 다음 정리합니다. 한 번도 복원해 본 적 없는 백업은 백업이 아니기 때문입니다.

장점만 있는 것은 아닙니다. 지난 '퍼포스에 대한 개인적 불만'에서 길게 다뤘습니다. 핵심만 추리면 이렇습니다. 퍼포스는 중앙집중형이라 서버가 없으면 거의 아무것도 못 합니다. 오프라인에서도 파일을 사용한다고 선언하고 커밋까지 하는 깃과 정반대입니다. 무결성 검사와 백업은 대부분 수동이라 관리자가 직접 챙겨야 하고 텍스트를 다루는 파일 타입 이름은 오래된 잔재라 헷갈립니다. 서드파티 도구와의 연동은 약하고 무엇보다 자기 스스로는 웹이나 모바일 클라이언트를 제공하지 않습니다. 그리고 개인이 서버를 직접 굴린다는 것은 문제가 생길 때 직접 해결해야 한다는 뜻입니다. 지난 2년 반 동안 데이터베이스 파일이 깨져 서브밋이 영원히 끝나지 않은 일을 '퍼포스 서버 데이터베이스 오류 문제해결'에서 다뤘습니다. 잘못된 경로에서 서버를 실행해 모든 데이터가 사라진 줄 알고 오싹했던 일을 '개인 퍼포스 장애 대응 보고'에 적었습니다. 싸구려 외장 SSD가 죽어 백업에서 이틀에 걸쳐 복원한 일을 '스토리지 장애대응 보고'로 남겼습니다. 무료로 강력한 도구를 얻은 대가는 이런 수고입니다.

마지막 단점 하나에는 제 나름의 답이 있습니다. 퍼포스는 웹 클라이언트를 주지 않아 브라우저나 휴대폰에서 디포를 열어 보거나 간단히 서브밋할 방법이 없었습니다. 데스크톱에 P4V를 설치해야 하고 웹으로 협업하려면 스웜이라는 무거운 별도 제품을 따로 운영해야 합니다. 예전에는 퍼포스가 P4Web이라는 웹 클라이언트를 직접 냈지만 2008년 판을 끝으로 오래 방치되어 지금은 쓸 수 없습니다[^Perforce P4Web - 2008.2 Release Notes]. 개인과 소규모 팀 크기에 맞는 물건이 그 사이에 없어서 이틀에 걸쳐 그냥 만들었습니다. 이름은 p4-web입니다. p4 명령줄 클라이언트를 감싼 파이썬 프로세스 하나와 빌드 과정이 없는 자바스크립트 화면이 전부인 가벼운 웹 퍼포스 클라이언트입니다. 로그인하면 패스워드를 퍼포스 티켓으로 바꾸고 패스워드 자체는 저장하지 않으며 이후 모든 동작이 그 사용자의 권한으로 실행되어 퍼포스의 접근 제어가 P4V에서와 똑같이 적용됩니다. 디포 트리를 열고 파일을 보고 히스토리와 diff를 확인하고 리비전을 오가며 블레임을 다시 계산하는 조회 기능부터 갖춘 뒤 사용자별 서버측 워크스페이스를 두고 웹에서 편집과 서브밋까지 처리하도록 만들었습니다. 공개 전에는 전 기능을 열어 놓고 코드 리뷰와 보안 감사와 레드팀을 거쳤습니다. 소개 페이지와 소스는 공개해 두었습니다[^p4-web 소개 페이지].

p4-web의 'Changes' 화면입니다. 상단의 상태와 사용자와 경로 필터 아래로 사용자별 검색 인덱스 상태 바와 체인지리스트 목록이 이어집니다. 화면에 보이는 데이터는 공개용 가상 픽스처입니다.

그래서 모두가 퍼포스를 써야 한다는 이야기는 아닙니다. 텍스트 코드를 다루고 오프라인과 값싼 브랜치가 중요하다면 깃이 맞습니다. 형상관리도구의 선택은 결국 무엇을 나르느냐의 문제입니다. 가벼운 텍스트를 나른다면 깃이 빠르고 편하지만 큰 파일과 바이너리라는 무게를 나른다면 깃은 앞서 이야기한 대로 자주 주저앉습니다. 그 무게를 군말 없이 감당하는 도구가 필요하다면 게임 스튜디오와 자동차 회사와 반도체 회사가 오래 검증해 온 이 도구를 개인도 그대로 쓸 수 있습니다. 사용자 다섯 명과 워크스페이스 스무 개까지는 무료입니다[^P4 Pricing and Plans]. 다만 무료로 강력한 것을 얻는 대가로 서버 한 대를 직접 관리해야 합니다. 그 수고가 아깝지 않을 만큼 무거운 것을 나르고 있다면 한번 올려 볼 만합니다. 앞으로도 한동안 이 도구에 제 모든 파일을 맡기고 지낼 것 같습니다.