
내 블로그 포스트를 팩트 체크하다가 제품 QA가 되어버린 경험: 3가지 실제 버그
요약
블로그 포스트의 기술적 사실을 검증하는 과정에서 제품의 실제 버그 3가지를 발견한 경험담입니다. 작성자는 글의 정확성을 위해 문장을 수정하는 대신, 제품의 코드를 수정하여 기술적 주장을 사실로 만드는 방식을 택했습니다.
핵심 포인트
- 기술 콘텐츠 작성 시 실제 코드와 대조하는 검증 습관의 중요성
- 글의 주장에 맞춰 제품의 미들웨어를 수정하여 버그 해결
- 데이터 누수(스탬프 파일) 및 미래 날짜 데이터 생성 버그 발견
- 검증 과정이 단순 글쓰기를 넘어 QA 역할로 확장될 수 있음
저는 제 블로그 포스트 중 하나에 적힌 "API가 no-store를 반환한다"라는 문장을 팩트 체크(fact-checking)하던 중, API가 실제로 그렇게 동작하지 않는다는 사실을 발견했습니다.
그래서 저는 문장을 수정하지 않았습니다. 대신 제품을 수정했습니다.
저에게는 스스로 정한 규칙이 있습니다. 기술적인 내용을 발행하기 전에, 모든 사실적 주장(factual claim)을 실제 코드와 대조하며 검토하는 것입니다. 이는 독자에게 깊은 인상을 남기기 위해서가 아니라, 스스로에게 정직하기 위해서입니다. 왜냐하면 그럴듯하게 들리는 내용을 쓰는 것은 부끄러울 정도로 쉽기 때문입니다. 이번 주에 이 습관은 글쓰기에 관한 것이 아니게 되었습니다. 네 개의 포스트를 검토한 결과, 포스트가 아닌 제품 내에서 세 가지 실제 버그(real bugs)를 찾아냈습니다.
버그 1: 문장은 맞았지만, 제품이 늦었다
해당 포스트는 공유 호스팅(shared hosting)에서의 인증 헤더(auth-header) 특이 사항에 관한 것이었으며, API가 인증된 응답(authenticated responses)에 대해 Cache-Control: no-store를 반환한다고 주장했습니다. 충분히 주장할 만한 내용이었습니다. 하지만 실제로 확인해 보니 사실이 아니었습니다. 헤더가 설정되지 않고 있었습니다.
표준 Authorization 헤더를 제거하는 프록시(proxy)를 통해 앱이 작동하는 방식 때문에, "Authorization과 연결된 응답은 공유 캐시(shared-cache)가 될 수 없다"라는 일반적인 보호 기능이 적용되지 않았습니다. 이는 이론적으로 인증된 응답이 공유 캐시에 저장될 수 있음을 의미했습니다.
저에게는 두 가지 선택지가 있었습니다. 블로그 문장의 수위를 낮추거나, 아니면 문장을 사실로 만드는 것이었습니다. 저는 파이프라인(pipeline)의 가장 바깥쪽 레이어에서 no-store를 설정하는 작은 미들웨어(middleware)를 추가하고, 몇 개의 테스트를 남겨둔 채 배포했습니다. 이제 문장은 정확합니다. 문장에 맞춰 제품이 변경되었기 때문입니다. 그 반대가 아니라 말이죠.
이것이 제가 가장 좋아하는 사례입니다. 제 글이 코드보다 앞서 나갔고, 글을 검토하는 과정이 버그를 표면화했습니다.
버그 2: "아무것도 쌓이지 않는다" — 쌓이는 것이 있었음에도 불구하고
또 다른 포스트는 일회용 데모(disposable-demo) 설정을 설명했습니다. 링크를 클릭하면 일회용 테넌트(tenant)를 할당받고, 매시간 정리 작업(sweep)이 모든 것을 삭제하므로 아무것도 쌓이지 않는다는 내용이었습니다. 저는 "아무것도 쌓이지 않는다"라는 주장을 문자 그대로 검증하러 갔습니다.
거의 아무것도 쌓이지 않았습니다. 하지만 각 데모 테넌트 (demo tenant)는 스윕 (sweep) 과정에서 삭제되지 않는 작은 테넌트별 스탬프 파일 — 스로틀 장부 기록 아티팩트 (throttle bookkeeping artifact) — 를 남겼습니다. 데모를 클릭할 때마다 하나씩 추가되었고 절대 제거되지 않았습니다. 서버를 곧 다운시킬 정도의 누수 (leak)는 아니었지만, 제가 막 발행하려던 문장과 정면으로 배치되는 내용이었습니다.
이제 스윕은 테넌트를 삭제할 때 해당 스탬프들을 제거하며, 이미 사라진 테넌트로부터 남겨진 고아 (orphans) 데이터들도 스스로 복구 (self-heals) 합니다. 주장이 다시 사실로 회복되었습니다.
버그 3: 데모가 미래를 보여주고 있었다
해당 데모 포스트의 영어 버전을 작성하던 중, 저는 독자의 입장에서 시드된 데이터 (seeded data)를 클릭하며 살펴보았습니다. 데모는 몇 개의 인보이스 (invoices), 몇 건의 결제 내역 등 현실적인 이력 (history) 을 심어두어 마치 실제 운영 중인 비즈니스처럼 보이게 합니다.
월의 전반부에 이를 열어보니, 그 "이력" 중 일부가 _미래_의 날짜로 되어 있었습니다. 아직 오지 않은 날짜로 기록된 결제 내역, 다음 주가 만기인 결제 완료 인보이스 같은 것들 말입니다. 시드 (seed) 과정에서 고정된 일자 (day-of-month) 값을 사용했기 때문에, 월초에는 오늘보다 앞선 날짜가 되어버린 것입니다.
이를 가장 먼저 알아챌 사람은 회계사일 것이며, 이는 정확히 데모의 타겟 고객층입니다. 수정 사항은 모든 시드된 이벤트 날짜를 "오늘 또는 그 이전"으로 제한(clamp)하되, 실제 미래 날짜(만기일 등)는 그대로 두도록 했습니다. 저는 최악의 상황인 월초에 시드하는 테스트를 추가하여, 수정 전에는 테스트가 실패함을 확인했습니다.
성과에 대해 솔직해지기
포스트 4개, 제품 수정 3개 — 하지만 저는 이 적중률을 과장하고 싶지 않습니다. 4개의 포스트 중 2개는 제품 버그가 전혀 없었습니다. 그들의 주장은 이미 사실이었고, 이를 확인하는 과정은 단지 한 시간의 비용과 확신을 얻는 과정이었을 뿐입니다. 세 개의 버그는 포스트 하나당 하나씩 나타난 것이 아니라, 두 개의 포스트에 집중되어 있었습니다. 만약 제가 이를 "모든 블로그 포스트에는 버그가 숨어 있다"라고 꾸며낸다면, 그것 또한 하나의 작은 날조가 될 것입니다.
핵심은 신뢰할 수 있는 수율 (yield)이 아닙니다. 관점 (lens)에 관한 것입니다.
왜 산문(prose)이 테스트가 놓치는 것을 잡아내는가
테스트는 당신이 작성할 것이라고 생각한 단언(assertions)들을 확인합니다. 산문(prose)은 다른 종류의 주장, 즉 더 위험한 주장을 합니다. 바로 낯선 이가 반증할 수 있을 만큼 명확하게 기술된 **"시스템이 X를 수행한다"**라는 주장입니다.
당신의 코드는 no-store라고 말하지 않습니다. 하지만 당신의 블로그 포스트는 그렇게 말합니다. 당신의 테스트 스위트(test suite)는 "아무것도 축적되지 않는다"라거나 "미래의 날짜가 존재하지 않는다"라고 단언한 적이 없지만, 당신의 문단은 인터넷 전체를 향해 큰 소리로 그렇게 말했습니다. 글을 쓰는 행위는 동작을 평이한 선언적 문장(declarative sentences)으로 압축하도록 강제하며, 이러한 평이한 선언적 문장이야말로 당신이 코드로 직접 걸어가서 확인할 수 있는 바로 그 대상입니다.
따라서 "모든 주장은 코드를 통해 검증되어야 한다"라는 규칙 아래 게시물을 올리는 것은 단순히 포스트의 위생(hygiene)을 위한 것이 아닙니다. 그것은 테스트가 결코 던지지 않았던 질문, 즉 _"내가 사람들에게 말하고 있는 것이 지금 실제로 사실인가?"_라는 질문에 의해 구동되는 QA 과정입니다.
그리고 no-store 사례처럼 그 답이 "아니오, 하지만 그래야만 합니다"일 때, 정직한 해결책은 문장을 축소하여 수정하는 것이 아닙니다. 그 문장을 사실로 만드는 것입니다.
당신은 게시 버튼을 누르기 전에 코드를 바탕으로 포스트를 확인하나요? 그리고 그 과정에서 작성 중이던 대상의 버그를 발견한 적이 있나요?
── Hideyuki Mori (Ayane International) 🔗 hideyuki-mori.com
[

](/hideyukimori)
HideyukiMORI팔로우
셀프 호스팅 비즈니스 워크플로우를 위한 API 우선(API-first) PHP 도구 구축 중. NENE2 및 NeNe OSS 시리즈 제작자.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기