라이트세일에 구축한 퍼포스 서버 사용기

라이트세일에 퍼포스 서버를 구축한다면 꼭 별도 스토리지를 붙인 다음 그 위치에 구축하세요. 그리고 퍼포스는 파일시스템에 파일을 직접 저장하니 다국어 환경에서는 무조건 유니코드 지원 설정을 켜야 합니다.

라이트세일에 구축한 퍼포스 서버 사용기

제가 오랜 기간에 걸쳐서, 또 여러 번에 걸쳐서 깃에 대한 강한 불평 불만을 토로해 온 것을 기억하실 겁니다. 깃이 서기 2023년 겨울 현재 세계에서 가장 널리 활용되는 형상관리도구라는 사실을 부정할 생각이 없으며 이 도구가 세계적인 여러 프로젝트를 성공적으로 운영하고 있다는 사실 역시 인정합니다.

그런데 이 도구가 확실히 잘 하지 못하는 분야가 있고 만약 그 분야에서 이 도구를 사용하려면 암만 생각해도 복잡한 환경, 이상한 절차를 겪어야 할 뿐 아니라 이들을 겪는다 하더라도 온전한 동작을 보장할 수 없다는 사실을 겪을 때마다 기술에 익숙하지 않은 여러 직군이 함께 일하고 바이너리 파일을 많이 다루며 리파지토리 크기가 큰 프로젝트에 적당하지 않다는 점에는 여러 모로 안타까웠습니다. 특히 얼마 전까지 참여하 프로젝트는 언리얼 엔진 기반으로 개발하는데 형상관리도구에 깃을 사용하며 이를 호스팅 하기 위해 깃헙을 사용했는데 이 조합이야말로 언리얼 개발과 완전히 반대쪽에 있는 이상한 형상관리 환경이라는 점을 긴 기간에 걸쳐 체험하며 딱 한번 내린 잘못된 의사결정이 시간에 따라 프로젝트에 얼마나 큰 비용을 부담하게 만드는지 체험했습니다.

기왕에 회사에서 버전관리에 깃을 사용하고 있으니 개인적으로도 이 환경에 익숙해질 겸 해서 깃을 버전관리 도구로 사용하기 시작하며 회사에서는 여러 사람이 바이너리 파일을 수없이 올려 대니까 이상한 동작을 할 수도 있다고 생각했습니다. 특히 여러 파일을 풀 해올 때 메타데이터만 업데이트 하고 실제 파일을 업데이트 하는데 실패하면 이 상황을 인지하지 않고 새로 업데이트 된 메타데이터와 업데이트 되지 않은 로컬 파일을 비교해 로컬 파일이 변경 되었다고 판단해 이 파일을 모두 스테이지에 올려놓는 모습은 처음에는 당황스러웠지만 나중에는 웃겼고 시간이 더 지나자 귀찮았습니다. 습관적으로 스테이지에 올라온 모든 파일을 디스커드 해야 했기 때문입니다.

혼자서 사용하는 작은 환경에서는 그러지 않을 거라고 예상했습니다. 하지만 깃은 빗버킷을 통해 단 4기가짜리 리파지토리를 사용할 때도 똑같지는 않지만 이상한 문제는 여전히 일어났습니다. 오피스 문서는 순식간에 수 십 메가가 되는데 단지 이들을 명시적으로 버전을 만들어 놓고 싶을 뿐이지만 푸시에는 긴 시간이 걸렸고 특히 이들을 다른 기계에서 풀 하는 데는 참아주기 힘든 시간이 걸리곤 했습니다.

라이트세일에 구축한 퍼포스 서버는 개인 버전 관리를 엄청나게 편하게 만들었습니다.

깃은 개인적인 사용 환경에도 전혀 부합하지 않는다는 사실을 깨달은 다음 회사에서 이 도구를 사용하며 고통 받는 현실에 좀 더 적응하기 위해 개인적으로도 같은 도구를 사용하며 좀 더 익숙해지는 것 보다는 차라리 제 요구사항을 가장 잘 처리하는 검증된 도구를 사용해 이 고통의 절반으로부터 탈출하는 편이 좋겠다는 결정을 내렸습니다. 그래서 지난번에 돌고 돌아 퍼포스에서 애초에 처음부터 바이너리 파일을 잘 다루고 리파지토리가 아무리 커져도 문제 없이 동작하는 퍼포스를 사용하기 시작하며 이전에 개인적으로 사용하며 제게 온갖 고통을 주던 깃을 완전히 사용하지 않게 되었다는 이야기를 했습니다.

