반응형

- 딴데 올려놨다가 잘 안 뜨길래 셀프렉카 해왔음.

- 기술적인 이야기지만 최대한 풀어쓰려 노력했음.

- 내가 틀린 부분이 있을 수 있음. 있으면 고쳐주십쇼.

- 렉카/유튜버/기자 환영합니다. 아래 내용은 CC BY 2.0 KR로 풀겠습니다: '한 네티즌'이 했다고만 해주시면 자유롭게 쓰실 수 있습니다.

 


코로나19 예방접종 사전예약 시스템.

전국의 교육·보육 종사자(돌봄 인력 포함)들의 대가리를 깨버린 시스템.

50~54세와 그들의 자녀와 손자들의 대가리를 깨버린 시스템.

 

도대체 시스템을 어떻게 만들었길래 펑펑 하고 터지는 걸까?

그걸 갖고 썰을 한 번 풀어보려 한다.

 


우선 대한민국 시스템의 방패이자 병폐인 넷퍼넬(NetFUNNEL)에 대해 알아볼 필요가 있다.

아마 이런 화면을 여러번 봤을 것이다.

 

그림 1. 백신 예약 시스템 접속할 때 뜨는 대기화면

 

'서비스 접속대기 중입니다', '앞에 몇 명', '뒤에 몇 명'(선택), '재접속하면 대기시간이 더 길어집니다.'

 이 4개의 구성요건이 모두 성립하는 대기화면. 분명히 이곳저곳에서 이런 화면을 봤을 것이다. 명절 기차표 예약, 백신 예약, 수강신청, 연말정산, 티켓팅, 어디에도 있는 이런 화면을 한번쯤 봤을 것이다.

 

 이 서비스의 이름이 넷퍼넬이다(국내에 유사한 다른 서비스가 없는 거로 알고 있다).

넷퍼넬 서비스를 이용하면, 어떤 시스템 앞에 쉽게 대기열을 붙일 수 있다.

시스템을 정말 못 만들어서 잘 터지거나, 사람이 뒤지게 많이 들어올 것으로 예상되는, 그런 서비스 앞에 대기열을 붙여놓으면, 어느 정도 효과가 있다.

 


그러면 백신 예약 시스템을 보자. 7월 14일, 그러니깐 교육·보육 종사자(돌봄 인력 포함) 대상으로 예약할 때이다.

 

그림 2. 7월 14일 기준 서버 구조 모식도.

 

대충 그려놨지만, 그래도 한번 더 글로 설명하면,

 

  1.  사용자가 백신 예약 서버에 접속한다.
  2.  백신 예약 서버는 사용자에게 '대기열 서버에 가서 줄 서고 올 것'을 지시한다.
  3.  사용자가 대기열 서버에 접속한다.
  4.  긴 시간이 지나면 대기열 서버는 사용자에게 '너 줄 다 섰다'고 알려준다.
  5.  사용자가 백신 예약 서버에 접속하고, '나 줄 다 섰다'고 알려준다.
  6.  백신 예약 서버가 사용자에게 백신 예약 화면을 보여준다.

대충 이렇다.

 


이 구조에는 세 가지 문제가 있었다.

 

첫째, 사용자가 구라를 칠 가능성이다. 그러니깐, 대기열 서버를 패싱해버리는 상황 말이다.

 

그림 3. 사용자가 구라를 치는 경우.

 

사용자가 줄 다 섰다고 서버에 구라를 치는 경우, 이 구조에서는 백신 예약 서버가 그걸 걸러낼 방법이 없다.

인터넷에 떠돌던 우회 방법 중 '어떤 코드를 입력하면 뚫린다' 중 일부가 여기에 해당한다.

 

 

둘째, '나 줄 다섰어' 라는 신호를 제대로 처리하지 않았다.

 

브라우저에는 Referer라는 개념이 있다. 쉽게 말해 '이 사이트로 넘겨준 사이트의 주소'를 알 수 있게 해주는 것이다. 예를 들어보면,

 

 

  • 내가 구글에 네이버를 검색해서 네이버로 들어온다.
    => 이러면 네이버에서 볼 수 있는 Referer는 구글이다. 구글 검색창에서 링크를 타고 네이버로 넘어왔기 때문이다.
  • 내가 주소창에 직접 www.naver.com을 쳐서 네이버로 들어온다.
    => 이러면 네이버에서 볼 수 있는 Referer는 빈칸이다. 어떤 링크를 탄 것이 아니라. 직접 네이버로 넘어왔기 때문이다.

 

