퍼포스 아카이브 디팟의 오브젝트 스토리지 지원에 유감

퍼포스 아카이브 디팟의 오브젝트 스토리지 지원은 그럴싸해 보이지만 오브젝트 스토리지에 대해 잘 이해하고 만든 것 같지는 않습니다.

퍼포스 아카이브 디팟의 오브젝트 스토리지 지원에 유감

퍼포스에는 ‘아카이브’라는 기능이 있습니다. 버전 관리 소프트웨어는 특별한 주문이 있지 않은 한 과거 버전을 결코 없애지 않고 유지하기 때문에 오랜 기간에 걸쳐 사용함에 따라 점점 더 많은 스토리지를 사용하게 됩니다. 현대에는 스토리지 가격이 낮아져 테라바이트 단위 스토리지도 그리 어렵지 않게 유지할 수 있지만 여러 사람들이 동시에 사용하면서도 성능 저하를 경험하지 않을 수 있는 수준의 스토리지를 유지하는데는 여전히 높은 비용이 필요합니다. 게다가 필요한 스토리지 용량이 컨슈머 수준의 스토리지를 벗어나는 스토리지를 구축하고 유지하려면 비용 뿐 아니라 높은 수준의 기술력을 요구하며 이를 백업하는데도 상당히 신경 써야만 합니다. 퍼포스의 아카이브 기능은 현재 더 이상 사용하지 않는 파일이나 경로, 오래된 리비전을 데이터베이스에는 유지한 채 분리 가능한 다른 스토리지로 옮겨 스토리지 사용량을 줄일 수 있게 해 줍니다.

아카이브 기능은 단순하게 동작합니다. 먼저 아카이브 할 목적지 디팟을 생성해야 하는데 이 디팟은 오직 아카이브에만 사용하기 때문에 여러 사람이 성능 저하 없이 사용할 첫 번째 스토리지에 비해 훨씬 저렴하고 기술적으로 더 간단한 스토리지를 사용할 수 있습니다. 이러한 별도 스토리지에 아카이브 디팟을 생성한 다음 아카이브 할 파일, 경로, 리비전을 설정하고 아카이브 될 목적지 디팟을 설정하면 퍼포스 서버는 데이터베이스에 이들이 아카이브 되었다고 표시한 다음 목적지 디팟으로 파일을 옮깁니다. 그러면 첫 번째 스토리지에서 파일이 제거되어 스토리지에 남은 용량이 증가하지만 파일은 여전히 데이터베이스에 남아 있기 때문에 모든 히스토리를 그대로 사용할 수 있고 필요할 경우 아카이브 했던 파일을 되돌릴 수도 있습니다. 일단 아카이브가 끝나고 나면 아카이브 디팟을 포함한 스토리지 디바이스를 오프라인으로 전환해 별도 보관하다가 필요할 때 다시 온라인으로 바꿔 되돌리거나 다른 장기 보존용 스토리지에 옮겨 보관할 수도 있습니다.

퍼포스 아카이브는 실제 동작 역시 굉장히 단순합니다. 퍼포스는 파일을 서브밋 - 커밋 - 하면 스토리지에 파일의 기존 경로와 동일한 디렉토리를 생성한 다음 그 하위에 압축해 저장합니다. 바이너리는 압축해 저장하고 텍스트 파일은 변경점만 저장하는데 여기서 핵심은 복잡한 스토리지 포멧 같은 것은 없고 그냥 기존 파일시스템 상 경로 하위에 버전 별로 파일을 그냥 압축해 보관할 뿐입니다. 다만 히스토리를 조회하거나 브랜치, 스트림 등 메타데이터를 변경해야 하는 작업은 별도 자체 데이터베이스에 기록해 처리하고 있습니다. 그럴 일은 거의 없겠지만 만약 퍼포스를 통해 파일을 복구하지 못하는 상황이 찾아오더라도 직접 퍼포스 파일시스템에 접근해 파일을 꺼낼 여지도 있고 이 난이도도 낮아 쉽게 검토할 수도 있을 겁니다. 아카이브는 기존 퍼포스 스토리지 포멧을 똑같이 사용합니다. 아카이브를 실행하면 기존 스토리지 포멧을 똑같이 유지한 채 파일을 스토리지 디팟으로 옮기고 이 사실을 데이터베이스에 기록합니다. 이게 아카이브 기능의 전부입니다. 특별할 것이 전혀 없습니다.

