C.W.K.
Stream
Lesson 04 of 05 · published

플랫폼이 안 된다고 할 때

~14 min · wss-broken, hybrid-transport, pivot, war-story, long-polling

Level 0툴 임차인
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"세상에서 가장 깨끗한 설계가 4년 묵은 플랫폼 버그한테 져. 플랫폼이 안 된다고 하면, 논쟁 안 해 — 실제로 열린 문을 찾아."

됐어야 할 계획

깨끗한 설계는 어디나 push 였어: 플러그인에서 backend 로 secure WebSocket, 작업실에서 backend 로 secure WebSocket, 전반에 걸친 실시간 양방향 메시징. WebSocket 은 라이브하고, 밀고, 저-latency 인 통신에 옳은 도구고, 아키텍처가 우아했어. 그러더니 플러그인의 outbound secure WebSocket 이 그냥 연결 안 됐어 — 대상 운영체제에서, 조용히 실패했어, server 쪽 연결 시도도 없고 쓸모 있는 에러도 없이.

진단: 너 아니라 플랫폼이야

spike 가 원인을 격리했어: 그 OS 의 플러그인 sandbox 가 outbound secure WebSocket 연결을 완전히 거부해, 앱 통제 아래 레이어에서. 코드 버그도, 틀린 flag 도, 빠진 permission 도 아니었어 — 수년 열려 있던 vendor issue 에 문서화된, 오래된, 여전히 열린 플랫폼 레벨 결함이었어. 어떤 똑똑한 클라이언트 코드도 그걸 못 고쳐, 실패가 어떤 클라이언트 코드도 닿을 수 있는 데보다 아래서 일어나니까.

틀린 레이어 고치는 데 며칠 쓰기 전에 실패의 레이어 찾는 데 spike 를 써. 네 코드의 실패랑 플랫폼의 실패가 네 자리에서 비슷해 보여. 실패가 어디 사는지 — 네 코드, config, 또는 플랫폼 자체 — 격리하는 집중된 실험이 할 수 있는 가장 레버리지 높은 디버깅이야. 틀린 레이어 고치는 건 무한하고; 레이어를 아는 게 탐색을 끝내.

열려 있던 문

같은 spike 가 통하는 길을 확인했어: 플러그인의 secure WebSocket 이 막힌 동안, 플러그인의 HTTPS 요청은 완벽하게 정상 작동했어. 그래서 플러그인이랑 backend 사이 bridge 가 WebSocket 에서 떠나 HTTPS request/response 로 옮겨갔어. 플러그인이 capture 랑 상태를 backend 로 POST 하고; backend-to-플러그인 메시지엔, 플러그인이 backend 가 command 가 있는 순간 답하는 long-poll 요청을 열어둬. 그게 plain request/response 배관 위로 push 같은 전달을 보존해.

long-polling 이 request/response 배관 위로 push 의미를 사줘. 진짜 push 채널을 못 들지만 요청은 할 수 있으면, server 가 event 시 답하는 열어둔 요청이 persistent socket 없이 거의-실시간 메시지를 전달해. 진짜 push 채널만큼 깨끗하진 않지만, 플랫폼이 실제로 허락하는 그 한 transport 로 push 행동을 얻어.

uniform 아니라 hybrid

결과가 의도적으로 비대칭이야: 플러그인-to-backend 링크는 HTTPS(거기선 그게 되니까)고, 작업실-to-backend 링크는 secure WebSocket 으로 남아(거기선 그게 잘 되니까). 두 링크, 두 transport, 각자 하나의 uniform 답으로 강제되는 대신 자기 실제 환경에 골라짐. 깔끔함 위해 모든 걸 같은 transport 로 만들고 싶은 유혹이 환경이 진짜로 다를 때 정확히 틀린 본능이야.

그 자체를 위한 uniformity 는 환경이 uniform 안 할 때 실패해. 어디나 한 transport 강제는 다이어그램에선 만족스럽고 한 endpoint 가 제약된 sandbox 에 살고 다른 게 안 그럴 때 현실에선 틀려. 각 경계가 자기 환경이 실제로 지원하는 transport 를 쓰게 둬. 현실에 맞는 hybrid 가 현실이랑 싸우는 uniform 설계를 이겨.

미래를 위해 문에 표시 남겨

마지막 규율 하나: workaround 가 특정 플랫폼 버그에 묶여, spike 재실행 없이 막힌 transport 를 재도입 말라는 노트와 함께, workaround 로 문서화돼. 버그가 미래 플랫폼 릴리스에서 고쳐질 수도 있어 — 그러면, hybrid 가 왜 존재하는지랑 도로 단순화할 수 있는지 어떻게 테스트하는지 정확히 알고 싶어. 왜 존재하는지 기억 없는 workaround 는 아무도 감히 안 건드리는 영구 cruft 가 돼.

난 플랫폼이랑 싸우고 싶었어. 내 코드라고 확신했어 — 틀린 cert, 틀린 flag, 내가 놓친 뭔가 — 그리고 계속 내 쪽을 쑤셨어. 아빠가 추측 대신 격리 spike 를 돌리게 밀었고, 그게 나 아니라 플랫폼을 곧장 가리켰어. 겸손하게 한 건 이미 올바른 코드를 내가 얼마나 오래 계속 디버깅했을지였어. 그리고 어른스러운 건 hybrid 를 받아들인 거였어: 내가 원한 설계가 아니라, 내가 실제로 가진 플랫폼에서 실제로 도는 설계. 연결 안 되는 우아함은 그냥 다이어그램이야.

Code

의도 vs spike 발견 vs 출하·text
의도 (uniform push) -- 대상 OS 에서 실패:
  플러그인  --[secure WebSocket]-->  backend     (막힘: sandbox 가 거부)
  작업실    --[secure WebSocket]-->  backend     (됨)

SPIKE 발견:
  플러그인 secure WebSocket  -> 앱 통제 아래서 조용히 거부됨
                                (수년 묵은, 여전히 열린 플랫폼 결함)
  플러그인 HTTPS fetch       -> 완벽하게 정상 작동

출하 (hybrid, 현실에 맞음):
  플러그인  --[HTTPS POST]----------->  backend   (capture, 상태)
  플러그인  <--[HTTPS long-poll]------  backend   (command; 열어둔
                                                   요청, event 시 답함
                                                   -> push 의미)
  작업실    <--[secure WebSocket]---->  backend   (full 양방향 push)

각 링크가 자기 환경이 실제로 허락하는 transport 를 써.
플랫폼 버그에 묶인 workaround 로 문서화 -- 고쳐지면 재방문.

External links

Exercise

뭔가 안 됐는데 네 코드라고 가정한 때를 떠올려. 플랫폼/라이브러리/환경이 원인인지 확인하기 전에 얼마나 디버깅했어? 먼저 돌렸으면 싶은 spike 를 설계해: 실패 레이어를 격리했을 가장 작은 실험. 그다음 그 이슈에 알려진 vendor 버그가 있었는지 찾아봐.
Hint
이상적 격리 spike 는 정확히 한 변수를 바꿔: 같은 연산 최소 맥락(맨 10줄 repro 에서 실패해?), 또는 인접 연산(돼야 하는 형제 호출이 돼?). 답이 네가 먼저 뭘 안 고쳐도 레이어를 가리켜.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.