홈랩 정전 대응

예정된 정전에 대비해 홈랩에서 돌아가는 서비스들을 유지하기 위해 임시로 서버 하드웨어와 위치를 옮기며 여러 가지 일을 겪었습니다.

홈랩 정전 대응

전기안전관리법 시행규칙 제 20조 1항에 따르면 공동주택의 사용전검사를 시행한 날로부터 25년이 지난 날부터 3년 안에, 또 이 안전점검을 한 날로부터 매 3년마다 안전검사를 시행하도록 규정하고 있습니다. 그리고 제가 살고 있는 집은 이 조건에 맞기 때문에 전기 안전검사를 수행해야 합니다. 그리고 이 전기 안전검사를 수행하려면 일정 시간 동안 공동주택 전체의 전원을 차단해야 합니다. 전원이 차단되어 작동하지 않는 장치의 범위에는 엘리베이터나 지하주차장 진입램프, 번호에 의해 개방되는 보안문 같은 공용 시설물부터 인터넷이나 셀룰러 신호를 보내 주는 중계기 같은 것들도 포함됩니다. 각 가정의 모든 전기 장치를 사용할 수 없게 되는 것은 당연한 수준입니다. 여태까지는 이런 안전점검에 별 관심이 없었습니다. 어쩌면 지난 3년 안에 이런 안전점검을 또 했었는지도 모릅니다. 하지만 기억이 희미합니다. 했는지 안 했는지 잘 모르겠습니다. 왜냐 하면 신경 쓸 필요가 없었기 때문입니다. 평일 낮에 두어 시간 동안 전기가 사라진다고 해서 당장에 문제 될 일은 거의 없습니다. 냉장고 정도가 좀 걱정되지만 두 시간 동안 문을 열지 않는다면 버틸만하고 나머지 어지간한 장치들은 전기가 나갔다가 돌아오면 다시 켜져 낮에 집을 비우고 있으면 전기가 나갔었다는 사실 조차 모를 겁니다.

그런데 약 1.5년 전부터 사용하기 시작한 홈랩은 24시간 켜져 있어야 합니다. 처음에는 개인적으로 사용하는 서비스를 주로 구동해 서버가 오작동해 서비스를 사용하지 못하게 되더라도 불편을 저 혼자 감당하면 됐지만 고스트 블로그를 온프레미스 환경으로 이전하면서 블로그를 직접 호스팅 하게 됐고 또 마스토돈을 온프레미스 환경으로 이전하면서 많지는 않지만 어쨌든 다른 사용자가 있는 서비스를 호스팅 하게 되면서 서비스가 중단되면 불편을 느끼는 사람이 저 혼자가 아니게 되었습니다. 이전까지는 예정된 정전에 아무 신경 쓸 필요가 없었지만 이제 신경 써야만 하는 상황이 된 겁니다. 사실 정전 상황에서 홈랩을 계속해서 운영할 방법은 없습니다. 처음에는 서버 전체를 랩탑으로 옮겨 배터리로 두 시간 정도를 버티면 되는 단순한 문제라고 생각했습니다. 하지만 단지 전체가 단전되면 집으로 들어오는 인터넷 회선을 사용할 수 없게 될 겁니다. 서버에 전원이 들어와 있다 한들 인터넷에 연결되지 않으면 아무 소용이 없었습니다. 이 상황에 모바일 인터넷을 통해 서비스를 유지할 수 있지 않을지도 잠깐 생각해봤는데 지금 제가 사용 중인 요금제의 테더링 용량 제한으로는 도저히 버틸 수 없어 보였고 특히 셀룰러 네트워크 중계기들도 꺼질 것이 분명해 꽤 먼 곳으로부터 신호를 받아야 하니 별로 쓸 만 하지 않을 겁니다. 그래서 예정된 단전 시간 동안 집에서 홈랩 서비스를 유지하는 것은 불가능하다는 결론에 이르렀습니다.

