하나의 .env 키가 두 개의 다른 사용자 이름을 가질 때, 제가 고친 것은 코드를 더 잘 추측하게 만드는 것이 아니었습니다.
요약
개발자가 `.env` 파일에서 하나의 키가 두 가지 다른 의미로 사용되는 상황(semantic overloading)을 발견하고, 이 문제를 해결하기 위한 설계 원칙을 논합니다. 단순히 유효성 검사를 추가하는 것보다, 각 값에 명확한 이름 지정 상수(named constants)를 사용하는 것이 장기적인 유지보수와 확장성에 훨씬 유리함을 강조합니다.
핵심 포인트
- 하나의 변수가 여러 의미로 사용되는 '의미론적 과부하'는 잠재적 버그 원인입니다.
- 단순 유효성 검사나 가드 추가만으로는 근본적인 해결책이 될 수 없습니다.
- 각 값에 명확한 이름 지정 상수를 사용하는 것이 확장성과 안정성을 높이는 최선의 방법입니다.
제가 GitHub 프로필과 DEV.to 아티클을 관리하기 위해 구축한 작은 MCP 서버 초기에, 모든 GitHub API 호출이 아무 의미 없는 404 오류로 실패하기 시작했습니다. 토큰은 유효했고, 엔드포인트도 정확했으며, 요청 자체는 독립적으로 보면 문제가 없어 보였습니다. 버그는 스택의 한 줄 위에서 발생했습니다: GITHUB_USERNAME 변수는 .env 파일에서 그대로 읽어오고 있었는데, 그 변수에 담긴 값은 언더스코어가 포함된 제 DEV.to 핸들인 enjoy_kumawat였습니다. 실제 GitHub 사용자 이름에는 언더스코어가 없습니다. GitHub의 API는 유사 일치(fuzzy-match)를 하지 않기 때문에, 존재하지 않는 사용자를 찾았고 저에게 그 사실을 정확하게 알려주었습니다.
.env 파일은 하나의 키가 두 가지 역할을 수행하고 있었습니다. 두 플랫폼 모두
두 개의 이름이 지정된 상수(named constants)가 사용되는 스크립트에 하드코딩되어 있으며, 각각 어떤 플랫폼을 위한 것인지 그리고 왜 그렇게 보이는지에 대한 주석이 달려 있습니다. 조회(lookup), 추론(inference), 또는 '스마트'한 해결 단계는 전혀 없습니다. 만약 세 번째 플랫폼이 추가되더라도, 그것은 자체적인 이름 지정 상수를 갖게 되며, 애초에 공유 슬롯에서 무언가를 추론하고 있지 않기 때문에 패턴이 규모가 커져도 저하되지 않습니다.
저는 이 결정(decision)을 나중에 다시 논쟁하지 않기 위해 당시 별도의 의사결정 기록(ADR-003 in this repo's docs/project_notes/decisions.md)으로 작성했습니다: 'GitHub 사용자 이름은 하드코딩하고, .env에서 읽지 말 것.' 이 ADR을 다시 살펴보니 흥미로운 부분은 수정 사항 자체가 아니라 그 틀(framing)입니다. 제가 실제 옵션으로 기록하지 않은 대안은 '모호한 읽기(ambiguous read)가 조용히 실패하는 대신 명확하게 실패하도록 유효성 검사(validation)를 추가하는 것'이었습니다. 이것이 이 유형의 버그에 대해 더 흔하게 듣는 조언입니다: 빠르게 실패하고, 입력을 검증하며, 단언(assertion)을 추가하는 것입니다. 아무것도 없는 것보다는 낫습니다. 하지만 여전히 데이터 내의 모호성을 남겨두고 그 앞에 가드(guard)를 추가할 뿐입니다. 이 가드는 유지 관리되어야 하고, 모든 새로운 경우를 커버해야 하며, 무언가 잘못 추측했을 때만 사후적으로 알려줄 뿐입니다.
이러한 구분은 제가 처음 이 문제를 겪었을 때보다 지금 더 중요합니다. 왜냐하면 이 저장소에서 .env 값을 읽는 주체가 더 이상 저 혼자만이 아니기 때문입니다. 이 코드베이스에서 작업하는 에이전트(agent)는 GITHUB_USERNAME을 검색하여 찾고, 돌아오는 모든 문자열을 완전한 확신으로 사용합니다. 만약 저장소의 무언가가 알려주지 않는 한, 그 키가 의미론적으로 과부하되었다(semantically overloaded)는 것을 독립적으로 알 방법이 없습니다. 404 오류를 디버깅하는 인간은 사전 지식(priors)을 가지고 있습니다: '음, 저 사용자 이름이 이상한데, 어디서 왔는지 확인해 봐야겠다.' 하지만
이것이 실제로 일반화 가능한 핵심이며, 사용자 이름보다 더 광범위합니다. 코드베이스의 어느 곳에서 하나의 저장 슬롯이 두 가지 미묘하게 다른 의미를 위해 재사용되는지는 독자(인간이든 에이전트든)가 매번, 영원히, 정확하게 추측해야 하는 지점입니다. 게다가 그 추측이 이루어지고 있다는 신호조차 없습니다. 독자가 더 잘 추측하도록 가르칠 수도 있습니다 (유효성 검사, 폴백, 런타임 체크). 또는 슬롯 자체가 모호하지 않도록 만들 수 있습니다 (별도의 명시적 이름의 상수 사용, 의미마다 하나씩). 후자는 더 많은 독자가 나타날수록 난이도가 증가하지 않습니다. 하지만 전자는 그렇지 않습니다. 왜냐하면 새로운 독자마다 동일한 모호성 해소 규칙을 다시 배워야 하기 때문입니다.
저는 '이 값의 이름이 그것이 담고 있는 것을 완전히 설명하며, 문맥에서 추론할 여지가 전혀 없는가'를 단순히 스타일적인 사소한 지적이 아니라 이 프로젝트의 실제 검토 질문으로 다루기 시작했습니다. 상수를 작성하는 동안 답변하는 데는 아무 비용도 들지 않습니다. 하지만 나중에 무언가가 잘못된 추측에 의존하게 되었을 때, 이를 해결하려면 혼란스러운 404 에러와 디버깅 세션이 필요합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기