액티브펍 네트워크의 결함 내구성 문제

지난번 짧은 휴가를 마치고 돌아오는 길에 액티비티펍 네트워크의 부하 내구성 문제를 마주쳐 먼 거리를 돌아오는 길이 그리 지루하지 않았다는 이야기를 소개했습니다. 한국어권 액티비티펍 네트워크는 릴레이를 통해 여러 서버가 서로 연결되어 있는데 액티비티펍 서버들은 사용자들의 직접적인 요청에 의한 서버 사이의 통신에 제약이 별로 없지만 서버들이 서로 간접적인 통신을 하지는 않기 때문에 X(구 트위터) 처럼 중앙화된 서비스처럼 다른 사용자를 쉽게 발견하기는 어렵습니다.

특히 한국어권 사용자들은 대대로 이런 작은 서비스를 사용하는데 익숙하지 않아 다른 사용자들을 발견하기 쉽지 않은 특징 때문에 서비스를 사용하기 어려워 하는 것 같아 보입니다. 이런 특징을 완화하기 위해 릴레이 서버라는 것이 있는데 액티비티펍 프로토콜 호환 서비스를 릴레이에 등록하면 각 서버 사용자가 직접 요청하지 않아도 릴레이에 연결된 각 액티비티펍 호환 서비스들로부터 공개된 글을 서로 다른 서버에 항상 전달해 다른 사용자들을 발견하기 쉽게 만들어 줍니다.

그런데 당시 X(구 트위터)가 갑자기 단위 시간 당 사용량을 제한해 서비스를 계속해서 사용할 수 없게 된 사용자들이 갑작스레 액티비티펍 네트워크에 나타났고 이들이 갑자기 쏟아내는 글이 평소의 액티비티펍 네트워크가 감당할 수 있는 양을 한참이나 초과해 네트워크 전체에 문제를 일으킵니다. 규모가 큰 서버는 문제가 두드러지지 않았지만 규모가 작은 서버는 릴레이를 통해 들어오는 페더레이션 타임라인이 늦게 처리되어 실시간으로부터 큰 차이가 나기 시작했는데 제가 겪은 가장 긴 딜레이는 실시간 페더레이션 타임라인으로부터 9시간 차이가 난 것입니다. 9시간 차이 난 상태가 한참이나 지속되자 혹시 이거 협정표준시와 한국표준시 차이로 생기는 문제가 아닐지 의심해봤을 정도입니다.

알고 보니 릴레이에 연결된 모든 서버는 사실 릴레이에 연결된 모든 서버가 릴레이로 뿜어내는 모든 메시지를 처리할 수 있는 처리량을 갖추고 있어야 이렇게 네트워크가 붐비는 상황에 문제를 겪지 않을 수 있었습니다. 평소에 릴레이 서버는 서로 떨어져 있어 직접적인 요청을 통한 통신 외에는 서버 간에 사용자를 발견하기 어려운 액티비티펍 네트워크의 특징이자 단점을 보완해 주지만 지난번 처럼 네트워크 사용량이 갑자기 늘어나는 상황에서는 한 서버의 사용량 증가를 릴레이에 연결된 모든 서버로 전파하는 일종의 DDoS 역할을 하게 됩니다.

개인적으로 이런 현상은 액티비티펍 프로토콜의 설계 결함이라고 생각합니다. 페더레이션에는 크고 작은 여러 규모의 서버가 있을 수 있는데 이들이 릴레이에 묶여 있다면 좋은 생각은 아닌 것 같지만 처음부터 릴레이 전체의 처리량을 견딜 수 있어야 한다는 제한을 걸거나, 릴레이에 묶인 서버 중 일부의 사용량이 늘어나더라도 이를 곧이곧대로 릴레이에 연결된 모든 서버에 전파하는 대신 우선순위를 매겨 릴레이에서 처리할 수 있는 수준으로 트래픽을 조정하는 메커니즘이 당연히 필요하다고 봅니다. 가령 한 서버에서 릴레이에 메시지를 보내기 전에 릴레이에 연결된 다른 서버로부터 직접 팔로잉 관계에 있는 계정의 메시지를 우선 처리한다든지 하는 식으로 이전 사용자들의 사용 경험을 망가뜨리지 않는 선에서 중요한 메시지를 우선 처리하고 나머지 메시지는 전체 네트워크 사용량이 감소할 때 릴레이를 통해 전송해 부하 상황을 완화할 수 있지 않을까 싶었습니다.

한편 이 일을 겪고 나서 시간이 좀 지난 다음 이번에도 비슷한 상황을 겪었습니다. 지난번 페더레이션 타임라인이 실시간으로부터 멀어지는 상황을 겪은 다음부터 페더레이션 타임라인이 실시간에 얼마나 가까운지, 실시간이기는 한지를 이전보다 더 주의 깊게 살펴보고 있었는데 무심코 눌러본 페더레이션 타임라인이 실시간보다 늦고 있었습니다. 지난번과 같은 상황일 거라고 생각하고 메시지 큐를 열어보니 이번에도 메시지 큐에 많은 메시지가 처리되지 않은 상태로 남아 있었는데 다른 서버 관리자님들의 반응을 보니 이번에는 지난번 처럼 갑작스런 사용자 증가로 인한 문제가 아닌 것 같아 보입니다. 확실히 지난번에는 페더레이션 타임라인에 액티비티펍 서비스를 처음 사용해 보는 것 같은 분들의 글이 끝없이 나타났지만 이번에는 다른 때와 별로 다르지 않은 타임라인인데도 문제가 일어나고 있었습니다.