좀 더 현실적인 문제도 있습니다. 만약 제가 단전 시간대에 물리적으로 집에 있다면 그냥 단전 직전에 안전하게 하드웨어를 종료하고 그냥 두 시간 다운타임을 기다린 다음 전원이 돌아오면 서비스를 재개하면 그만일 수도 있습니다. 다운타임이 생기는 건 좀 아쉽지만 평일 낮에 두 시간 정도는 개인이 운영하는 홈랩 수준에서 감당할 수 있는 수준이 아닐까 싶었습니다. 한 달에 두 시간 다운타임이면 업타임 비율이 99.7%쯤 되니 할만한 것 아닌가 싶습니다. 하지만 이런 시나리오의 현실적인 문제는 평일의 저는 생업을 위해 집에서 상당히 멀리 떨어진 장소에서 일하고 있을 거라는 사실입니다. 그래서 예정된 단전이 있는 날에도 아침에 집을 나서야 하고 저녁에나 집에 돌아와야 합니다. 단전이 있기 전에 서비스를 중단하거나 단전이 끝난 직후에 서비스를 재개할 수 없습니다. 원격에서 이 작업을 할 방법을 생각해봤습니다. 하지만 여기에는 KVM Over IP 기능이 있는 별도 장비가 필요했습니다. 맥OS는 여러 가지 방법으로 원격 접속을 지원하지만 파일시스템을 암호화 하고 있으면 재시작 한 다음 첫 로그인을 하기 전에는 원격으로부터 그 무엇도 할 수 없습니다. 그래서 별도의 원격 장비가 필요했는데 꽤 진지하게 원격 제어 하드웨어를 알아봤지만 특히 와이파이 네트워크를 통해 동작하는 맥미니에 붙여 사용할 수 있는 하드웨어는 적어도 제 검색에는 나타나지 않았습니다. 그러니까 낮 시간의 단전 시작 시각 전에 서비스를 중단할 수는 있었지만 한 번 운영체제를 종료하고 하드웨어 전원을 차단하면 단전이 끝난 다음 원격에서 다시 서비스를 시작할 방법이 없었습니다.

단전 시작 시각 전에 원격에서 운영체제를 종료하고 다운타임을 시작한 다음 그냥 퇴근해서 다시 서비스를 시작하는 방법도 생각해봤습니다. 다운타임은 대략 대여섯 시간 정도인데 정말 어쩔 수 없으면 이렇게 해야겠다고 생각하고 여러 가지 시나리오 중 맨 밑에 올려 두었습니다. 하지만 이 시나리오는 결국 실행할 수 없게 됐는데 하필 단전이 있는 날 빠질 수 없는 저녁 약속이 생겼기 때문입니다. 단전 시작에 맞춰 서비스를 종료할 수 있지만 서비스 재개는 자정이 넘은 시점에나 할 수 있을 지도 몰랐습니다. 또 그 시점의 저는 만취상태여서 제대로 서비스 재시작을 해내지 못할는지도 모릅니다. 그래서 긴 다운타임을 그냥 맞이해버리는 시나리오는 수행할 수 없다는 결론에 다다랐습니다. 서버가 집에 있는 이상, 그리고 제가 집에서 멀리 떨어진 장소에서 일하고 있는 이상 어느 정도 다운타임이 생기는 것을 감안하더라도 뭔가 매끄럽지 않았습니다. 뭔가 다른 좀 더 현실적인 대안이 필요했습니다.

앞서 랩탑에 모든 서비스를 띄우고 배터리 생각을 했던 시점으로 돌아가 봅시다. 생각해보니 랩탑은 평소에는 회사에 있고 주말에 잠깐 집에 가져와 사용합니다. 단전 시간 동안 랩탑을 집에 가져와 사용할 생각을 했으니 이걸 반대로 생각하면 랩탑이 회사에 있는 상태로 서비스를 수행할 수 있을 것 같았습니다. 지난 홈랩 투어 (2025)에서 소개한 대로 현재 서비스를 구동하고 있는 하드웨어는 맥미니 M4 모델인데 랩탑은 맥북에어 M1 모델입니다. 일단 CPU 아키텍처와 운영체제가 동일해 종종 아키텍처에 따른 바이너리가 만들어낸 데이터가 서로 호환되지 않아 다른 기계에서 인스턴스를 띄울 수 없는 문제가 생길 것 같지 않았습니다. 물론 메모리가 64기가에서 16기가로 줄어들지만 운영체제가 알아서 스왑을 잘 사용해 별 문제 없이 돌지 않을까 싶었습니다. 게다가 지난 개인 백업 전략을 소개한 다음 레이드 1로 구성한 하드디스크 기반 스토리지로 돌리던 서비스들을 모두 외장 SSD 스토리지로 옮겨 구동하고 있었습니다. 그렇다면 출근할 때 주머니에 SSD를 넣어 들고 출근해 랩탑에 서비스를 올려 놓고 또 퇴근할 때 다시 서비스를 중단한 다음 주머니에 SSD를 넣어 퇴근해 맥미니에 다시 연결해 서비스를 재시작하면 되지 않을까 싶었습니다. 이 시나리오는 출근시간과 퇴근시간 동안 다운타임이 일어난다는 점이지만 가장 현실성 있었고 또 다운타임이 단전 시간 동안 제가 집에 있다가 전원이 돌아오자마자 서비스를 다시 시작하는 것과 거의 비슷했습니다. 또 그 시간 동안에 회사에서 일할 수도 있었고요.