이제 개인 용도로는 깃을 완전히 없애고 퍼포스를 사용하기 시작한 지 한 달이 되어 가는데 퍼포스 자체는 이미 아주 오래 전부터 사용해 온 터라 도구 자체는 예상하는 대로 잘 동작합니다. 다만 퍼포스 서버를 구동하는 기계 사양이 충분하지는 않기 때문에 아주 많은 파일을 한번에 서브밋 하거나 아주 많은 파일을 한번에 체크아웃 할 때 좀 느려지는 문제가 있었지만 이 정도면 이전에 깃을 사용할 때는 애초에 한 번에 커밋 한 다음 푸시 할 수조차 없는 크기여서 납득할 만한 수준입니다. 최소한 퍼포스는 동작에 실패하더라도 그냥 바로 이어서 작업을 재시작 하면 이어서 작업을 끝낼 수 있어 실패한 작업을 직접 제거하고 같은 작업을 재시도하게 만드는 깃과는 비교할 수 없이 편합니다.

하지만 회사에서 사용하는 퍼포스를 클라이언트로만 사용할 때와 퍼포스 서버를 만들어 클라이언트를 사용하고 동시에 서버를 관리해야 하는 입장에서는 이전에 오직 클라이언트만 사용할 때와 비교해서 자잘한 관리 지점이 생겼고 오늘은 퍼포스 서버를 사용하며 알게 된 특징, 아쉬운 점, 관리 요령을 공유할 작정입니다. 크게 퍼포스가 바이너리 파일을 잘 다루는 이유는 바이너리 파일을 압축해서 아카이브에 직접 보관하기 때문인데 이 점은 아쉬운 점과 바로 연결됩니다. 바이너리 파일을 압축해서 파일시스템에 보관하기 때문에 어떤 파일의 이전 버전을 요청하면 간단히 압축된 파일의 압축을 풀어 클라이언트로 던져줄 뿐이어서 빠르게 동작하는 장점은 있습니다.

하지만 여러 언어로 된 파일 이름을 직접 파일시스템에 사용하기 때문에 파일 이름에 사용된 언어가 다양해짐에 따라 문제가 생길 여지가 있습니다. 가령 처음 서버를 생성할 때 서버가 유니코드를 지원하게 할 지, 말 지를 선택할 수 있는데 만약 여기서 유니코드를 지원하지 않는다고 하면 적어도 둘 이상의 언어를 항상 사용하는 동양권에서는 여러 언어로 된 파일 이름을 직접 서버 파일시스템에 저장해 버리는 특성 상 큰 문제를 겪을 여지가 있습니다. 한국인처럼 둘 이상의 언어를 항상 사용한다면 반드시, 무조건 유니코드를 지원하도록 설정해야 합니다.

이와 비교할 때 처음에 개인 버전관리 도구로 사용하던 SVN은 서버에서 한 커밋을 한 파일에 저장하고 있었습니다. 한 커밋에 파일 100개를 커밋하면 서버에서는 이 커밋 번호를 이름으로 한 파일 한 덩어리에 커밋한 모든 파일을 묶어 저장했는데 퍼포스와 비교할 때 파일 이름을 직접 파일시스템에 사용하지 않아 여러 가지 언어로 된 파일 이름에 의한 문제가 생길 여지는 훨씬 적어 보입니다. 하지만 SVN을 버전 관리에 사용하던 시대에는 종종 파일시스템에 따라 한 파일의 최대 크기에 제한이 있는 환경일 때가 있었는데 이럴 때 한 번에 파일시스템의 최대 파일 크기 제한보다 더 많은, 더 큰 여러 파일을 한 번에 커밋하려고 할 때 문제가 생기기도 했습니다. 이런 원인 때문인지 확실하지는 않지만 종종 SVN에서는 오래된 리비전으로 돌아가려고 할 때 파일이 깨져 있어 리비전으로 돌아갈 수 없는 일이 종종 일어나곤 했는데 이런 점들은 현대에 파일시스템 제약이 거의 없어진 상황에서도 SVN 사용을 기피하게 만들었습니다.

퍼포스는 파일 경로와 이름을 파일시스템에 직접 사용해 저장합니다.

한편 퍼포스가 바이너리 파일을 잘 다루는 이유는 그냥 간단합니다. 아무 가공 없이 파일을 올리면 파일 이름으로 된 파일시스템 상의 경로 하위에 파일을 압축해서 저장하기 때문입니다. 다른 방법에 비해 스토리지를 더 많이 차지하는 문제가 있어 보이기는 하지만 현대에 스토리지는 저렴하고 파일시스템에 물리적 제한도 거의 없는 것과 마찬가지여서 바이너리를 직접 저장한 다음 아무리 오래된 리비전이라도 순식간에 가져올 수 있는 쪽이 훨씬 사용하기에 편리합니다. 또 파일을 비교해야 할 때 자체 비교 도구를 제공해 본격적인 개발 도구를 사용하지 않는 비 개발자 입장에서 별도의 비교 도구를 준비하지 않아도 되는 장점도 있습니다.

