본문으로 건너뛰기
AZ Tools

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가 이 바이트로 무엇을 할지이지, 당신이 무엇을 쓰려 했는지가 아닙니다.

.properties 파일 내용

고유 키

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주석
2app.nameorders-api=덮어써짐
3server.port8080:
4app.modeproduction공백공백 구분자
5jdbc.urljdbc:postgresql://db:5432/orders?ssl=true=
6menu.label 1Save as…=키 안의 구분자
7–8welcome.messageHello and welcome=
9app.tokenabc123···=값 끝의 공백 유지
10greetingGrüße=
11greeting.escapedGrüße=
12app.nameorders-api-v2=
13pathC:\\Users\\dev\\app=
14notevalue # this is not a comment=주석이 아님

표에서는 제어 문자를 \n, \t로 바꾸고 값 끝의 공백을 ·로 표시해 보이게 합니다. JSON 보기는 있는 그대로입니다.

사용법

  1. 파일 내용을 붙여 넣거나 .properties 파일을 드롭 영역에 끌어다 놓으세요. 브라우저 안에서만 읽고 업로드하지 않습니다.
  2. 줄별 표를 확인하세요. 각 항목이 몇 번째 줄에서 왔는지, 실제로 쓰인 구분자가 무엇인지, 그 줄에 이상한 점이 있는지 배지로 표시됩니다.
  3. 위쪽 지적 사항을 하나씩 처리하세요. 중복 키, 값 끝의 공백, 다음 항목을 삼킨 이어붙이기 이 세 가지가 운영에서 조용히 동작을 바꿉니다.
  4. 비ASCII 글자가 있으면 UTF-8과 ISO-8859-1 해석을 전환해 load(InputStream)이 애플리케이션에 무엇을 넘길지 확인하세요.
  5. 설정 비교에는 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에는 그런 것이 없습니다. 따옴표는 값에 그대로 들어가는 평범한 문자이고, 값 뒤의 #도 값의 일부이며, 형식 자체에는 변수 확장이 없고(스프링이 위에 얹은 것입니다) 이어붙이기는 따옴표가 아니라 백슬래시로 합니다.

관련 도구