다만 이 시나리오에는 두 가지 감안할 점이 있습니다. 두어 시간 동안의 다운타임 발생을 감안하더라도요. 일단 제가 출퇴근에 무리 없이 들고 갈 수 있는 것은 외장 SSD 뿐입니다. 이 말은 나머지 백업 하드웨어는 모두 집에 남게 된다는 점이고 홈랩 서비스가 랩탑에서 임시로 구동되는 동안에는 백업이 없다는 의미입니다. 사실 그 정도 시간 동안에 뭔 일이 일어날까 싶기는 하지만 백업이 있는 상태와 백업이 없는 상태에는 아주 거대한 차이가 있습니다. 만약 문제가 생기면 SSD를 분리해 출발하기 이전에 생성된 백업으로 돌아가야만 합니다. 지난 퍼포스 서버 데이터베이스 오류 문제해결 때 한 시간 단위로 만들어진 타임머신 백업이 없었다면 심각한 문제를 겪었을 수 있었지만 타임머신 백업 덕분에 한 시간이 안 되는 데이터 유실을 겪고 무사히 서비스를 정상으로 되돌릴 수 있었습니다. 또 홈랩에 일상의 많은 부분을 의존하고 또 다른 사용자가 있는 서비스를 구동하는 이상 백업은 매우 매우 중요합니다. 데이터가 유실되고 데이터베이스가 망가지는 상황에서 ‘뭐 중요한 데이터는 없으니 그냥 처음부터 다시 하지 뭐’ 같은 결정은 불가능합니다. 그래서 백업이 없는 상황에 놓인다는 사실이 상당히 불편했습니다. 하지만 이 위험을 해결할 수 없었습니다. 다른 한 가지 문제는 인터넷 연결입니다. 회사는 업무용 네트워크 외에 직원들의 편의를 위해 업무용 네트워크와 분리된 와이파이 네트워크를 제공합니다. 엄밀히 말해 이 와이파이 네트워크는 편의를 위한 것만은 아닙니다. 와이파이 네트워크를 제공하면 직원들의 물리적 동선을 파악할 수 있고 또 이 네트워크를 통해 보안 규정을 우회한 데이터 전송이 일어날 경우 이를 모니터링 할 수 있습니다. 홈랩에서 돌아가는 모든 서비스는 클라우드플레어 터널이나 테일스케일 중 하나를 사용하고 있어 네트워크 관제에 제가 뭘 하고 있는지 직접적으로 드러나지는 않을 테고 또 이 행동이 어떤 규정을 위반하는 것도 아니지만 과연 이래도 될는지 좀 걱정스러웠습니다.

계획은 이렇습니다. 단전이 예정된 당일 아침 출근 직전에 도커 컨테이너들을 모두 중지한 다음 외장 SSD를 언마운트하고 운영체제를 종료한 다음 SSD를 분리해 이걸 들고 출근합니다. 또 이참에 한동안 미뤄둔 맥OS 업데이트를 수행하고 또 공유기 펌웨어 업데이트 역시 수행합니다. SSD를 들고 회사에 도착하면 랩탑에 이를 연결하고 도커 컨테이너들을 실행하면 되는데 이 때 시간을 최소화 하기 위해 전날 미리 도커 이미지를 모두 받아놨습니다. 또 혹시 예상하지 못한 원인으로 컨테이너가 구동되지 않는 상황이 일어날까 싶어 한 번도 구동해본 적 없는 ‘Hello World’ 컨테이너도 한번 띄워봤습니다. 랩탑에 SSD를 연결해 도커 컨테이너들이 다 뜨면 수동으로 서비스들이 돌아가는지 둘러본 다음 그대로 두면 됩니다. 그럼 만 하루 이상 사양이 낮은 하드웨어에서 서비스들이 돌아가겠지만 어쨌든 더 긴 다운타임이 발생하지 않을 수 있습니다. 또 단전이 일어나고 또 빠질 수 없는 저녁 약속에 갔다가 다음 날 다시 출근했다가 퇴근할 때 이번에는 랩탑 쪽에서 도커 컨테이너들을 중지 및 삭제하고 SSD를 언마운트해서 들고 퇴근해 다시 집 맥미니에 연결해 컨테이너들을 재시작하면 됩니다. 백업 하드웨어들은 이 계획을 시작할 때 맥미니 전원을 내릴 때 함께 전원이 차단되고 또 운영체제를 시작할 때 전원이 인가되어 로그인 하고 나면 마운트 될 겁니다. 아마 백업 소프트웨어들이 자동으로 시작되겠지만 혹시 모르니 수동으로 확인하면 될 겁니다. 딱히 문제가 발생할 것 같아 보이지는 않았습니다. 절차를 잘 기록한 다음 예정된 단전이 일어날 당일이 되었습니다.

