Watch at Ease세상을 읽고, 일상의 답을 찾다.

기술 · 실용 가이드

TOML 테이블 중복 선언? 헤더를 지우기 전에 키 경로부터 확인하세요

인용된 이름, 점 키와 생성된 구역은 글자가 달라도 충돌할 수 있습니다. 원본과 파싱 트리를 보존하고 다음 생성도 검증하세요.

TOML 키 경로를 설명하는 자체 제작 도식
자체 제작 일러스트: 동등한 인용과 인용 안 점의 차이를 확인합니다. Watch at Ease

테이블 중복 오류는 의미상 경로를 가리키며 두 줄이 완전히 같다는 뜻은 아닙니다. 헤더 삭제·키 변경·설치 재실행 전에 파일과 작성 주체를 확인하세요.

1. 정확한 파일과 작성 주체를 보존하세요

편집 전에 원본 설정을 복사하세요. 앱이 실제 읽는 경로, 파서/Python 버전, 전체 오류와 수동·병합·자동생성 여부를 기록합니다. 오류 줄은 두 번째 선언을 가리키는 경우가 많으므로 바로 지우지 말고 같은 경로를 먼저 정의한 부분을 찾으세요.

출력을 조사하는 동안 실패한 생성 단계를 멈추세요. 도구 관리 값과 사용자 소유 값을 구분해 기록합니다. 자격 증명이 든 전체 설정을 온라인 검사기에 보내지 말고 충돌 키 구조를 유지하는 최소 비식별 예제를 만드세요.

2. 헤더 문자열보다 의미상 경로를 비교하세요

CPython3.12.14 사례에서 [service.api] 뒤의 [service."api"]는 실패했습니다. 같은 요소에 인용부호를 붙여도 새 테이블이 아닙니다. 반면 [service."api.v1"]와 [service.api.v1]은 서로 다른 트리입니다. 전자는 api.v1이라는 단일 키, 후자는 api 아래 v1입니다. 인용 위치 변경은 설정 의미를 바꿀 수 있습니다.

각 경로 요소와 필요한 값을 적으세요. 인용된 요소 안의 점은 이름 일부이므로 모든 점에서 헤더를 나누는 텍스트 검색을 사용하지 마세요. 공백이나 동등한 인용 표기 차이는 생성기의 유일성 판단 기준이 아닙니다.

3. 경로가 먼저 정의된 방식을 구분하세요

같은 시험에서 service=1 뒤의 [service.api], service.api.port=8000 뒤의 [service.api]는 거부됐습니다. 인라인 service={api={port=8000}} 뒤에서 [service.api]를 확장해도 실패했습니다. 값/테이블 또는 선언 충돌이므로 들여쓰기로 해결되지 않습니다.

암시적 부모는 다릅니다. port가 있는 [service.api] 뒤에 name을 가진 [service]를 두면 성공했습니다. 실제 중복 service.api는 port와 host를 보존한 한 구역으로 합치면 성공했습니다. 어느 선언이 테이블을 소유하는지 정하고 필요한 값을 모두 보존하세요. 임의의 나중 값 우선 정책이나 전체 블록 삭제는 피합니다.

4. 트리와 다음 쓰기를 검증하세요

앱이 지원하는 파서로 후보 복사본을 읽으세요. Python3.11+의 tomllib.load는 바이너리 파일, tomllib.loads는 문자열을 받습니다. TOML 구문만 검사하며 앱이 허용하는 옵션이나 쓰기는 지원하지 않습니다.8개 사례는 CPython3.12.14/TOML1.0에서 실행했으며 Python3.15의 TOML1.1 지원과 구분해야 합니다.

필수 키 경로·형식·값을 확인한 후 앱 자체의 안전한 설정 검사를 실행하세요. 생성기가 소유한다면 임시 복사본에서 두 번 실행해 두 출력이 모두 파싱되고 사용자 값이 남으며 새 중복 테이블이 없는지 확인합니다. 이후 백업을 유지한 채 교체하세요. 다음 생성에서 다시 망가진다면 수동 수정은 끝난 것이 아니며 작성 도구나 문서화된 수정 버전을 고쳐야 합니다.

TOML 복구 검증 절차 도식
자체 제작 일러스트: 원본·구문·값·두 번의 생성을 검증합니다. Watch at Ease