백신 예약 서버는, 좀 더 상세히 다음과 같이 작동한다.

 

  1. 대기열 페이지의 경우, 사용자에게 줄을 선 뒤, 줄을 다 서면 예약 페이지로 넘어가게 한다.
  2. 다른 모든(예약, 의료기관 찾기, 조회) 페이지의 경우,
    1. Referer가 빈 칸이면(즉, 주소창에 주소를 치고 바로 넘어왔으면) 대기열 페이지로 넘겨준다.
    2. Referer에 뭔가 있으면(즉, 어딘가에서 일단 넘어왔으면) 화면을 정상적으로 불러온다. 

이게 왜 문제가 됬을까?

그림 4. 구글 뒷문

 

알파고가 의료기관 찾기 페이지를 떡하니 링크시켜놨기 때문이다.

이 경우 의료기관 찾기 페이지로 넘어가면, Referer가 구글이다. 빈칸이 아니므로, 정상적으로 의료기관 찾기 페이지가 로딩된다.

거기에서 예약 페이지로 넘어가면 Referer가 백신 예약 서버다. 빈칸이 아니므로 정상적으로 예약 페이지가 로딩된다.

인터넷에 떠돌던 우회 방법 중 '어떤 코드를 입력하면 뚫린다' 중 일부가 여기에 해당한다.

 

 

셋째, 대기열 서버에 접속이 안 될 가능성이다.

 

그림 5. 대기열 서버가 뒤진 경우

 

원래 대기열 서버, 그러니깐 넷퍼넬 자체가 뒤지는 상황은 흔치 않다. 꽤 튼튼하게 지어놨기 때문이다.

근데 만약에, 어떻게 어떻게 터진다면, 어떻게 될까?

 

넷퍼넬의 기본 설정은, '대기열 서버가 연결이 안 되면, 줄 서는 걸 생략한다' 이다.

그렇기 때문에, 만약에, 정말 만약에, 서버가 터진다면,

 

그림 6. 살수대첩

 

줄 서고 기다리던 10만명이, 마치 살수대첩처럼, 물밀듯이 백신 예약 서버에 접속하게 된다. 당연히 백신 예약 서버는 터질 것이다.

이래서 역사를 배워야 하지 않나 싶다.

 

다행히도 이번에는 대기열 서버가 터지지는않았다. 대신에 그런 얘기 들어본 적 있지 않은가?

 

'3초 정도 비행기 모드를 켜놨다 끄면 접속이 된다.'

 

비행기 모드를 켜면 대기열 서버에 접속이 안 된다. 그래서, 대기열 서버가 죽은 것으로 판단하고 백신 예약 서버로 넘어가게 된다.

그 때 비행기 모드를 끄면, 백신 예약 서버에 접속이 되는 것이다.

 


이 구조 때문에 대기열로 인한 효과가 그리 좋지 못했다.

아니 근데 그렇다 해도 서버가 그렇게 맛이 가는게 말이 되는가? 뚫는 사람은 소수일텐데?

 

사실 이유가 더 있다.

사이트를 좀 바보같이 만들었거든.

 

내가 실험해보니깐, 줄 다 서고 예약 페이지 들어와서 본인인증하기 직전까지,

웹페이지의 사이즈가 4 MB 이다.

4 MB 를 얕잡아보면 안된다. 10만명이 접속하면 400 GB 이다. 서버에서는 파일을 수십만 번 불러오고 보내주면서, 동시에 본인인증 처리하고, 백신 접종 되는 의료기관 찾아주고, 맞는 시간 찾아주고 예약 처리까지 하면서 문자까지 보내줘야 한다. 할 일이 뒤지게 많은 것이다.

 

도대체 어떻게 사이트를 만든 걸까? 기술적으로 말이 길어질 수 있기 때문에 생략하겠지만, 전반적으로 코드가 너무 무겁고, 쓸데없는 내용도 굳이 포함하고 있다.

 

그리고 사이트 개발자에게 진짜 궁금한 것. 사이트 예쁘게 만들고 싶은 건 이해하지만, 그렇다고 0.6 MB 에 달하는 폰트를 굳이 가져다 쓸 필요가 있을까? 부하를 15%나 줄일 수 있을텐데?

 

그림 7. 예쁜 폰트 (0.6 MB)

 

원래 정적(static)인, 즉 내용이 변하지 않는 것들은 CDN이라고 해서, 다른 서버에 집어넣는 게 국룰이다. 그래야 서버가 받는 고통을 조금이라도 덜어줄 수 있기 때문이다.

근데 그걸 분리하지 않고 같은 서버에서 처리했다. 그러면 서버가 몇 MB짜리 내용을 계속 사용자에게 보내야 된다.

 

그렇게 파일들을 계속 보내고 있으니깐, 네트워크 대역폭을 다 써버리게 된다. 이 사용자가 파일을 보내달라고/본인인증을 처리해달라고/서울특별시에 어떤 구가 있는지 찾아달라고/여기 의료기관 찾아달라고/예약 시간 확인해달라고/예약해달라고 해도, 답을 보내려고 하니 이미 다른 사용자에게 답장을 보내고 있느라 이 사용자에게 바로 답을 보내주지 못한다.

 