나갈 준비를 마친 다음 마지막으로 도커 컨테이너를 모두 종료하고 외장 SSD를 언마운트 한 다음 케이블에서 뽑아 주머니에 넣었습니다. 그리고 운영체제 업데이트를 해 놓고 집을 나섭니다. 공유기 펌웨어 업데이트도 해야 하지만 공유기에는 테일스케일을 통해 접근할 수 있기 때문에 지하철을 타고 이동하는 도중 원격에서 해도 됩니다. 1초가 아까운 아침 시간에 굳이 직접 하지 않아도 되는 일 때문에 나가는 시간을 늦출 수 없습니다. 닌자 퇴근술에 소개한 대로 평소와 같이 아무 짐 없이 폰과 교통카드, 회사 출입카드, 에어팟만 덜렁 들고 길을 나섭니다. 다른 날과 달리 오늘은 한 쪽 주머니에 홈랩 전체가 들어있는 8테라짜리 외장 SSD가 들어있지만 지나가는 아저씨가 주머니에 수 테라바이트에 이르는 홈랩 전체를 들고 있을 거라고 상상하기는 어려울 겁니다. 미친듯이 밀리는 출근시간대의 2호선을 뚫고 회사에 도착할 때까지 아무런 문제도 일어나지 않았습니다. 회사에 도착해 재빨리 랩탑에 도커 데스크탑을 띄우는 사이에 SSD를 마운트합니다. 이어서 터미널에서 각 스택을 돌며 서비스를 시작해 줍니다. 혹시 하드웨어가 바뀌었다고 뭔가 문제가 생기지 않을지 조마조마했지만 스택과 스택에 포함된 각 컨테이너들은 아무 문제 없이 시작되었습니다. 와이파이 네트워크에 잘 연결될지도 좀 걱정이었는데 클라우드플레어 터널과 테일스케일 모두 아무 문제 없이 연결되었습니다. 다만 테일스케일은 DERP 서버를 경유했는데 속도가 훨씬 느리지만 불만을 가질 만한 수준은 아닙니다. 52분 간의 다운타임 후 서비스를 재개했습니다.

이제 걱정할 문제는 제가 실수로 랩탑을 덮어 버리는 것입니다. 클램쉘 모드로 사용할 수 있다는 것을 알고 있지만 뚜껑을 덮어 버릴 때 시스템이 중단되지 않도록 하려면 어떻게 해야 하는지 지금 당장은 모릅니다. 또 일단 출근했으니 더 이상 이 상황에 신경 쓰고 싶지도 않았습니다. 그래서 오래 전 오피스 빌딩 냉방 문제해결 사례 때 데이터를 얻기 위해 사용했던 인터넷으로 기록을 쌓아 주는 온습도계를 랩탑에 올려놨습니다. 본능적으로 랩탑을 닫으려 할 때 걸리적거리며 지금 제가 뭔가 해서는 안될 일을 시도하고 있다는 사실을 일깨워줄 겁니다. 의외로 맥북에어 M1은 여러 스택에 걸친 40여개에 달하는 컨테이너들을 멀쩡히 구동해 냈습니다. 모바일 네트워크를 통해 접근해 본 서비스들은 대체로 멀쩡한 것처럼 보였는데 몇몇 서비스들은 이전보다 느리게 동작하는 것을 체감할 수 있었습니다. 모니터링 소프트웨어가 보고하는 CPU나 메모리 사용량에는 여유가 있는 것으로 미루어 네트워크 속도로 인한 문제가 아닐까 의심해봤지만 확신할 수는 없었습니다. 일단 집에 일어날 정전과 무관하게 서비스가 동작하는 상태가 된 것 만으로 충분합니다. 앞서 잠깐 생각해본 대로 백업이 완전히 없어진 상태가 상당히 거슬리기는 하지만 이건 운에 맡기기로 합니다. 설마 그 사이에 뭔 일이 일어날까요. 근데 그 뭔 일이 일어났습니다.