이런 아카이브 기능은 이전까지 별도 하드디스크나 자기테이프 같은 매체에 기록해 보관하는 시나리오에서 잘 동작했을 것 같습니다. 아카이브의 핵심은 더 비싼 스토리지에서 더 싼 스토리지로 당장 사용하지 않는 파일을 옮긴 다음 이들을 별도 보관해 비용을 낮추는 것입니다. 여기서 더 비싼 스토리지와 더 싼 스토리지 사이의 차이는 한 번에 여러 사용자로부터 입출력을 견디는 성능 뿐 아니라 퍼포스 서버로부터 완전히 분리해 별도 보관하더라도 서버와 스토리지 양쪽 모두에 문제를 일으키지 않는 것입니다. 일단 서버 측면에서 파일의 존재를 데이터베이스에 남겨 두되 파일이 아카이브 되었음을 표시해 히스토리를 살펴보면 이전 리비전 기록을 볼 수는 있지만 그 리비전으로 전환할 수는 없는 상태임을 표시합니다. 또 이 기록에 기반해 아카이브 된 파일을 복원해 이전 리비전으로 되돌릴 수 있습니다. 스토리지 측면에서는 스토리지를 서버로부터 분리하더라도 서버와 스토리지 양쪽 모두 독립적으로 유지할 수 있어야 하는데 서버는 이미 데이터베이스 기록을 삭제하지 않으니 아무런 문제가 없고 스토리지에는 메타데이터 없이 기존 스토리지 포멧과 똑같은 구조로 파일을 옮길 뿐이어서 이를 분리한다 하더라도 동작에 아무런 영향을 끼치지 않습니다.

이런 특징 때문에 오랫동안 아카이브 디팟을 S3 같은 오브젝트 스토리지에 생성할 수 있게 해 달라는 요구가 있어 왔습니다. 현재 활발하게 사용되는 디팟을 오브젝트 스토리지에 생성했다가는 입출력 요구를 감당하지 못해 성능에 심각한 문제를 일으키겠지만 한 번 아카이브 하고 나면 이를 복원할 때까지 입출력이 없거나 거의 없기 때문에 오브젝트 스토리지는 일정 규모 이하에서 아카이브에 사용하기 편리합니다. 아카이브 규모가 아주 커지면 자기 테이프 같은 별도 방법을 사용하는 편이 좋겠지만 규모가 그 정도로 크지 않을 때는 실제 미디어를 안전하게 관리하는 것 역시 간단하지 않기에 오브젝트 스토리지는 아카이브, 미디어 관리, 백업 같은 자잘한 문제를 지워 줍니다. 하지만 퍼포스는 이 요구사항을 오랫동안 받아들이지 않아 왔습니다. 물론 그렇다고 해서 방법이 없는 것은 아닌데 S3FS를 사용해 마운팅 포인트를 만든 다음 퍼포스에서 이 경로에 아카이브 디팟을 생성하면 됩니다. 그리고 로컬에 있는 디팟에 아카이브 하듯 이 디팟에 아카이브 하면 오브젝트 스토리지 상으로 파일이 이동됩니다. 이를 사용할 때 장점 세 가지는 아카이브 미디어를 별도로 관리할 필요가 없고 미디어를 제거할 필요가 없어 항상 접근할 수 있을 뿐 아니라 미디어 관리 또는 백업에 신경 쓸 필요가 없다는 것입니다.