그래서 당장 뭘 하기보다는 다른 서버 관리자 분들이 올리시는 글을 살펴보고 있었는데 이번에는 아마도 특정 액티비티펍 호환 소프트웨어의 특정 버전이 문제를 일으키고 있는 것 같았습니다. 그 소프트웨어는 평소에도 소스 관리가 잘 안 된다고 알고 있었습니다. 호기심에 눌러 본 깃헙 리파지토리에 적힌 여러 코멘트는 이게 정말 수많은 사람들이 의존하는 오픈소스 소프트웨어가 맞는지 의심스러울 정도로 엉망이었는데 코드를 만드는 분들의 의식의 흐름에 따라 수정된 코드가 그냥 한 커밋에 우르르 올라와 있었고 이 코드가 무엇을 어디까지 수정 했는지에 대한 정보를 얻을 수가 없었습니다. 또 가끔 이 소프트웨어는 메이저 업데이트를 할 때 이전 버전에서 사용하던 환경이나 인프라를 무시하기도 하는 것 같았는데 가령 자세한 설명 없이 이전 버전에서 사용하던 데이터베이스 스키마를 변경한다든지 주요 스크립트의 경로를 변경한다든지 해서 별 생각 없이 메이저 업데이트를 따라갔다가 서비스 장애를 겪곤 하는 것 같아 보입니다.

하지만 어째서 인지 이 소프트웨어는 한국어권 액티비티펍 네트워크의 인기 있는 여러 서버를 운영하는데 활용되고 있습니다. 또 이 서비스는 액티비티펍 호환 소프트웨어라고 하기에는 종종 다른 액티비티펍 호환 소프트웨어와 호환되지 않는 기능을 추가하기도 했는데 이런 경향 때문인지 이 소프트웨어를 통해 서버를 운영하시는 관리자님들은 종종 이 소프트웨어의 근본이 액티비티펍 네트워크 호환 소프트웨어라는 점 보다는 단일 서버에 의미있는 기능을 추가한다는 관점에서 다른 서버에서 볼 때 오동작 하거나 아예 보이지 않는 기능을 추가하는데 깊은 고민을 하시지는 않는 것 같아 보였습니다.

새롭게 등장한 페더레이션 타임라인이 실시간으로부터 멀어진 원인은 바로 그 소프트웨어의 한 버전에서 예외 처리를 부주의하게 한 코드가 릴레이를 통해 메시지를 보내지 않아야 하는 상황에서 빈 메시지를 릴레이에 보내는 동작을 했기 때문인 것 같았습니다. 이런 문제에 굉장히 빠른 대응을 하시던 한 서버 관리자님은 상황을 파악하고 이미 그 소프트웨어 리파지토리에 찾아가 문제를 일으키는 코드와 그 코드를 포함한 커밋을 살펴보고는 그 부주의함에 당혹스러워 하고 계셨고 이 문제를 전달 받은 다른 서버 관리자님들은 공식 업데이트가 올라오기 전에 각자가 코드를 수정해 문제가 일어나지 않도록 하고 있었습니다. 하지만 모든 서버 관리자가 이런 대응을 할 수 있는 것은 아니어서 몇몇 서버는 이 문제를 계속해서 일으켰지만 공식 업데이트가 나오기 전에는 손 쓸 수 없는 상태로 남아있기도 했습니다.

페더레이션 타임라인이 실시간으로부터 지연되고 있었지만 지난번처럼 뭔가 대응을 하기도 뭣하고 안 하기도 애매한 상황이었는데 고작 액티비티펍 네트워크 호환 소프트웨어 특정 버전의 오동작에 대응하기 위해 서버 처리량을 늘리고 메시지 큐에 쌓인 저 잘못된 메시지를 삭제하는 대응을 하는 것도 썩 좋은 생각은 아닌 것 같았습니다. 무책임하지만 ‘얼른들 고치세요’ 라고 생각한 다음 아무 대응도 하지 않았고 시간이 좀 지나자 한국어권에 이 소프트웨어를 사용하는 주요 서버가 문제를 해결한 듯 페더레이션 타임라인은 다시 실시간을 유지하기 시작합니다. 이 소프트웨어의 공식 배포처로부터 문제를 해결한 버전이 배포되었다는 링크를 본 것은 문제가 어느 정도 해결된 다음의 일이었습니다.

