WebPiki
tutorial

JSON이란? 웹 개발자가 매일 쓰는 데이터 포맷 완전 정리

JSON의 기본 구조, 데이터 타입, API 활용, 흔한 실수까지. 프론트엔드와 백엔드를 잇는 JSON의 모든 것.

웹 개발을 하면 JSON을 안 쓸 수가 없다. API 응답도 JSON, 설정 파일도 JSON, 로컬 스토리지에 저장하는 것도 JSON. 프론트엔드와 백엔드 사이 대부분의 데이터 교환이 JSON으로 이루어진다.

JSON 기본

JSON(JavaScript Object Notation)은 데이터를 저장하고 교환하기 위한 텍스트 포맷이다. 이름에 JavaScript가 들어가지만 언어에 독립적이다. Python, Java, Go, C# 어디서든 쓴다.

기본 구조는 심플하다:

{
  "name": "김개발",
  "age": 28,
  "skills": ["TypeScript", "React", "Node.js"],
  "employed": true,
  "address": null
}

중괄호 {}는 객체, 대괄호 []는 배열. 키는 반드시 큰따옴표로 감싸야 한다. 이게 JavaScript 객체 리터럴과의 가장 큰 차이다. JS에서는 { name: "홍길동" }이 되지만, JSON에서는 { "name": "홍길동" }으로 써야 한다.

데이터 타입 6가지

JSON이 지원하는 타입은 딱 6개다:

타입예시설명
문자열"hello"큰따옴표만 가능
숫자42, 3.14, -1정수, 소수점, 음수
불리언true, false소문자만
nullnull값 없음
객체{ "key": "value" }키-값 쌍
배열[1, 2, 3]순서 있는 값 목록

여기에 없는 것들: undefined, 함수, 날짜 객체, NaN, Infinity. JavaScript에서 JSON.stringify를 쓸 때 이런 값들이 들어있으면 사라지거나 null로 바뀐다.

JSON.stringify({ a: undefined, b: NaN, c: Infinity })
// '{"b":null,"c":null}'
// undefined인 a는 아예 제거됨

API와 JSON

REST API의 세계에서 JSON은 사실상 표준이다. 요청 보낼 때도, 응답 받을 때도 JSON.

// 데이터 보내기
const response = await fetch("/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "홍길동", email: "hong@example.com" }),
});

// 데이터 받기
const data = await response.json();

Content-Type: application/json 헤더를 빼먹으면 서버가 JSON으로 파싱하지 않는 경우가 있다. 꽤 흔한 실수.

JSON vs 다른 포맷

JSON vs XML

XML은 JSON이 나오기 전에 쓰던 포맷이다. 같은 데이터를 표현해보면:

<user>
  <name>김개발</name>
  <age>28</age>
</user>
{
  "name": "김개발",
  "age": 28
}

JSON이 훨씬 간결하다. XML은 태그가 중복되니까 데이터 대비 텍스트 양이 많다. 그래서 웹 API가 거의 다 JSON으로 갈아탔다. 다만 XML이 아직 쓰이는 곳도 있다 — SOAP 웹 서비스, RSS 피드, SVG 같은 분야.

JSON vs YAML

YAML은 JSON의 상위 집합이다. 유효한 JSON은 전부 유효한 YAML이기도 하다.

name: 김개발
age: 28
skills:
  - TypeScript
  - React

설정 파일에서는 YAML이 더 많이 쓰인다. Kubernetes, GitHub Actions, Docker Compose 전부 YAML. 사람이 읽고 쓰기에 YAML이 편하고, JSON은 기계가 주고받기에 편하다.

JSON vs TOML

TOML은 설정 파일 전용 포맷이다. Rust의 Cargo.toml이 대표적.

[database]
host = "localhost"
port = 5432

단순 설정에는 TOML이 깔끔하지만, 중첩이 깊어지면 JSON보다 오히려 읽기 어려워진다.

흔한 실수들

쉼표 문제. 마지막 항목 뒤에 쉼표를 붙이면 JSON 파싱 에러가 난다. JavaScript 객체에서는 되지만, JSON 스펙에서는 안 된다.

{
  "a": 1,
  "b": 2,  // ← 이 쉼표가 에러
}

작은따옴표. JSON은 큰따옴표만 허용한다. {'name': 'test'}는 유효한 JSON이 아니다.

주석. JSON에는 주석이 없다. // comment/* comment */도 안 된다. 설정 파일로 쓸 때 불편한 부분인데, 그래서 JSONC(JSON with Comments)라는 변형이 생겼다. VS Code의 settings.json이 JSONC를 쓴다.

큰 숫자. JSON의 숫자는 IEEE 754 부동소수점으로 파싱된다. 9007199254740993 같은 큰 정수는 정밀도가 깨질 수 있다. 이런 경우 문자열로 전달하는 게 안전하다. 트위터 API가 ID를 "id_str": "12345" 형태로 제공하는 이유가 이거다.

JSON 다루기 팁

JSON.stringify의 세 번째 인자. 들여쓰기를 지정할 수 있다.

JSON.stringify(data, null, 2);
// 2칸 들여쓰기로 예쁘게 출력

replacer 함수. 두 번째 인자로 필터링이나 변환이 가능하다.

JSON.stringify(data, (key, value) => {
  if (key === "password") return undefined; // 비밀번호 제거
  return value;
});

JSON.parse의 reviver. 파싱할 때 값을 변환할 수 있다.

JSON.parse(text, (key, value) => {
  if (key === "date") return new Date(value);
  return value;
});

날짜 문자열을 Date 객체로 변환할 때 유용하다. JSON에는 날짜 타입이 없으니까 이런 처리가 필요한 경우가 많다.

JSON 스키마

JSON Schema는 JSON 데이터의 구조를 정의하는 표준이다. TypeScript의 인터페이스와 비슷한 역할을 한다.

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name"]
}

API 문서화, 설정 파일 검증, 코드 생성 등에 쓰인다. VS Code에서 JSON 파일을 편집할 때 자동완성이 되는 것도 JSON Schema 덕분이다.

JSON 디버깅

API 응답이 한 줄로 뭉쳐서 내려오면 읽기가 힘들다. 보통 브라우저 개발자 도구나 jq 같은 CLI 도구를 쓰는데, 웹에서 바로 확인하고 싶을 때는 JSON 포맷터를 쓰면 된다. 붙여넣기만 하면 들여쓰기가 정리되고, 문법 오류가 있는지도 바로 알 수 있다.

# CLI에서는 jq가 편하다
curl -s https://api.example.com/users | jq .

# 특정 필드만 뽑기
cat response.json | jq '.data[] | {name, email}'

결국 JSON은 별거 아니다. 중괄호, 대괄호, 큰따옴표. 이 세 가지만 기억하면 기본은 된다. 나머지는 쓰다 보면 손에 익는다.

#JSON#데이터포맷#API#웹개발#JavaScript

관련 글