"세상에서 제일 깨끗한 설계도 아무도 안 고쳐 줄 플랫폼 버그한테는 져. 플랫폼이 안 된다고 하면 따지지 마. 실제로 열려 있는 문을 찾아."
됐어야 할 계획
깨끗한 설계는 전부 밀어 주는 방식이었어. 플러그인에서 backend 로 secure WebSocket, 작업실에서 backend 로 secure WebSocket, 전체에 걸쳐 실시간 양방향. WebSocket 은 살아 있고 밀어 주고 지연이 짧은 통신에 맞는 도구고, 아키텍처도 매끄러웠어. 그런데 플러그인에서 밖으로 나가는 secure WebSocket 이 아예 연결이 안 됐어. 그 운영체제에서, 조용히, server 쪽에 연결 시도 흔적조차 없이, 쓸 만한 에러 하나 없이.
진단: 네가 아니라 플랫폼이야
짧은 실험 하나가 원인을 짚어 냈어. 그 OS 의 플러그인 sandbox 가 밖으로 나가는 secure WebSocket 연결을 통째로 거절하고 있었어. 앱이 손댈 수 없는 층에서. 코드 버그도 아니고, 플래그를 잘못 준 것도 아니고, 권한이 빠진 것도 아니었어. 플랫폼 층위의 거절이었고, 실험을 마지막으로 다시 돌렸을 때까지도 안 고쳐져 있었어. 아무리 똑똑한 클라이언트 코드로도 못 고쳐. 실패가 클라이언트 코드가 닿을 수 있는 데보다 아래에서 일어나니까.
열려 있던 문
같은 실험이 통하는 길도 확인해 줬어. 플러그인의 secure WebSocket 은 막혀 있는데, 플러그인의 HTTPS 요청은 멀쩡히 됐거든. 그래서 플러그인과 backend 사이 다리를 WebSocket 에서 떼어 HTTPS 요청/응답으로 옮겼어. 플러그인이 떠 온 것과 상태를 backend 로 올리고, backend 에서 플러그인으로 가는 메시지는 플러그인이 열어 둔 요청을 backend 가 명령이 생기는 순간 응답해 주는 방식으로. 평범한 요청/응답 배관 위에서 밀어 주는 것 같은 전달을 살린 거야.
통일이 아니라 두 갈래
결과는 일부러 비대칭이야. 플러그인과 backend 사이는 HTTPS 고(거기선 그게 되니까), 작업실과 backend 사이는 secure WebSocket 그대로야(거기선 그게 잘 되니까). 연결이 둘이고 transport 도 둘인데, 하나로 통일하라고 억지로 밀어 넣은 게 아니라 각자 자기 환경에 맞게 고른 거지. 깔끔해 보이려고 전부 같은 transport 로 맞추고 싶은 마음이, 환경이 실제로 다를 때는 정확히 틀린 본능이야.
나중을 위해 문에 표시를 남겨
마지막 규율 하나. 이 우회는 그걸 찾아낸 날짜 붙은 실험에 묶인 우회로 문서에 적어 뒀어. 짧은 실험을 다시 돌리기 전에는 막혔던 transport 를 도로 들이지 말라는 메모도 같이. 그 인용이 뭐가 될 수 있고 뭐가 될 수 없는지는 정직하게 말해 둘 만해. 이건 공개된 버그 번호가 없어. 벤더 tracker 에 같은 권한 쪽 이야기로 오래 열려 있는 항목이 하나 있긴 한데, 거기 적힌 실패는 다른 실패야. 그걸 여기 갖다 붙이면 증거처럼 보이지만 증거가 아니고. 그래서 메모가 묶인 건 우리가 직접 돌린 날짜 붙은 실험이야. 언제, 정확히 뭘 해 봤고, 결과가 뭐였는지. 다시 돌릴 수 있는 실험에 묶인 우회는 누구든 시험해 볼 수 있어. 정작 필요한 말을 안 하는 인용에 묶인 우회는 아무 데도 안 묶인 것보다 나빠. 다음 사람이 거기서 찾기를 멈추거든. 그 버그가 나중 플랫폼 릴리스에서 고쳐질 수도 있잖아. 그러면 이 두 갈래가 왜 생겼고, 다시 단순하게 되돌릴 수 있는지 어떻게 확인하는지 정확히 알고 싶으니까. 왜 있는지 기억이 안 남은 우회는 아무도 감히 못 건드리는 영구 찌꺼기가 돼.