평소와 같이 파일 모양으로 저장한 자료를 찾으려고 퍼포스 리파지토리를 돌아다니는 도중 서버로부터 끊겼다는 메시지가 나타납니다. 재접속 버튼을 몇 번 눌러봤지만 접속할 수 없습니다. 평소 같으면 원격에 있는 서버 상태를 확인해야 하지만 이번에는 서버 기계가 바로 옆에 있습니다. 잠금을 풀고 무슨 일이 일어났는지 살펴봅니다. 도커 데스크탑은 거의 모든 스택이 정상 동작하고 있다고 보고했지만 일부 컨테이너가 재시작에 실패하고 있었습니다. 일단 이들이 재시작 된 원인을 알 수 없었고 또 재시작에 실패하는 원인도 아직 알 수 없었습니다. 그런데 화면 오른쪽 위에 ‘외장 드라이브가 안전하게 분리되지 않았다’는 메시지가 나타나 있습니다. 깜짝 놀라 파인더를 열어 확인해봤지만 SSD는 멀쩡히 마운트 되어 있었습니다. 그러니까 중간에 어떤 이유로 SSD가 언마운트 됐다가 다시 마운트 된 것 같은데 이 때 어떤 컨테이너는 살아남았지만 어떤 컨테이너는 문제를 일으켜 재시작 된 것 같습니다. 그런데 SSD가 안전하지 않게 언마운트 되면서 파일이 깨진 것 같았습니다. 재시작에 실패하는 컨테이너를 보니 둘 다 sqlite를 사용했는데 데이터베이스 파일을 열 수 없다며 시작에 실패하고 있었습니다. 얼른 검색해보니 sqlite 파일을 덤프하거나 테이블 중 일부만 덤프한 다음 복원하는 절차가 있었지만 sqlite를 사용하는 서비스는 이런 작업을 할 도구 없이 sqlite를 임베딩 한 채로 배포됩니다. 그러니까 문제를 해결하려면 별도 도구를 설치해야 했는데 이 상황에 전혀 대비 되어 있지 않았고 일 해야 했기 때문에 이 상황에 신경을 더 쓸 여유는 없었습니다. 컨테이너 하나는 홈랩 투어 (2025)에 소개한 ‘docklogkeeper’여서 로그를 날리고 처음부터 다시 시작해도 상관 없었습니다. 다른 한 컨테이너는 ‘portainer’였는데 고맙게도 백업 디렉토리에 이전 데이터 파일을 따로 가지고 있었습니다. 이 백업을 끄집어내 sqlite 파일을 덮어 쓰고 나니 컨테이너가 재시작 되었습니다.

당장의 문제를 해결한 것 같았지만 애초에 이런 현상이 왜 일어났는지 설명할 수 없었습니다. 처음 든 생각은 맥OS의 ‘가능하면 하드디스크를 잠자기 상태에 두기’ 옵션 때문이 아닐까 하는 것이었습니다. 그렇다 하더라도 스토리지가 언마운트 되는 것은 이상했지만 일단 이 쪽을 의심해봅니다. 하지만 랩탑에는 이 옵션이 없었습니다. 검색해보니 맥OS가 늘 그렇듯 예쁜 GUI를 통해 제공하지 않는 옵션은 모두 터미널에서 입력해야 하는 명령어로 되어 있습니다. 맥OS는 윈도우 레지스트리더러 뭐라고 할 게 아닙니다. 잠자기 모드 전체를 해제하려면 sudo pmset -a disablesleep 1이라고 입력하면 되는 모양입니다. 이런 안내들은 종종 너무 오래 된 경우가 많아 매년 업데이트를 거듭하며 여러 가지 설정이 사정 없이 바뀌고 있는 맥OS의 현실을 반영하지 못할 때가 많아 이런 설정이 잘 동작할지 의심스러웠지만 뭐 일단 해봅니다. 또 신경 끄고 한참을 일하다가 똑같은 상황이 다시 찾아왔습니다. 이번에도 퍼포스 서버가 응답하지 않기 시작했고 바로 무슨 일이 일어났는지 확인해봅니다. 이번에도 SSD가 언마운트 됐다가 마운트 된 상태였고 컨테이너 두 개가 재시작에 실패하고 있었습니다. 이번에는 postgres가 재시작에 실패하고 이 데이터베이스에 의존성이 있는 다른 컨테이너 하나도 시작에 실패하고 있었습니다. postgres가 시작할 때 올바른 체크포인트를 찾을 수 없고 또 WAL이 고장났다고 보고했는데 이 시점의 저는 WAL이 뭔지도 몰랐습니다. 어쨌든 데이터베이스가 고장났고 이번에는 그냥 날리고 재시작할 수 없었습니다.