AWS의 단순한 버전인 Lightsail에서 퍼포스 서버를 운영하면 EC2에 서버를 만들 때에 비해 압도적으로 자잘한 설정을 신경 쓰지 않고 쉽게 인스턴스를 생성하고 또 퍼포스를 설치해 운영을 시작할 수 있지만 Lightsail에서는 볼륨 크기를 조절할 수 없기 때문에 스토리지가 부족해져 이를 확장할 때가 되면 방법이 별로 없다는 점에 당황할 수도 있습니다. Lightsail은 EC2에 비해 압도적으로 단순해 비 개발자가 별다른 지식 없이 쉽게 서버를 만들 수 있게 해 주지만 EC2처럼 볼륨 크기를 직접 조정해 확장할 수는 없습니다. 처음에는 별 생각 없이 Lightsail 작은 인스턴스에 시험 삼아 퍼포스 서버를 구축했는데 이내 스토리지가 부족해져 확장하려고 보니 두 가지 방법 밖에 없었습니다.

하나는 스토리지만 늘리고 싶더라도 CPU, 메모리, 스토리지, 전송량이 한 번에 묶인 상위 번들로 이동하는 것입니다. 이건 이전 서버의 스냅샷을 만든 다음 더 큰 번들로 옮겨 인스턴스를 생성하면 끝나니 엄청나게 편하기는 하지만 필요한 것은 스토리지 뿐이었는데 메모리, CPU 같은 원하지 않는 사양을 번들로 함께 구입해야 해서 필요보다 더 높은 비용을 사용해야만 합니다.

다른 방법은 Lightsail에서 스냅샷을 만든 다음 이를 EC2로 가져가서 본격적인 AWS 환경에 인스턴스를 만드는 것인데 애초에 Lightsail이 본격적으로 AWS를 사용하기 전에 맛보기로 사용하는 일종의 게이트웨이 같은 역할을 한다고 볼 때 이런 유도는 회사가 의도한 움직임처럼 느껴지기는 합니다. 하지만 Lightsail에 비해 EC2는 같은 결과에 도달하는데 훨씬 더 자잘한 설정을 신경 써야 하기 때문에 단지 퍼포스 서버를 계속해서 사용하고 싶은 요구사항이 있을 뿐인데 갑자기 AWS에 서버 인프라를 관리하는 일을 추가하고 싶지는 않았습니다.

EC2와 달리 Lightsail에서는 미리 가상 디스크를 만들어 구축하는 편을 추천합니다.

Lightsail에서 선택할 수 있는 방법은 가상 스토리지를 생성해 기존 인스턴스에 마운트 한 다음 퍼포스 서버 디렉토리를 가상 스토리지 경로로 설정하는 방법입니다. 퍼포스 매뉴얼 상에는 스토리지를 확장하는 방법에 그냥 새 스토리지를 마운트 하고 이전 파일을 모두 복사한 다음 퍼포스 서버 설정에 새 경로를 지정한 다음 실행하기만 하면 된다고 나와 있지만 실제로는 이렇게 쉽게 되지는 않았습니다. 처음에는 이렇게까지 간단하다니 역시 서버 관리도 편하다고 생각했지만 실제로는 단순 복사로는 권한 문제, 소유권 문제, 퍼포스 서버가 구동되는데 필요한 모든 파일의 경로가 설정 하나만으로는 일괄로 바뀌지 않는 문제 등등 온갖 이상한 문제가 일어나 스토리지 확장을 아주 고통스럽게 만듭니다.

그래서 개인적으로 추천하는 방법은 Lightsail에 작은 인스턴스로 퍼포스 서버를 만들고 싶다면 처음부터 인스턴스에 가상 스토리지를 만들어 마운트 한 다음 퍼포스 서버를 처음 설정할 때 스토리지를 마운트 한 가상 스토리지 경로로 설정하는 것입니다. 이러면 나중에 스토리지를 확장해야 할 때 그냥 퍼포스 서버를 중단한 다음 이전 스토리지에서 새 스토리지로 파일을 복사하고 이전 스토리지의 마운트를 끊고 그 위치에 새 스토리지를 마운트 한 다음 퍼포스 서버를 시작하면 되니 확장이 굉장히 편리합니다.

