Java .properties 파서
.properties는 가장 단순해 보이는 설정 형식이지만, 직접 만든 파서가 가장 자주 틀리는 형식이기도 합니다. 이 페이지는 java.util.Properties.load가 실제로 쓰는 절차(JDK의 LineReader, 이어서 load0과 loadConvert)를 그대로 실행해, 붙여 넣거나 끌어다 놓은 텍스트가 어떤 맵이 되는지 키 하나씩 보여 주고 JSON과 Properties.store가 다시 써 낼 형태로도 보여 줍니다. 구분자는 =, : 그리고 공백입니다. 그래서 "c three"는 키 c에 값 three이고, "key with spaces=x"는 키가 "key", 값이 "with spaces=x"입니다. 구분자 주변 공백은 사라지지만 값 끝의 공백은 남습니다. 줄 끝의 백슬래시는 다음 줄을 이어 붙이고 이어지는 줄의 들여쓰기는 제거되지만, 백슬래시가 짝수 개면 이어지지 않으며 주석 줄은 백슬래시로 끝나도 이어지지 않습니다. #와 !는 줄의 첫 비공백 문자일 때만 주석이므로 URL 조각의 #는 값에 그대로 남습니다. 이스케이프는 \t \n \r \f와 \uXXXX뿐이고 나머지 백슬래시는 조용히 사라집니다. 현장에서 가장 큰 문제는 인코딩입니다. 거의 모든 프레임워크가 부르는 load(InputStream)은 바이트를 ISO-8859-1로 읽으므로 UTF-8로 저장한 파일은 글자가 깨집니다. 입력에 비ASCII가 있으면 이 페이지는 두 가지 해석을 모두 보여 주고 달라지는 키를 짚어 줍니다. 모든 처리는 브라우저 안에서 이뤄지며 업로드는 없습니다. 다만 중복된 키 중 어느 쪽이 의도였는지, 이상해 보이는 값이 정말 틀렸는지는 알려 줄 수 없습니다. 이 도구가 말하는 것은 JDK가 이 바이트로 무엇을 할지이지, 당신이 무엇을 쓰려 했는지가 아닙니다.
고유 키
11
지정 횟수
12
주석 줄
1
이어진 줄
1
지적 사항
6
거의 모든 프레임워크의 기본인 load(InputStream)은 항상 ISO-8859-1로 읽습니다. 두 해석을 전환해 어떤 키가 달라지는지 확인하세요.
비ASCII 글자가 깨짐 · 줄 10
load(InputStream)은 바이트를 ISO-8859-1로 읽습니다. UTF-8로 저장한 파일이면 한 글자가 두세 글자로 깨집니다. \uXXXX로 이스케이프하거나 문자셋을 지정한 Reader로 읽으세요.
- greeting: "Grüße" → "GrüÃe"
공백 구분자 · 줄 4
이 줄에는 =도 :도 없습니다. 첫 공백이나 탭이 키와 값을 나누므로 "c three"는 c = three입니다.
app.mode
값 끝의 공백 유지 · 줄 9
구분자 주변 공백은 사라지지만 값 끝의 공백은 값의 일부로 남습니다. 편집기에도 보이지 않고 오류도 나지 않습니다.
app.token (+3)
키 안의 구분자 · 줄 6
이 키에는 이스케이프된 =, : 또는 공백이 들어 있습니다. 한 개의 키이며, 첫 "="에서 자르는 코드는 엉뚱한 위치를 자릅니다.
menu.label 1
주석이 아님 · 줄 14
#와 !는 줄의 첫 비공백 문자일 때만 주석을 엽니다. 여기서는 값 뒤에 있으므로 값의 일부로 그대로 들어갑니다.
note
중복 키 · 줄 2, 12
같은 키가 여러 번 지정되었습니다. load는 마지막 값만 남기고 아무 경고도 하지 않으므로 앞의 줄들은 살아 있는 것처럼 보이는 죽은 설정입니다.
app.name → "orders-api-v2"
| 줄 | 키 | 값 | 구분자 | 비고 |
|---|---|---|---|---|
| 1 | # Spring Boot style configuration — and every trap in the format | 주석 | ||
| 2 | app.name | orders-api | = | 덮어써짐 |
| 3 | server.port | 8080 | : | |
| 4 | app.mode | production | 공백 | 공백 구분자 |
| 5 | jdbc.url | jdbc:postgresql://db:5432/orders?ssl=true | = | |
| 6 | menu.label 1 | Save as… | = | 키 안의 구분자 |
| 7–8 | welcome.message | Hello and welcome | = | |
| 9 | app.token | abc123··· | = | 값 끝의 공백 유지 |
| 10 | greeting | Grüße | = | |
| 11 | greeting.escaped | Grüße | = | |
| 12 | app.name | orders-api-v2 | = | |
| 13 | path | C:\\Users\\dev\\app | = | |
| 14 | note | value # this is not a comment | = | 주석이 아님 |
표에서는 제어 문자를 \n, \t로 바꾸고 값 끝의 공백을 ·로 표시해 보이게 합니다. JSON 보기는 있는 그대로입니다.
사용법
- 파일 내용을 붙여 넣거나 .properties 파일을 드롭 영역에 끌어다 놓으세요. 브라우저 안에서만 읽고 업로드하지 않습니다.
- 줄별 표를 확인하세요. 각 항목이 몇 번째 줄에서 왔는지, 실제로 쓰인 구분자가 무엇인지, 그 줄에 이상한 점이 있는지 배지로 표시됩니다.
- 위쪽 지적 사항을 하나씩 처리하세요. 중복 키, 값 끝의 공백, 다음 항목을 삼킨 이어붙이기 이 세 가지가 운영에서 조용히 동작을 바꿉니다.
- 비ASCII 글자가 있으면 UTF-8과 ISO-8859-1 해석을 전환해 load(InputStream)이 애플리케이션에 무엇을 넘길지 확인하세요.
- 설정 비교에는 JSON 보기를, 다시 저장할 파일이 필요하면 Properties.store 보기를 복사하세요. 구분자와 비ASCII가 모두 이스케이프됩니다.
자주 묻는 질문
- "c three"에 = 기호가 없는데 왜 키와 값으로 나뉘나요?
- 이 형식에서는 공백도 구분자이기 때문입니다. Properties.load는 이스케이프되지 않은 첫 =, : 또는 공백 문자를 찾아 그 앞을 키로 봅니다. 그래서 "c three"는 키 c에 값 three이고, "key with spaces=x"는 키가 "key", 값이 "with spaces=x"가 되어 =는 구분자 역할을 하지 못합니다. 키에 공백을 넣으려면 "\ "처럼 이스케이프해야 하며, Properties.store도 그런 키를 쓸 때 정확히 그렇게 씁니다.
- 한글이나 악센트 글자가 깨져서 나옵니다. 무슨 일인가요?
- java.util.Properties.load(InputStream)은 스트림을 ISO-8859-1로, 한 바이트를 한 글자로 읽도록 규정되어 있습니다. UTF-8로 저장한 파일에서 한 글자는 두세 바이트이고, 그 바이트들이 각각 라틴 문자가 되어 깨집니다. 예외도 나지 않아서 깨진 문자열이 화면까지 그대로 갑니다. 해결책은 세 가지입니다. 비ASCII를 \uXXXX로 쓰거나(native2ascii와 Properties.store가 하는 방식), UTF-8 InputStreamReader로 load(Reader)를 부르거나, 기본이 UTF-8인 loadFromXML을 쓰면 됩니다.
- 값 끝의 공백이 정말 그대로 남나요?
- 남습니다. 그리고 그것이 한 부류의 버그 리포트를 만들어 냅니다. 줄 앞의 공백, 구분자 주변 공백, 이어지는 줄의 들여쓰기는 모두 사라지지만 값 끝의 공백은 그대로 유지됩니다. 거기서 줄이 끝나므로 아무도 잘라 내지 않기 때문입니다. 공백이 하나 섞인 비밀번호나 URL은 문법 오류 없이 파싱되고 접속만 실패하며, 편집기에서도 코드 리뷰에서도 정상과 똑같아 보입니다. 이 페이지의 표는 그 문자를 눈에 보이게 표시합니다.
- 어떤 줄이 다음 줄로 이어지나요?
- 백슬래시가 홀수 개로 끝날 때입니다. 마지막 백슬래시가 제거되고 다음 줄이 붙으며, 그 줄의 앞 공백은 잘립니다. 짝수 개이면 이어지지 않고 백슬래시는 절반 개수의 실제 문자로 남습니다. 여기서 두 가지 함정이 생깁니다. 값 끝에 백슬래시가 잘못 남아 있으면 아래의 "key=value" 줄이 그 값에 삼켜지고 그 키는 사라집니다. 또 주석 줄은 백슬래시로 끝나도 이어지지 않으므로 그 다음 줄은 평범한 항목으로 파싱됩니다.
- 같은 키를 두 줄에서 지정하면 어느 쪽이 이기나요?
- 뒤쪽이, 아무 말 없이 이깁니다. Properties는 Hashtable이고 load는 항목을 만날 때마다 put을 부를 뿐이라 나중 줄이 앞 줄을 덮어씁니다. 경고도 오류도 기록도 없습니다. 여러 조각을 합쳐 파일을 만들거나 같은 키를 한 번은 =로, 한 번은 :로 쓴 경우에 실수로 만들어지기 쉽습니다. 이 페이지는 중복된 키와 그것을 지정한 모든 줄 번호를 나열하고 진 줄은 흐리게 표시합니다.
- .env 파일과 같은 형식인가요?
- 아닙니다. 서로 같다고 생각하는 것이 조용한 장애의 흔한 원인입니다. .env에는 공백 구분자가 없고, 따옴표로 값을 보호하거나 여러 줄을 담으며, 값 뒤의 #를 인라인 주석으로 보고, ${VAR} 확장을 지원하는 경우가 많습니다. .properties에는 그런 것이 없습니다. 따옴표는 값에 그대로 들어가는 평범한 문자이고, 값 뒤의 #도 값의 일부이며, 형식 자체에는 변수 확장이 없고(스프링이 위에 얹은 것입니다) 이어붙이기는 따옴표가 아니라 백슬래시로 합니다.
관련 도구
텍스트 인코딩 변환기
EUC-KR · Shift_JIS · Windows-1252 등 비-UTF-8 텍스트 파일을 UTF-8로 읽으세요.
Mbox 보관 파일 뷰어
mbox 보관 파일을 브라우저에서 분할합니다. 메시지 경계와 디코딩된 헤더, MIME 구조, 스레드, 중복 Message-ID를 보여 주며 업로드는 없습니다.
자바 클래스 파일 분석기
컴파일된 .class 파일을 브라우저에서 바로 분석합니다. 클래스 파일 버전과 자바 릴리스, 접근 플래그, 상수 풀, 필드, 메서드, 참조 클래스를 보여줍니다.
BSON 디코더 · 확장 JSON 뷰어
MongoDB BSON 파일을 브라우저에서 해석합니다. 요소 타입과 타입 바이트, 정확한 int64와 decimal128, 정규/완화 확장 JSON을 함께 보여 줍니다.
JSON to Java 클래스(POJO) 변환기
JSON 객체를 타입이 매핑된 필드가 포함된 Java POJO 클래스로 브라우저에서 변환합니다.
문자열 이스케이프 변환기
한 입력으로 10개 컨텍스트 이스케이프 출력 — JavaScript, JSON, HTML 엔티티, URL, SQL, regex, Bash(단·이중 따옴표), C 문자열, Unicode \u. 필요한 것을 복사.