일단 체크포인트는 퍼포스의 체크포인트와 비슷한 일종의 백업 같아 보입니다. 그러니까 체크포인트가 없다고 해서 당장 데이터가 사라졌을 것 같진 않습니다. 또 WAL은 ‘Write Ahead Log’의 약자인데 이건 일종의 저널과 비슷해 보입니다. 데이터베이스에 트랜잭션을 보내기 전에 일단 로그를 만든 다음 트랜잭션에 성공하면 로그를 제거하는 식으로 동작합니다. 그래서 레플리카 여러 개가 있는 환경에서 WAL만 동기화하면 이에 따라 레플리카들이 같은 데이터 쓰기 작업을 할 수 있다고 합니다. 그런데 WAL이 깨졌다는 건 아직 데이터베이스에 트랜잭션을 보내지 않은 상태의 데이터가 유실될 거라는 의미입니다. 하지만 기존 데이터들이 살아남는다면 새 데이터는 다시 읽어오면 되니 이 상황을 어떻게 해결하기만 하면 될 것 같습니다. 검색해보니 이 상황에 WAL을 리셋하는 명령이 있었고 대략 pg_resetwal -D /var/lib/postgresql/data같은 형식으로 쓰면 되는 것 같아 보입니다. 다만 도커 컨테이너 안에서 수행해야 하는데 데이터베이스가 시작에 실패할 때마다 컨테이너가 재시작 되고 있었기 때문에 도커 데스크탑 GUI 상에서는 아무것도 할 수 없었습니다. 터미널에서 docker exec -it hollo-postgres bash를 실행해 컨테이너 내부 쉘을 실행합니다. 그리고 앞서 준비한 pg_resetwal을 실행하는데 이번에는 수퍼유저만 이 명령을 실행할 수 있다며 튕겨냅니다. 저는 이미 root 유저였고 이 메시지를 이해할 수가 없었습니다. 더 이상의 수퍼유저라는 것이 존재할 수 없는 것 아닌가 싶었습니다. 하지만 검색해보니 postgres가 말하는 수퍼유저는 운영체제의 root가 아니라 postgres라는 다른 유저라는 점을 알게 되었습니다. 애초에 docker compose 할 때 root 유저로 데이터베이스를 실행했지만 어쨌든 수퍼유저는 root가 아닌 모양입니다.

그러면 sudo -u postgres pg_resetwal …을 실행하면 될 거라고 생각했는데 이번에는 sudo가 없습니다. 생각해보니 이런 최소 이미지에는 평소에 당연하다고 생각한 여러 유틸리티가 빠져 있었습니다. sudo가 없다고 해도 이상한 일은 아닙니다. 다만 postgres 수퍼유저 권한으로 명령을 실행할 쉬운 방법이 없어졌을 뿐입니다. 처음으로 su - postgres라고 뒤에 계정 이름을 붙여 su를 쓸 수 있다는 것을 배웠습니다. 그런데 이 환경에서는 PATH 설정이 모두 사라져 pg_resetwal 실행파일을 찾지 못합니다. 그래서 /usr/lib/postgresql/17/bin/으로 이동한 다음 명령어를 입력해야 합니다. 명령은 잠깐 동안 실행된 다음 다시 프롬프트로 돌아왔습니다. 도커 데스크탑 인터페이스에서 postgres 인스턴스를 시작하자 이번에는 멀쩡히 시작됩니다. 이 데이터베이스에 의존성이 있는 서비스도 멀쩡히 실행됩니다. 윈도우를 사용하며 항상 USB 스토리지를 운영체제에서 제거하지 않고 그냥 뽑아버리곤 했는데 그러다가 큰일 난다는 사실을 이런 식으로 썩 달갑지 않은 방법으로 배웠습니다. 전원 옵션을 변경했고 깨진 데이터베이스를 포기하거나 바로잡아 서비스를 유지했습니다. 하지만 얼마 후 같은 문제가 또 일어났습니다. 이번에는 다행히 중단된 컨테이너는 없었지만 이 문제가 앞으로도 계속해서 일어나며 문제를 일으킬 거라는 사실은 확실해 보였습니다. 원인을 찾아야 합니다.

