JSON 포맷터
예상 결과: orders를 펼치면 항목 두 개가 표시됩니다. paid는 false, total은 42.5입니다. 복사하면 두 칸 들여쓰기 JSON을 얻습니다.
제한 사항: JavaScript JSON 파싱을 사용하므로 중복 키가 합쳐지고 큰 정수는 정밀도를 잃을 수 있습니다. 정확해야 하는 식별자는 문자열로 넣으세요.
입력한 내용은 저장, 기록, 공유되지 않습니다.
JSON을 붙여넣으면 즉시 정렬하고 검증합니다. 모든 처리가 브라우저 안에서 이루어지므로 데이터가 서버로 전송되지 않습니다.
사용 방법
- 입력창에 JSON을 붙여넣습니다.
- 정렬된 결과가 바로 표시됩니다.
- 복사 버튼으로 결과를 복사합니다.
이 포맷터가 받아들이는 것
파서는 RFC 8259를 정확히 따르며, 이는 대부분의 사람이 예상하는 것보다 엄격합니다. 키는 큰따옴표로 감싸야 합니다. 문자열도 큰따옴표만 쓸 수 있고 작은따옴표는 안 됩니다. 객체나 배열의 마지막 요소 뒤에 쉼표를 둘 수 없고, 어떤 형태의 주석 문법도 없으며, NaN, Infinity, undefined도 없습니다. 숫자는 16진수로 쓸 수 없고, 앞에 + 기호를 붙일 수 없으며, 정수 부분이 0으로 시작할 수도 없습니다.
이 엄격함은 트집이 아니라 의도된 것입니다. 받는 쪽의 모든 JSON 파서가 적용하는 기준이 바로 이것이기 때문입니다. 여기서 포맷되는 문서는 Python, Go, Rust, PostgreSQL에서도 파싱됩니다. 관대한 파서가 의도를 추측해 줘야만 동작하는 문서는 나중에 어딘가에서, 대개는 운영 환경에서 실패합니다.
입력에 주석이나 끝 쉼표가 있다면 그것은 JSON이 아니라 tsconfig.json 같은 설정 파일에 쓰이는 완화된 변형인 JSON5나 JSONC입니다. 이들도 실제로 쓰이는 정당한 형식이며, 유효한 JSON으로 만들기 위해 주석을 지우는 것은 정보를 잃는 편집입니다. 그 점을 알고 하세요.
오류 메시지 읽는 법
파싱에 실패하면 엔진이 보고한 문자 오프셋으로 계산한 줄과 열이 오류에 표시됩니다. 다만 그 위치는 파서가 포기한 곳이지, 항상 실수한 곳은 아니라는 점에 주의하세요. 닫는 중괄호가 빠진 경우에는 그 지점까지의 모든 내용이 여전히 유효할 수 있었기 때문에 대개 문서 끝에서 오류가 보고됩니다.
실패 원인의 거의 전부는 네 가지입니다. 닫는 괄호 앞의 끝 쉼표, 문자열이나 키를 감싼 작은따옴표, JavaScript 객체 리터럴에서 복사해 온 따옴표 없는 키, 그리고 문자열 값 안의 이스케이프되지 않은 큰따옴표나 줄바꿈입니다. 보고된 열이 따옴표를 가리킨다면 그 앞의 문자열이 일찍 끝났을 가능성이 큽니다.
또 다른 흔한 경우는 잘린 문서입니다. 크기 제한이나 타임아웃으로 잘린 응답은 값 중간에서 멈추기 전까지는 정상적으로 파싱되므로, 오류가 유용한 위치가 아니라 마지막 줄에 나타납니다. 중간을 뒤지기 전에 입력의 끝부분부터 확인하세요.
파싱 후 다시 출력하면 달라지는 것
포맷팅은 문서를 파싱한 뒤 다시 직렬화하므로, 그 과정에서 몇 가지가 정규화됩니다. 무엇이 바뀌는지 알아 둘 가치가 있습니다.
숫자는 IEEE 754 배정밀도 부동소수점 수가 됩니다. 9,007,199,254,740,991보다 큰 정수는 정밀도를 잃는데, 64비트 데이터베이스 ID, 트위터 방식의 Snowflake ID, 나노초 타임스탬프가 모두 이 선을 넘기 때문에 중요한 문제입니다. 9223372036854775807이라는 ID는 9223372036854776000으로 돌아옵니다. 이런 값을 온전히 유지해야 한다면 페이로드에 문자열로 넣으세요. 끝의 0도 사라져서 1.0은 1로, 1e3은 1000으로 포맷됩니다.
파싱 단계에서 객체를 만들기 때문에 중복 키는 하나로 합쳐지고 마지막 값이 남습니다. 그 외에는 키 순서가 유지되지만, JavaScript 객체에서 물려받은 예외가 하나 있습니다. 0 이상의 정수처럼 보이는 키는 숫자 순으로 정렬되어 나머지 키보다 앞으로 옵니다. 주석과 원래의 공백은 파싱을 거치면 남지 않으므로 당연히 사라집니다.
트리 보기
포맷된 텍스트 위에는 접고 펼 수 있는 트리가 있습니다. 이것은 다른 용도를 위한 것입니다. 수천 줄의 들여쓴 텍스트를 스크롤하지 않고도 낯선 응답의 구조, 원하는 필드가 어디에 있는지, 얼마나 깊이 중첩되어 있는지 파악할 수 있습니다. 관심 없는 배열을 접으면 구조가 한 화면에 읽힙니다.
복사 버튼으로 복사되는 것은 항상 포맷된 텍스트이므로, 트리에서 탐색해도 편집기에 다시 붙여 넣을 내용은 바뀌지 않습니다.
JSON은 어디서 왔고 무엇을 담을 수 있나
JSON은 2000년대 초 Douglas Crockford가 JavaScript 객체 리터럴 문법의 부분집합으로 규정했습니다. 브라우저가 이미 그것을 파싱할 수 있고, XML은 대부분의 웹 API에 필요한 것보다 무겁다는 관찰에서 출발한 것입니다. RFC 4627로 표준화되었고 이후 RFC 8259와 ECMA-404가 그 자리를 이어받았습니다. 문법 전체가 한 페이지에 들어간다는 사실이 JSON이 널리 퍼진 이유의 대부분입니다.
데이터 모델은 일부러 작게 만들어졌습니다. 객체, 배열, 문자열, 숫자, 불리언, 그리고 null. 그게 전부입니다. 날짜 타입도 없고, 바이너리 타입도 없고, 정수와 실수의 구분도 없고, 주석도 없으며, 문서의 한 부분에서 다른 부분을 참조할 방법도 없습니다.
JSON에서 껄끄러운 점은 모두 이 목록에서 비롯됩니다. 날짜는 타입이 아니라 관례일 수밖에 없고, 바이너리는 텍스트로 인코딩해야 하며, 큰 정수는 숫자가 보통 double로 파싱되는 형식에 부담을 줍니다. 그리고 주석이 필요한 설정 파일은 방언을 쓰거나 아예 다른 형식을 써야 합니다.
날짜, 돈, 그리고 큰 수
날짜에 대해 자리 잡은 관례는 UTC 기준 ISO 8601, 즉 2026-03-14T09:30:00Z 같은 형식입니다. 사전순 정렬이 그대로 통하고, 모호하지 않으며, 어떤 언어에서든 파싱할 수 있습니다. 대안들은 문제를 일으킵니다. 유닉스 타임스탬프는 초와 밀리초의 구분을 잃어버리고, 03/14/2026 같은 지역화된 문자열은 그것을 쓴 나라 밖에서는 해석이 갈립니다.
금액은 JSON 숫자가 되어서는 안 됩니다. 파서는 배정밀도 부동소수점을 써도 되기 때문에 0.1 더하기 0.2 같은 문제가 페이로드와 함께 도착하고, 반올림 동작도 언어마다 다릅니다. 19.99파운드를 1999로 적는 정수 보조 단위를 쓰고 통화는 별도 필드에 두는 것이 모든 소비자에게서 살아남는 표현입니다.
큰 식별자는 같은 문제가 더 날카로운 형태로 나타납니다. 2^53을 넘는 값은 double로 파싱되는 순간 정밀도를 잃고, 여기에는 64비트 데이터베이스 id와 스노플레이크 방식 식별자가 포함되므로 페이로드 안에서는 문자열이어야 합니다. 가정이 아닙니다. 여러 대형 API가 id와 id_str 필드를 함께 반환하는 이유가 바로 이것입니다.
메모리에 다 올릴 수 없는 파일
문서 전체를 객체로 만드는 파서는 파일 크기의 몇 배에 달하는 메모리를 필요로 합니다. 그래서 여유 메모리가 수 기가바이트인 장비에서도 500 MB짜리 내보내기 파일 하나가 프로세스를 고갈시킬 수 있습니다. 이를 피하는 방법은 두 가지입니다.
첫째는 줄바꿈으로 구분된 JSON으로, 각 줄이 하나의 완전한 문서이고 파일 전체는 유효한 JSON이 아닙니다. 스트리밍이 자연스럽고 덧붙이기 비용이 낮아서 대부분의 로그 파이프라인과 대량 내보내기 형식이 이 방식을 씁니다. 둘째는 스트리밍 파서로, Python의 ijson이나 다른 언어의 SAX 방식 리더가 여기에 해당합니다. 파일을 훑으며 이벤트를 내보낼 뿐 트리 전체를 메모리에 만들지 않습니다.
명령줄에서는 jq가 두 경우를 모두 다루며, 그 자체로 익혀 둘 가치가 있습니다. jq '.items[] | {id, name}' big.json 이면 문서를 편집기에 올리지 않고도 필요한 부분만 뽑아낼 수 있습니다. --stream 플래그는 jq의 기본 모드조차 메모리를 너무 많이 쓰는 경우까지 감당해 줍니다.
JSON 페이로드의 보안 표면
JSON 파싱 자체는 현대의 어떤 언어에서도 안전합니다. 위험은 그다음에 벌어지는 일에 있습니다. 가장 잘 알려진 것이 프로토타입 오염입니다. JavaScript에서 공격자가 통제하는 JSON을 걸러 내지 않고 객체에 병합하면 __proto__가 설정되어 프로세스 안 모든 객체의 동작이 바뀔 수 있습니다. 깊은 병합 유틸리티들은 이 버그를 여러 차례 출시했고, 방어책은 그런 키를 명시적으로 거부하거나 프로토타입이 없는 객체를 쓰는 것입니다.
JSON을 절대 평가하지 마십시오. JSON.parse가 없던 시절에는 eval로 파싱하는 것이 실제 관행이었지만, 그것은 들어온 것을 무엇이든 실행합니다. 오늘날 데이터에 eval을 쓰는 코드는 취향 문제가 아니라 지적 사항입니다.
알아 둘 만한 작은 문제가 두 가지 더 있습니다. 브라우저가 실행하는 콘텐츠 타입으로 JSON 배열을 제공하는 것이 과거 JSON 하이재킹 공격의 토대였고, 일부 API가 여전히 응답 앞에 루프를 깨뜨리는 한 줄을 붙이는 이유가 그것입니다. 그리고 중복 키는 문법상 허용되지만 파서마다 처리 방식이 달라서, 애플리케이션이 결국 읽게 되는 값과 다른 값을 검증기 앞으로 통과시키는 수법에 이용되어 왔습니다.
방언들, 그리고 언제 쓸 것인가
JSON5는 주석, 뒤따르는 쉼표, 따옴표 없는 키, 작은따옴표 문자열을 더합니다. JSONC는 더 작은 변종으로 Visual Studio Code가 설정과 tsconfig.json에 쓰는 것이며, 본질적으로 JSON에 주석을 더한 것입니다. 둘 다 JSON이 아니고, 전용 패키지 없이는 표준 라이브러리에서 파싱되지 않습니다.
중요한 구분은 독자가 누구냐입니다. 사람이 관리하는 파일은 주석에서 엄청난 이득을 보기 때문에 JSON5, JSONC, YAML, TOML 모두 그 자리에서는 합리적입니다. 반면 네트워크를 건너가는 페이로드는 순수한 JSON이어야 합니다. 받는 쪽이 어떤 언어, 어떤 라이브러리 버전일지 알 수 없고, 방언은 상호 운용성 보장을 의존성으로 바꿔 버리기 때문입니다.
설정 파일을 엄격한 파서에 붙여 넣었는데 실패한다면, 대개 그 파일이 잘못된 것이 아니라 방언이라는 뜻입니다. 파서를 통과시키려고 주석을 걷어 내는 것은 누군가의 문서를 잃는 편집이므로, 반드시 사본에서 하십시오.
자주 묻는 질문
- JSON 데이터가 서버로 전송되나요?
- 아닙니다. 모든 처리는 브라우저의 JavaScript로 실행됩니다. 데이터가 기기를 벗어나지 않으므로 API 응답이나 운영 데이터도 안전하게 다룰 수 있습니다.
- 처리할 수 있는 최대 크기가 있나요?
- 별도의 제한은 없습니다. 로컬에서 처리하기 때문에 실질적인 한계는 브라우저 메모리이며, 수 MB 파일도 문제없이 처리됩니다.
- JSON에 오류가 표시되는 이유는 무엇인가요?
- 가장 흔한 원인은 마지막 쉼표, 큰따옴표 대신 작은따옴표 사용, 키에 따옴표 누락입니다. 오류 메시지에 파싱이 실패한 행과 열이 표시됩니다.
마지막 업데이트:
참고 자료
RFC 8259 — JSON최근 변경
- — 실행 가능한 예제, 예상 결과, 제한 사항 및 참고 링크를 추가했습니다.
진행 단계, 예상 결과, 실제 결과를 적어 주세요. 비밀 정보와 개인 정보는 삭제해 주세요.