퍼포스는 지난 p4d 2023.2 버전부터 아카이브 디팟을 오브젝트 스토리지 상에 생성할 수 있게 됐고 여기에는 S3 뿐 아니라 S3와 호환되는 다른 스토리지 서비스 역시 사용할 수 있다고 합니다. 다만 개인적으로 클라우드플레어 R2를 설정해 보니 설정이 잘못 되어 에러가 발생할 때 원인을 정확히 설명해 주지 않아 올바른 설정을 찾기 굉장히 힘들었습니다. 오리지널 S3를 사용하면 원하는 대로 동작하지만 S3는 호환 서비스에 비해 이용 요금이 높고 특히 스토리지로부터 인터넷을 통해 파일을 읽어 올 때 요금이 높고 또 R2 같은 호환 서비스에 비해 특별히 속도가 더 빠른 것도 아닐 뿐 아니라 전용 스토리지 포멧을 사용하는 것도 아니어서 퍼포스가 직접 제공하는 오브젝트 스토리지 지원 대신 앞에 설명한 S3FS를 통해 R2에 생성한 아카이브 디팟을 사용하기 시작했습니다. 이렇게 될 줄 알았으면 퍼포스가 직접 아카이브 디팟에 오브젝트 스토리지를 지원하기 전부터 그냥 S3FS에 기반해 사용했으면 비용을 더 줄일 수 있었겠다는 생각이 들지만 이제부터라도 비용을 크게 줄일 수 있게 되어 다행입니다.

아카이브 디팟을 오브젝트 스토리지 상에 생성할 수 있게 되었다고 해서 아카이브 방식이 달라지지는 않습니다. 여전히 아카이브는 기존 스토리지 포멧을 유지한 채 직접 파일을 이동 시키는 방식으로 동작합니다. 그래서 파일 갯수가 아주 많을 때 오브젝트 스토리지 상에 있는 아카이브 디팟으로 아카이브를 시도하면 굉장히 느리게 동작합니다. 용량은 고작 몇 기가 밖에 안 되지만 파일 갯수가 만 단위라면 아카이브 하는데 며칠 단위로 시간이 걸립니다. 물론 아카이브 디팟 뿐 아니라 모든 퍼포스 디팟의 스토리지 포멧이 동일하고 또 단순한 모양이기 때문에 재해 대응 난이도가 상대적으로 낮은 장점은 있지만 아카이브 스토리지가 아주 느리게 동작하는 시나리오에서 기존과 완전히 같은 스토리지 포멧은 문제를 일으킵니다.

특히 아카이브 도중에 데이터베이스 전체에 쓰기를 잠가 서브밋을 포함해 상당히 많은 기능이 응답하지 않게 됩니다. 서브밋, 브랜치, 태그 같은 쓰기 기능이 응답하지 않는 것은 조금이나마 이해할 수 있지만 디렉토리 단위의 히스토리 조회 같은 기능도 응답하지 않는 점은 불편하기도 하고 이해하기도 쉽지 않습니다. 사실 아카이브 전후에 파일시스템에 파괴적인 변경이 일어나므로 그 사이에 데이터베이스의 무결성을 보장하기 위해 데이터베이스를 잠그는 것을 완전히 이해할 수 없는 것은 아니지만 아카이브 스토리지가 느린 상황에서 장시간 동안 퍼포스를 정상적으로 사용할 수 없는 점은 파일을 대량으로 아카이브 할 때 계획을 세워야 하고 또 장시간에 걸쳐 아카이브 해야만 하는 상황을 만듭니다. 아카이브 디팟을 오브젝트 스토리지로 옮긴 다음 이제 거의 사용하지 않지만 그냥 삭제하기는 좀 뭣한 오래된 프로젝트 리파지토리를 아카이브 했는데 이 경험은 상당히 나빴습니다. 제 목소리를 녹음해 TTS로 만드는 초기 기계학습 과정을 시도했던 기록었는데 전체 용량은 20기가 남짓이었지만 파일 갯수가 엄청나게 많았습니다. 이 리파지토리를 오브젝트 스토리지에 있는 아카이브 디팟으로 옮기는데 시간이 주 단위로 걸렸습니다. 파일 하나 당 1초가 걸린다 하더라도 며칠이 필요한 상황인데 파일 하나 당 그보다 훨씬 긴 시간이 걸렸기 때문에 아카이브 자체에 엄청난 시간이 필요했고 이 사이에는 퍼포스를 정상 사용할 수가 없었습니다.