그래서 페이지 한 번 로딩할때마다 1분 넘게 걸렸던 것이다.

 


7월 19일. 53~54세 대상 예약 시즌.

 

지난 시간의 고통에서 조금이라도 배운 게 있던 것 같다. 몇 가지를 고쳤다.

 

첫째, 사용자가 구라를 치기 조금 어려워지게 만들어놨다.

 

코드를 살짝 정교하게 바꿔놨다.

그래도 3줄 코드 안에 우회가 되긴 한다.

 

 

둘째, '나 줄 다섰어' 라는 신호를 어느 정도 처리하게 됬다.

 

Referer 안에 'kdca.go.kr'가 포함되어 있어야 줄을 서고 넘어온 것으로 판단하게 되었다.

물론 근본적인 해결책은 아니지만(이걸 쓰면 2줄 코드 안에 우회가 된다), 구글 뒷문은 막혔으니 어느 정도 일은 한 셈이다.

 

*발표에서 '클라우드로 일부 시스템을 이전'했다고 했는데, 솔직히 이전 안 한 거나 다름없다.

*정확히는, 위에서 말한 '대기열 페이지'만 클라우드로 이전했다. 진짜 부하가 걸리는 예약 페이지는, 전혀 이전하지 않았다.

 


얘네들은 이걸 고치면서 안도했을까?

 

7월 19일에는 서버가 더 성대하게 터졌다. 8시에 예약을 시작한다고 했다가 8시 50분 쯤에 죽어가는 서버를 견디지 못하고 10시로 미뤘다.

 

뭐 예상하긴 했다. 여전히 줄 서는 걸 우회할 수 있었고, 사이트가 너무 무겁고, 근데 사용자는 너무 많고. 충분히 터질만 했다.

근데, 예상 밖의 일이 하나 일어났다.

 

대기열 서버가 터졌다.

 

원래 대기열 서버, 그러니깐 넷퍼넬 자체가 뒤지는 상황은 흔치 않다. 꽤 튼튼하게 지어놨기 때문이다.

근데 이렇게 터져버렸는데, 어떻게 됬을까?

 

넷퍼넬의 기본 설정은, '대기열 서버가 연결이 안 되면, 줄 서는 걸 생략한다' 이다.

그렇기 때문에,

 

그림 8. 살수대첩

 

줄 서고 기다리던 10만명이, 마치 살수대첩처럼, 물밀듯이 백신 예약 서버에 접속하게 됬다. 당연히 백신 예약 서버는 터졌다.

이래서 역사를 배워야 하지 않나 싶다.

 


7월 20일에는 그래도 좀 괜찮았다.

 

근본적으로, 사용자가 제대로 줄을 섰는지 백신 예약 서버가 대기열 서버에 확인하는 매커니즘이 이제야 추가됬기 때문이다.

'이제야'라고 굳이 붙이는 이유는, 넷퍼넬이 원래 제공하는, 쓰기만 하면 되는 기능을 이제야 추가했기 때문이다.

 

7월 20일에 오류 때문에 시끄러웠던 까닭은 두 가지이다.

첫째, 사용자들이 접속해 있는데 코드를 막 뒤집어 엎어서 그렇다.

아까 말한 매커니즘은 8시 30분에서 9시 사이에 추가됬다. 그 전에 줄 서서 쭉 기다리고 통과한 사람들의 경우, 줄이 다 끝난 뒤 그대로 나가리됐다.

둘째, 그냥 사이트가 버그가 있었다. 이건 근데 잘 몰라서 생략하겠다.

 

사이트는 여전히 무겁다. 그래서 아직 느린게 아닐까. 그래도 전보다는 괜찮다. 우회하는 사람이 적어서 그런 것 같다.

 


아 제발 진짜 좀.

 

만든 사람을 욕하는 건 아니다. 그 사람도 매일 8시에 야근하면서 당연히 터질 서버를 어떻게 고쳐야 할지 머리를 싸매고 있을 것이다.

그 사람이 개발 못 하는 건 맞다. 그러나 불쌍하다. 하고 싶었겠는가, 소속된 회사가 하청 받았으니까 하는거겠지.

 

그래도 2시간 동안 예약을

여러번 하고 있으니깐

빡치는건 어쩔 수 없다.

 

아 제발 진짜 좀.

개드립 - (정성글) 백신예약 서버가 터지는 이유에 대한 상세한 해설 ( https://www.dogdrip.net/338552744 )

반응형
by 밑바닥에서 글로벌로~ 발전소장 에르 :) 2021. 7. 21. 14:42