그러다가 문득 이 외장 SSD를 랩탑에 연결하는데 사용하는 비실비실한 케이블이 눈에 띕니다. 어디서 구한 케이블인지는 모르겠지만 그 동안 다른 스토리지를 연결할 때 멀쩡하게 잘 써 왔습니다. 하지만 암만 생각해도 이 비실비실한 케이블이 문제를 일으키고 있는 것 아닌가 싶은 의심이 들기 시작했습니다. 이게 원인이라는 확신은 없지만 문제의 원인을 하나 씩 줄여 가기는 해야 했습니다. 이 임시 서버는 다음날 저녁까지 운영되어야 하는데 계속해서 이런 문제를 일으켜서는 안됐습니다. 심지어 지금은 백업도 없는 상황입니다. 재빨리 뛰어 내려가 근처 편의점에서 새 케이블을 사왔습니다. 5A까지 버틸 수 있다고 적혀 있는 새 케이블은 확실히 뭔가 더 튼튼해 보입니다. 도커 데스크탑을 완전히 종료하고 케이블을 교체한 다음 다시 도커 데스크탑을 시작해 모든 스택의 컨테이너들을 재시작합니다. 이제 케이블 교체가 효과가 있는지 알아보는 방법은 그냥 기다리는 것 뿐입니다. 이후 일하며 이 서버에 문제가 생겼었다는 사실을 잠깐 잊었습니다. 모든 것이 약간 굼뜨지만 멀쩡하게 돌아갔습니다. 그러니까 케이블 문제가 맞았습니다. 평소에는 긴 시간에 걸쳐 사용할 일이 없었기 때문에 문제가 드러나지 않았지만 이번처럼 장시간에 걸친 사용에 문제가 드러났습니다. 이후 같은 문제는 다시 일어나지 않았고 약간 걱정되긴 했지만 이전 보다는 훨씬 안정된 편안한 마음으로 술을 마시러 나갔습니다. 서버는 다음 날 저녁 제가 직접 중지하기 전까지 무사히 돌아갔습니다.

분해는 조립의 역순이고 맥미니에서 랩탑으로 옮겼던 홈랩을 다시 맥미니로 옮기는 과정 역시 동일합니다. 랩탑에서 도커 데스크탑을 종료해 컨테이너를 모두 중단한 다음 SSD를 언마운트하고 케이블로부터 분리합니다. 케이블은 서랍에 넣고 비실비실한 케이블은 버리기로 결정합니다. SSD를 주머니에 넣고 퇴근합니다. 이번에도 지하철은 지옥같이 밀렸지만 딱히 주머니에 들어있는 SSD에 문제가 생길 만한 상황을 겪지는 않았습니다. 집에 도착하자마자 SSD를 꺼내 맥미니에 연결하고 전원을 켭니다. 로그인 하고 방금 연결한 SSD를 포함한 백업 스토리지들이 마운팅 되는 모습을 파인더를 열고 지켜봅니다. SSD가 마운트 되자마자 도커 데스크탑을 실행했고 잠깐 기다리자 컨테이너들이 모두 멀쩡하게 동작하기 시작합니다. 타임머신과 ArqBackup이 돌아가는 것을 확인하자 지난 이틀에 걸친 정전 대응이 마무리되었습니다. 랩탑으로 옮겨 갈 때는 약 50분, 다시 맥미니로 돌아올 때는 약 80분에 걸친 다운타임이 발생했습니다. 다른 사용자가 있는 서비스에는 각각 점검 공지를 해야 했고 지하철을 타고 이동하는 동안 제 상황을 말할 곳조차 없어졌다는 사실을 받아들여야만 했습니다. 홈랩의 부재는 n8n을 통한 지라 태스크 자동화, 현재 사용 중인 소셜 네트워크 서비스인 hollo 등을 함께 없애기 때문에 홈랩이 없으면 이 사실을 징징거리며 사람들에게 말할 서비스도 사라지고 제 지라에 날짜나 이메일, 다른 정보를 보고 할 일을 만들어 주지도 않아 멍청한 제가 그나마 사람 구실을 할 수 있도록 도와주던 할 일 목록도 사라져버립니다. 이런 상황이다 보니 홈랩을 안정적으로 유지하는 것은 굉장히 중요합니다. 원래 중요하다는 점을 이해하고 있었지만 이번 정전 대응을 하며 이 점을 훨씬 더 절실하게 깨달았습니다.

