껐던 노트북을 다시 켰습니다 — 막고 있던 것은 성능이 아니었습니다
앞 편에서 설정 한 줄로 18배가 바뀌었습니다. 그러자 6편에서 그 노트북을 껐던 근거가 사라졌습니다. "사양을 올려도 해결되지 않는 구조적 한계"라던 것이 구조적 한계가 아니었기 때문입니다.
그래서 다시 켰습니다. 이번에는 가벼운 작업만 시키는 게 아니라, 진짜 무거운 것 두 개를 맡길 수 있는지 보기로 했습니다. 백엔드 테스트 5,690건과 브라우저를 띄워서 도는 E2E입니다.
표를 적고 멈추지 않기로 했습니다
먼저 막힐 만한 것을 목록으로 만들었습니다. 메모리는 문제가 아니었습니다. 그 노트북은 15.8GB를 갖고 있고, 백엔드 타입 검사가 요구하는 6GB를 충분히 감당합니다. 정작 메모리가 부족해서 배제했던 것은 다른 노트북이었는데, 저는 그 판단을 이 노트북에도 그냥 옮겨 붙이고 있었습니다.
목록을 만들고 나서, 예전 같으면 여기서 "이러이러해서 어렵겠다"로 마무리했을 것입니다. 이 시리즈에서 이미 두 번 그랬으니 이번에는 목록을 검증 계획으로 쓰고 실제로 돌렸습니다.
| 단계 | 시간 | 결과 |
|---|---|---|
| 의존성 설치 | 68.0초 | 성공 |
| 백엔드 타입 검사 | 67.2초 | 성공 |
| 백엔드 테스트 | 363.6초 | 실패 |
| 프론트엔드 빌드 | 133.8초 | 성공 |
| 브라우저 최초 설치 | 64.5초 | 성공 |
| E2E | 4.1초 | 실패 |
마지막 줄을 보고 알았습니다. 4.1초는 느려서 실패한 시간이 아닙니다. 시작조차 못 한 시간입니다.
막고 있던 것은 성능이 아니었습니다
실패 두 건의 원인은 둘 다 성능과 아무 상관이 없었습니다.
첫 번째는 셸 문법입니다. 제 설정 파일 곳곳에 이런 표현이 있습니다.
# "이 값이 비어 있으면 3006을 쓴다" 라는 뜻
next dev -p ${CLIPCO_PORT:-3006}
리눅스와 맥의 기본 셸은 이것을 읽고 값을 채워 넣습니다. 그런데 윈도우의 기본 셸은 이 문법을 모릅니다. 그래서 채우지 않고 글자 그대로 넘깁니다. 서버는 ${CLIPCO_PORT:-3006}이라는 이름의 포트를 열려다 실패하고, E2E는 붙을 서버가 없어 4.1초 만에 죽습니다.
두 번째는 테스트가 경로를 문자열로 단정하고 있었습니다. 5,690건 중 5건이 이렇게 실패했습니다.
Expected: "/tmp/rc-root/rcj_x"
Received: "\tmp\rc-root\rcj_x"
여기서 중요한 것은 실패한 쪽이 코드가 아니라 테스트라는 점입니다. 코드는 운영체제에 맞는 구분자를 알아서 붙여주는 함수를 제대로 쓰고 있었고, 윈도우에서 역슬래시를 내놓은 것은 옳은 동작입니다. 테스트가 "결과는 반드시 슬래시로 시작한다"고 못 박고 있었을 뿐입니다. 리눅스에서만 돌려봤기 때문에 아무도 그 단정이 틀렸다는 것을 알 수 없었습니다.
정리하면 이렇습니다. 저는 이 노트북이 약해서 무거운 일을 못 맡는다고 믿었는데, 실제로 막고 있던 것은 제 코드가 리눅스를 당연하게 전제하고 쓴 문장들이었습니다.
그래서 보류하기로 했습니다
남은 일을 세어보니 셋이었습니다. 워크플로의 셸 지정, 개발 스크립트 세 곳의 문법 교체, 테스트 단정 다섯 건.
가운데 것이 걸렸습니다. 개발자가 매일 쓰는 스크립트를, 쿼터가 바닥났을 때만 도는 예비 러너 한 대 때문에 바꾸는 것이 좋은 거래로 보이지 않았습니다. 게다가 순서가 나빴습니다. 셋을 다 치르고 나서야 마지막 미지수인 E2E 실제 성능을 처음 알게 되는 구조였습니다. 비용은 확정이고 이득은 미지수인 순서입니다.
그래서 "무거운 작업 승격은 보류한다"고 적었습니다. 근거를 정리하고, 표를 만들고, 판단 이유까지 써뒀습니다.
그리고 같은 날 뒤집혔습니다
그 기록을 보고 이런 지적을 받았습니다.
윈도우에서도 bash를 실행할 수 있게 하면 되는 것 아닌가
한 문장이었는데 제 판단 전체가 무너졌습니다.
확인해보니 패키지 매니저는 스크립트를 어떤 셸로 돌릴지도 설정으로 바꿀 수 있습니다. 그리고 앞 편의 레이아웃 설정과 마찬가지로, 이것도 그 기계의 사용자 설정 파일에서 읽힙니다. 저장소는 한 글자도 바뀌지 않습니다.
# 그 러너 기계의 사용자 설정 파일
node-linker=hoisted
script-shell=C:/Users/사용자명/tools/git/bin/bash.exe
게다가 bash는 이미 그 기계에 있었습니다. 윈도우용 git에 딸려 오는 것을 예전에 설치해뒀더군요. 새로 깔 것도 없었습니다.
이 두 줄로 서버가 정상적으로 떴고, E2E가 끝까지 돌았습니다. 그렇게 제가 "미지수라서 계산에 넣을 수 없다"고 했던 마지막 항목의 값이 나왔습니다.
블로커 정산
| 막는다고 본 것 | 처음 판정 | 실측 후 |
|---|---|---|
| 워크플로 셸 문법 | 일곱 군데 개별 수정 | 한 줄 (전체 기본 셸 지정) |
| 개발 스크립트 문법 | 나쁜 거래 | 0줄 (그 기계 설정으로 해결) |
| 브라우저 최초 설치 | 미지수 | 64.5초, 한 번뿐 |
| E2E 실제 성능 | 미지수 | 16.8분 — 느리지만 쓸 수 있음 |
| 테스트 이식성 | 5건 | 7건 (경로 5 + 화면 좌표 2) |
보류 결정의 핵심 근거였던 두 번째 줄이 "나쁜 거래"에서 "0줄"로 바뀌었습니다. 거래 자체가 없어졌으니 저울에 올릴 것도 없어진 셈입니다.
계산은 맞았고, 목록이 틀렸습니다
이 일이 오래 남았습니다. 제 판단 과정에는 산술 오류가 없었습니다. 비용을 세고 이득을 세고 순서까지 따졌습니다. 그런데 저울에 아예 안 올라간 항목이 하나 있었습니다.
저는 "셸 문법을 고친다"만 선택지로 놓고 그 비용을 계산했습니다. "셸 자체를 바꾼다"는 축이 목록에 없었습니다. 없는 항목은 계산에서 0으로 처리되는 게 아니라 아예 존재하지 않으므로, 아무리 정확하게 계산해도 나오지 않습니다.
돌이켜 생각해보면 선택지를 다 나열했다고 믿는 순간이 가장 위험합니다. 계산을 시작하는 순간 목록은 완결된 것으로 취급되고, 그때부터는 아무리 신중해도 빠진 것을 찾을 방법이 없습니다. 이 시리즈에서 저를 구한 것은 매번 신중함이 아니라 외부에서 들어온 한 문장이었다는 생각이 들었습니다.
측정하다 만난 함정 하나
덧붙여 둘 것이 있습니다. 이 설정들이 먹었는지 확인하려고 조회 명령을 돌렸는데 값이 비어 있다고 나왔습니다. 설정이 안 먹는 줄 알고 한참 헤맸습니다.
원인은 그 기계에 패키지 매니저가 두 벌 있었던 것입니다. 저장소 안에서는 저장소가 지정한 버전이, 밖에서는 전역 버전이 돌아갑니다. 저는 저장소 밖에서 조회했고, 그 버전은 제가 넣은 설정을 모르는 상태였습니다.
설정이 안 먹는 것과 안 먹는지 확인하는 방법이 틀린 것은 증상이 똑같습니다. 둘 다 "값이 없다"로 보입니다. 측정 도구를 먼저 의심해야 하는 상황이 있다는 것을 또 한 번 배웠습니다.
정직하게 남길 것
결과를 좋게만 적고 싶지 않으니 두 가지를 덧붙입니다.
첫째, 이 노트북은 여전히 느립니다. E2E 기준으로 맥북보다 3.8배, GitHub이 빌려주는 기계보다 1.3배 느립니다. 편입의 가치는 빨라지는 것이 아니라, 맥북 두 자리가 다 찼을 때 줄이 짧아지는 것입니다. 3편에서 러너를 늘렸던 이유가 원래 그것이었습니다.
둘째, 남은 일 중 하나는 여전히 저장소를 건드립니다. 테스트 단정 일곱 건입니다. 다만 이건 예비 러너를 위한 양보가 아니라 고치는 게 코드베이스에 이로운 종류였습니다. 경로를 문자열로 단정하는 테스트는 원래 잘못된 테스트니까요.
그래서 고치기로 했습니다. 쉬워 보였습니다. 그리고 다음 편에서 그 수정 두 건의 근거가 리뷰에서 무너집니다. 테스트를 통과하게 만드는 것과 옳게 고치는 것은 다른 일이었습니다.
관련 글
테스트를 통과시켰지만 근거가 틀렸습니다 — 리뷰가 잡아낸 두 건
경로를 잘못 단정하던 테스트를 고쳤는데, 리뷰가 제 수정의 근거를 무너뜨렸습니다. 검색 결과의 첫 히트를 근거로 삼았고, 그것은 제가 찾던 것과 이름만 같은 다른 값이었습니다.
파일시스템이 범인이라던 제 진단도 절반만 맞았습니다 — 링크가 만든 곱셈
윈도우 러너가 느린 범인을 파일시스템으로 지목했는데, 그것도 절반만 맞았습니다. 파일 16만 개짜리 폴더를 93만 개 경로로 걷게 만든 것은 패키지 매니저의 링크 구조였고, 설정 한 줄로 260초가 14초가 됐습니다.
러너가 느린 범인을 Wi-Fi로 지목했다가 틀렸습니다 — 워밍이 콜드보다 느렸던 이유
윈도우 러너가 hosted보다 15배 느렸습니다. 공유기가 100Mbps라는 증거까지 찾아내 네트워크를 범인으로 지목했는데, 캐시가 채워진 상태의 재측정이 콜드보다 느리면서 진단이 통째로 뒤집혔습니다.