만약 퍼포스가 이러한 오브젝트 스토리지의 특성이나 아카이브 하는 동안 무결성 유지를 위해 데이터베이스를 잠그는 특징을 고려했다면 지금처럼 기존 스토리지 포멧을 그대로 유지한 채로 아카이브 기능을 만들지는 않았을 겁니다. 퍼포스 스토리지 포멧은 단순하고 이해하기 쉽지만 많은 파일을 속도가 느린 스토리지로 옮길 때 문제가 있습니다. 특히 속도가 느린 스토리지에 오랜 시간 파일을 이동 시킬 때 퍼포스를 정상 사용할 수 없기 때문에 서비스 중인 상황이라면 주말이나 한밤중에만 아카이브를 해야 하고 이 때문에 그렇잖아도 느린 아카이브에 더 오랜 시간이 걸릴 수 있습니다. 퍼포스가 이런 상황을 고려했다면 아카이브 스토리지로 파일을 옮길 때는 파일 수를 줄이는 다른 스토리지 포멧을 사용해 파일 갯수에 따라 이동 시간이 극적으로 증가하는 기존 스토리지 포멧에 비해 훨씬 빨리 아카이브 할 수 있었을 겁니다. 사실 이 문제를 고려해 잠깐 아카이브 할 디렉토리를 직접 압축한 다음 기존 히스토리를 제거하고 압축된 파일 하나만 아카이브 디팟으로 보낼까 하는 생각도 해 봤는데 이러면 기존 히스토리가 망가지므로 굳이 퍼포스를 통해 아카이브를 할 필요조차 없다는 사실을 깨달았습니다.

아카이브 기능에는 이 뿐만 아니라 다른 자잘한 귀찮은 문제도 있는데 퍼포스는 아마도 서버와 클라이언트, 커맨드라인 인터페이스와 그래픽 유저 인터페이스 사이에 서로 다른 주체가 개발하고 있는 것 같습니다. 그래서 종종 커맨드라인 인터페이스에 추가된 기능이 그래픽 유저 인터페이스에는 없을 때가 많은데 아카이브 역시 마찬가지입니다. 퍼포스 비주얼 클라이언트 상에서 아카이브 된 파일은 다른 아이콘 모양으로 나타나기는 하지만 여기서는 이를 볼 수만 있을 뿐 접근하거나 되돌리는 등 아무런 작업도 할 수 없습니다. 파일이나 경로, 리비전을 아카이브, 리스토어 하고 싶으면 반드시 커맨드라인 인터페이스를 사용해야 합니다. 처음부터 아카이브와 리스토어 기능은 관리자가 사용하는 시나리오를 감안해 개발한 것 같기는 하지만 세월이 흘러 퍼포스 리파지토리가 커지고 사용자가 늘어나면 사용자 개인 수준의 아카이브를 통해 스토리지 비용을 감소 시킬 수도 있었을 테지만 지금은 퍼포스 비주얼 클라이언트 상에서는 아무런 기능도 제공하지 않습니다. 또한 관리자 그래픽 인터페이스 상에서도 아카이브 디팟은 단지 표시되기만 할 뿐 심지어 같은 스토리지 포멧을 사용함에도 관리자 인터페이스 상에서 아카이브 디팟 하위에 보관된 파일 목록을 볼 수조차 없습니다.

애초에 퍼포스 자체가 파일 각각의 라이프사이클 관리에 굉장히 보수적으로 접근하는 도구라는 사실을 이해하지만 시간이 흐름에 따라 더 이상 현재 적극적으로 사용하지 않는 파일이 생기고 이를 다른 가격이 더 낮은 스토리지로 옮겨 유지할 방법은 필요합니다. 아카이브 기능은 기존 스토리지 포멧을 유지한 채 데이터베이스에 기록한 다음 파일의 실제 위치를 옮기는 단순한 방식으로 동작해 단순하고 또 단단하게 동작하지만 오브젝트 스토리지처럼 용량보다 파일 갯수에 영향을 많이 받는 특성을 가진 스토리지를 아카이브에 사용할 때 속도가 너무 느린 문제가 있습니다. 만약 퍼포스가 이러한 오브젝트 스토리지의 특성을 조금 더 깊이 이해했다면 복잡성이 조금 증가하더라도 기존 스토리지 포멧 대신 아카이브 전용 스토리지 포멧을 사용해 아카이브 기능 및 아카이브 디팟의 오브젝트 스토리지 지원 기능을 개발했지 않았을까 싶습니다. 현재 아카이브 및 아카이브 디팟의 오브젝트 스토리지 지원 기능은 동작하기는 하지만 이런 이유로 아쉽습니다.