Lightsail에서 퍼포스 서버를 관리할 때 편리한 점 중 하나는 백업입니다. 사실 이건 퍼포스 서버를 관리할 때 나타나는 장점이라기 보다는 Lightsail의 장점이기도 한데 하루 한 번 서버 전체에 대한 스냅샷을 자동으로 만들어 문제가 생길 때 문제에 빠르게 대응할 수 있습니다. 퍼포스 매뉴얼에서는 일정 시점마다 p4 verify 명령을 사용해 데이터베이스 기록과 실제 파일시스템 상의 파일을 비교해 무결성을 검사하고 또 일정 시점마다 p4 admin journal 명령을 사용해 일종의 데이터베이스 백업을 만들라고 되어 있습니다. 아마도 어떤 이유로 데이터베이스 무결성에 문제가 생기면 이전에 생성한 저널 파일을 참고해 데이터베이스를 복구하는데 사용하는 것 같은데 아직 까지는 이런 작업을 할 일이 없어서 실제로는 어떻게 사용될지 모르겠습니다.

하지만 Lightsail에서 퍼포스 서버를 관리하고 스냅샷을 켜 놨다면 문제가 생길 때 일단 현재 서버 상에서 문제를 해결해 보고 상황이 여의치 않다면 이전 스냅샷으로 새 서버를 만들어 그쪽으로 옮겨 가면 끝나기 때문에 문제를 직접 수정하지 않고 서비스를 복원할 수 있어 좋았습니다. 만약 제 핵심 임무가 서버를 안전하게 관리하는 것이라면 문제가 일어난 원인을 파악하고 이를 제발하지 않도록 조치해야 하겠지만 이것이 핵심 임무가 아닌 이상 제 입장에서는 문제가 생길 때 이 문제 상황을 빠르게 해결할 수 있는 방법이 존재하는 쪽이 훨씬 마음이 놓입니다.

그래서 또 다시 결론은 지난 돌고 돌아 퍼포스와 똑같이 여러 바이너리 파일을 다루는 비 개발자 입장에서 버전 관리를 필요로 할 때 깃이 요구사항에 잘 부응하지 못해 고통 받은 경험이 있다면 사용자 다섯 명, 워크스페이스 스무 개 까지 무료인 퍼포스를 사용해 바이너리 파일을 전혀 다루지 못하는 깃으로부터 해방되어 버전관리에 신경 쓰지 말고 작업에만 집중하세요. 그리고 하나 더, 언리얼 기반으로 개발하고 있는데 형상관리도구로 깃을 사용하고 있다면 답이 없으니 도망치세요. 이 결정을 내린 사람은 아마 팀에 엔지니어 이외의 직군이 있다는 사실을 고려할 생각이 없는 사람일 가능성이 있으니 도망칠 여러 가지 이유가 있을 겁니다.

아. 이건 지난 권고사직 이후 오피스에 갔다가 아무도 돕지 않고 돌아선 사건의 원인인데 뭔가를 도우려고 했지만 그때 제 회사 기계에는 리파지토리 클론이 없었고 이를 깃헙 리파지토리로부터 클론하다가 관리자로부터 제기를 받았기 때문입니다. 이전에 회사 기계 스토리지에 불량이 생겼고 부담 없는 윈도우 재설치를 여러 번 반복해도 문제가 해결되지 않자 이상한 수집욕에서 한 달에 걸쳐 크래시 된 횟수를 기록해 제시한 끝에 스토리지를 교체 받을 수 있었습니다. 상당히 열이 받았지만 회사에 돈이 없어 어쩔 수 없다고 생각했습니다. 하지만 리파지토리 전체를 받기에는 턱없이 부족한 용량이었기 때문에 개인 외장 SSD에 리파지토리를 클론해 사용하고 있었는데 권고사직 이후 개인 외장 SSD를 뽑아 집에 들고 가 맥북 타임머신 용도로 전환했기 때문에 회사 기계에는 리파지토리 클론이 없었습니다.

저...기 그럼 저 일하지 말까요?

하지만 깃헙 요금제는 전송량에 과금하기 때문에 누군가 리파지토리를 클론하려고 시도하면 전송량을 평소에 비해 훨씬 많이 사용해 전송량 제한을 초과해 모든 사람의 리파지토리 사용을 막을 수 있습니다. 그래서 엔지니어들 끼리는 이따금씩 리파지토리 클론을 압축해 공유디렉토리에 올려 놓고 클론 하는 대신 이 압축 파일을 로컬에 복사한 다음 여기서부터 풀을 받아 전송량을 절약하고 있었던 것 같습니다. 비용을 절약하는 관점에서 이해가 안 되지는 않지만 엔지니어 부서에서 사용하던 전송량 절약 방법을 팀 전체에 문제가 생기고 나서야 공유하며 앞으로 문제가 생기면 계정 사용 제한을 하겠다는 메시지를 보고 정말 이 도구와 이 환경과 이 호스팅 서비스를 선택한 결정이 올바른지 다시 한 번 고민해보게 됐습니다. 결국 아무도 돕지 못하고 돌아설 수밖에 없었는데 정말 이게 최선인가 하는 생각을 여러 번 하게 만들었습니다.