앞서 살펴본 전기안전관리법 시행규칙에 따르면 다음 예정된 정전은 약 3년 후에 일어나게 됩니다. 그 때는 어떻게 대응해야 할까요. 이제 다음 번에는 같은 상황에 다운타임을 거의 없애는 방법을 시도해 보려고 합니다. 앞서 홈랩을 맥미니에서 랩탑으로 옮겨 배터리로 단전 동안 버티는 시나리오를 검토했습니다. 사실 랩탑으로 그 정도 시간을 버티는 것은 딱히 어렵지 않을 것 같습니다. 하지만 단전에 의해 인터넷이 없어지는 문제는 제가 어떻게 한다고 해서 해결되는 문제는 아닙니다. 하지만 다음에는 그 시간 동안 모바일 네트워크의 테더링을 통해 인터넷 연결을 유지해 볼 작정입니다. 어쩌면 제가 사용하는 가격이 제일 싼 가정용 인터넷보다 성능이 더 좋을지도 모릅니다. 테더링을 제공하는 태블릿도 배터리로 구동되므로 단전 상황에서도 인터넷 연결을 제공할 수 있습니다. 만약 이들 각각의 배터리가 몇 시간 동안을 버텨내지 못할 것을 염려한다면 랩탑과 태블릿 각각에 외장 배터리를 연결해 두면 조금 더 긴 시간 동안 버틸 수 있을 겁니다. 물론 맥미니의 220볼트 플러그를 직접 연결할 수 있는 UPS 장비나 요즘에는 캠핑용 대용량 배터리를 사용할 수도 있지만 가정용 장비의 범위 기준을 너무 많이 초과하는 것 같아 거기까지는 가지 않으려고 합니다. 트래픽을 많이 사용하지만 절실하지는 않은 몇몇 서비스를 중단해 놓으면 충분히 버틸 수 있을 겁니다.

이번 정전 대응으로 배운 점은 M1 프로세서가 아직도 매우 강력해 M4 프로세서가 하던 일 상당 부분을 여전히 잘 수행해 낸다는 것입니다. 물론 로컬에서 구동하던 대규모 언어모델을 통한 요약과 태깅, 원격에서 안전한 브라우징과 메시징에 사용하는 webtop 같은 더 강력한 프로세서와 많은 메모리를 요구하는 서비스는 처음부터 실행하지 않았지만 이들을 제외하면 나머지 자잘한 웹서비스, 퍼포스 서버 등을 운영하는데는 처음 출시되고 나서 이제 5년이 흘렀지만 여전히 쓸만합니다. 또 좋은 케이블을 써야 하고 좋은 케이블을 사용하지 않을 때의 댓가는 이렇게 오랜 시간에 걸쳐 데이터를 전송해야 하는 중요한 일을 할 때 치르게 된다는 점을 배웠습니다. 그리고 아무리 임시 환경이라도 백업이 없으면 위험한 상황에 처할 수밖에 없다는 점, 그리고 sqlite가 깨질 경우에 대비해 이를 복구할 적절한 도구를 서버에 미리 준비해 놓아야 한다는 점, 그리고 postgres의 WAL은 대부분의 상황에서 데이터베이스를 더 안정적이고 확장성 있게 유지하는데 도움을 주지만 종종 WAL 스스로가 깨져 데이터베이스 시작을 방해할 수 있다는 점도 배웠습니다. 물론 이는 방해라기보다는 데이터베이스를 안전하게 유지하는데 초점을 맞춘 동작이라고 생각합니다. WAL에 문제가 있지만 그래도 서비스를 시작해 데이터베이스에 쓰기 동작들을 수행했다가 문제가 악화되는 것 보다는 나은 동작일 것임에 분명합니다. 어쨌든 데이터베이스가 깨진 상황에 대비해야 합니다. 혹은 지난 퍼포스 서버 데이터베이스 오류 문제해결 때처럼 파일을 덮어 쓴 다음 그냥 아무 일도 없었던 것처럼 행동할는지도 모릅니다. 이번에도 아마 백업이 있었다면 그렇게 행동했을 겁니다.

돈이 없어 데이터센터에서 온프레미스로 서버를 옮겨 온 다음 가정집에서 서버를 안정적으로 유지하기는 꽤 어렵다는 점을 차츰 배우고 있습니다. 이쯤 되면 클라우드 서비스가 왜 비싼지 조금은 이해할 수 있을 것 같기도 합니다. 하지만 돈을 훨씬 더 많이 벌지 않는 이상은 가정용 인터넷과 가정용 전력망에 의존한 홉랩 운영은 계속될 겁니다. 문제를 해결하는 것은 재미있지만 다른 한편으로는 인프라 유지에 매몰되지 않고 서비스 사용에 집중했으면 하는 아쉬움도 있습니다. 언젠가 데이터센터로 다시 옮기고 전력이나 네트워크 같은 문제에 신경 끌 수 있으려면 열심히 일해야겠습니다.