개인적으로 나쁜 선입견이 있는데 특히 특정 국가에서 만들어진 오픈소스 소프트웨어는 뭔가 완성도가 충분하지 않아 서비스에 사용하기에는 문제가 많다는 겁니다. 분명 모든 소프트웨어가 그렇지 않다는 사실을 너무나 잘 알고 있습니다. 그런데 부주의한 코드 관리와 가까운 미래조차 잘 내다보지 않고 또 너무 가까운 기능 추가에 집중한 업데이트는 이 소프트웨어들의 완성도를 떨어뜨리고 액티비티펍 네트워크처럼 서로 다른 여러 소프트웨어가 서로 영향을 주고 받는 상황에서 ‘주로' 문제를 일으키곤 해서 좋은 인상을 받기 어려웠습니다. 이번에도 소스 리파지토리에서 본 몇몇 커밋 로그가 상당히 충격적이어서 이런 나쁜 인상을 개선하기는 당분간 쉽지 않을 것 같습니다.

또 이 소프트웨어로 서비스를 운영하시는 분들은 종종 직접 코드를 수정해 새로운 기능을 추가하거나 코드를 트윅해 그 서버만의 특징을 만들곤 하셨는데 이런 트윅은 대체로 무해하지만 가끔 우연히 본 코드가 코드를 전문적으로 만들지 않는 문외한이 봐도 보안 상 문제가 있을 수 있어 보일 때가 있어 걱정스러울 때도 있습니다. 또 중장기적으로 이런 트윅들이 최신 업데이트를 쉽게 적용하지 못하게 만드는 원인이 되기도 하는데 그 업데이트가 심각한 보안 문제에 대응하는 업데이트라면 이를 적용하기 어렵게 만드는 트윅은 상황을 복잡하게 만들 수 있습니다. 이상적으로는 이런 트윅들을 핵심 코드와 분리할 일종의 플러그인 시스템이 필요하겠지만 이 리파지토리의 지난 역사를 돌아볼 때 그런 걸 만들어낼 수 있을지 걱정스럽습니다. 내가 할 걱정은 전혀 아니지만요.

문제는 특정 액티비티펍 호환 소프트웨어의 특정 버전이 일으키기는 했지만 근본적으로 이 에피소드 역시 액티비티펍 프로토콜의 설계 결함이라고 생각합니다. 딱히 표준을 통제하지 않고 또 각 소프트웨어의 표준 준수 여부나 결함 여부를 누군가 통제하지 않는 분산 환경의 특성 상 프로토콜 수준에서 특정 소프트웨어의 결함 여부에 관계 없이 네트워크가 안정적으로 동작할 수 있는 프로토콜이 필요하다고 생각합니다. 네트워크에 참여한 누군가가 갑자기 이상한 빈 메시지를 대량으로 릴레이에 전송하더라도 릴레이 수준에서 이상을 감지하고 이를 릴레이에 연결된 나머지 서버로 전송하지 않거나 애초에 릴레이 서버로 메시지를 보내기 전에 이 메시지가 멀쩡한지 검사하는 과정이라도 있었다면, 이런 과정이 프로토콜 수준에 정의되어 있었어야 합니다. 네트워크에 참여하는 모든 사람들은 소프트웨어에 전문가가 아니고 이는 심지어 액티비티펍 호환 소프트웨어를 만드는 장본인들 역시 마찬가지일 수 있습니다. 이런 현실을 고려하면 액티비티펍 프로토콜에는 결함 내구성이 충분하지 않다고 볼 수 있습니다.

최근에 여러 트윅을 하시는 한 서버 관리자님의 ‘굳이 다른 액티비티펍 소프트웨어와 호환성을 갖춰야 할까?’ 하는 의문을 포함한 글을 보고 어쩌면 이런 결과는 그 소프트웨어를 선택하고 사용하는 분들께 자리 잡은 일종의 문화일 수도 있겠다는 생각이 들었습니다. 사실 서버 단위에서 기능을 추가하고 코드를 트윅해 재미 있는 기능을 제공하는 건 완전 신나고 재미있는 일입니다. 다만 그 서버가 액티비티펍 네트워크의 일부라는 점을 감안하면 약간 거슬릴 수 있고 또 위에서 잠깐 언급한 제대로 된 이른바 플러그인 시스템이 없는 코드 위에서 주의 깊지 않게 작성된 코드는 보안 업데이트 같은 긴급 수정 상황을 필요 이상으로 복잡하게 만들 수 있어 조금 걱정이 되긴 하지만요.

결론. 액티비티펍 프로토콜은 지난번에는 일시적인 부하에 대한 내구성이 부족해 보이는 경험을 하게 했고 이번에는 네트워크 상의 결함이 있는 서버의 오동작에 대한 내구성이 부족해 보이는 경험을 했습니다. 근본적인 원인은 액티비티펍 프로토콜 자체에 있다고 생각합니다. 이상적으로는 모두가 온전한 코드를 만들고 모두가 온전한 서비스를 하는 것이겠지만 환경이 분산 될수록 그런 이상적인 상태로부터 멀어질 수밖에 없으며 이는 오롯이 프로토콜 스스로가 감당해야 합니다.