좋아, 이 질문은 많은 개발자가 헷갈리는 핵심 포인트이므로
완전히 깔끔하게 정리해줄게.
결론부터 말하면: JSON은 “데이터를 표현하는 텍스트 형식”일 뿐 객체가 아니다.
🎯 핵심 결론 4줄 요약
- JSON은 오직 “문자열 형식(text format)”이다.
즉, 파일·응답·문자열일 뿐 객체가 아니다. - “JSON 객체”라는 표현은 사실 틀린 말이다.
정확한 말은 “JSON 구조를 담고 있는 문자열(JSON text)”. - JavaScript 객체는 실제 메모리에 존재하는 js 엔진의 데이터 구조다.
- JSON 문자열을 파싱(분석)하면 -> JavaScript 객체가 만들어지는 것.
→ 둘은 완전히 다른 것!
1️⃣ JSON이란 무엇인가?
JSON의 정의:
JavaScript Object Notation (자바스크립트 객체 표기법)
데이터를 표현하기 위한 문자열 기반의 표준 포맷(format)
즉 JSON은 문자열 규칙의 집합이다.
JSON은 이런 규칙을 가진 텍스트:
{
"name": "Hong",
"age": 20
}
이것은 사람이 보면 객체처럼 생겼지만(JS 객체 표기법),
브라우저·서버가 받는 건 100% 문자열이다.
예)
"{\"name\":\"Hong\",\"age\":20}"
2️⃣ “JSON 문자열” vs “JavaScript 객체”
✔ JSON 문자열 (text)
"{\"x\":1}"
- 단순한 텍스트 문자열
- 네트워크로 주고받는 데이터
- 저장되는 값
- JS 엔진은 이걸 객체로 인식하지 않음
✔ JavaScript 객체 (in-memory object)
{ x: 1 }
- 메모리에 실제로 존재하는 구조체
- 속성 접근 가능(x.y)
- 프로토타입 체인을 가짐
- 메서드를 가짐 (toString 등)
3️⃣ JSON 문자열을 파싱 → JavaScript 객체 생성
예:
JSON.parse('{"x":1}')
→ { x: 1 }. // JS 객체
반대로:
JSON.stringify({ x: 1 })
→ '{"x":1}' // JSON 문자열
즉:
| JSON(string) | JS Object |
| 저장용 | 실행/조작용 |
| 텍스트 | 메모리 구조 |
| 네트워크용 | 프로그램 내부용 |
| 따옴표 규칙 강제 | 규칙 자유로움 |
4️⃣ “JSON 객체”라는 말은 틀린 표현이다
많은 사람들이 이렇게 말함:
- “JSON 객체”
- “JSON 형태의 객체”
하지만 기술적으로 정확한 표현은:
- JSON 문자열(JSON text)
- JSON 데이터(JSON formatted string)
왜냐하면 JSON은 실제로는 객체가 아니기 때문.
기술적으로 ECMAScript 명세에서는 이렇게 정의함:
JSON is a string representation of structured data.
5️⃣ JSON과 JavaScript 객체가 생긴 것이 비슷한 이유
JSON의 문법이 JS 객체 리터럴(Object literal) 문법을 기반으로 만들어졌기 때문.
그래서 생긴 게 비슷함:
JS 객체:
{ x: 1 }
JSON:
{ "x": 1 }
하지만 규칙이 다름:
| 규칙 | JS 객체 | JSON |
| 속성 이름 | 따옴표 없어도 됨 | 반드시 쌍따옴표 |
| 값 | 함수 가능 | 함수 ❌ |
| undefined | 있음 | ❌ |
| Infinity, NaN | 있음 | ❌ |
| 주석 | 가능 | ❌ |
즉, JSON은 더 엄격한 텍스트 규칙이다.
6️⃣ 최종적으로 정리하면
✔ JSON은 “문자열”이다
파일, 네트워크 응답, 텍스트로 존재한다.
✔ JavaScript 객체는 “메모리의 실제 객체”이다
프로토타입·메서드·참조 등이 존재.
✔ JSON 문자열을 → 파싱하면 → JS 객체가 됨
그래서 둘이 “생긴 건 비슷하지만 완전히 다른 존재”.
📌 아주 짧게 요약
"JSON은 객체처럼 생긴 문자열일 뿐이다."
"JS 객체는 진짜 객체다."
"res.json()은 JSON 문자열을 JS 객체로 바꾼다."
원하면:
- JSON의 전체 문법 규칙
- 왜 JSON은 프로토타입이 없는가
- JSON.stringify 커스텀 replacer
- JSON.parse reviver 함수
이런 것들도 자세히 설명해줄게!
Q. 파싱
좋아, "파싱(parsing)"이란 무엇인가를 가장 직관적으로, 어려운 말 절대 없이 설명해줄게.
🎯 아주 간단한 정의
파싱 =
어떤 형식의 “문자열”을 → 의미 있는 구조(데이터)로 분석/변환하는 과정.
즉 문자열을 해석해서 구조화하는 것.
🧠 한 줄로 요약하면
“문자열을 읽어서 → 컴퓨터가 이해할 수 있는 데이터 구조로 바꾸는 것”
이게 파싱이다.
📌 예시 1: JSON 파싱
JSON 문자열:
"{\"name\": \"Tom\", \"age\": 20}"
이건 그냥 문자의 나열이다.
이걸 JS 객체로 변환하는 게 파싱:
JSON.parse("{\"name\": \"Tom\", \"age\": 20}")
→ { name: "Tom", age: 20 }
즉 문자열을 → 객체로 변환한 것.
📌 예시 2: URL 파싱
문자열 URL:
https://example.com:3000/path?q=10
이걸 브라우저는 이렇게 구분한다:
- scheme: https
- host: example.com
- port: 3000
- path: /path
- query: q=10
브라우저가 이 문자열을 해석해서 쪼개는 것 = URL parsing
📌 예시 3: HTML 파싱
HTML 문자열:
<div>Hello</div>
브라우저는 이걸 읽어 div DOM 요소를 만든다.
이 과정 = HTML 파싱
📌 예시 4: 숫자 파싱
문자열 "123" 을 숫자 123 으로 바꾸는 것:
parseInt("123") → 123
이것도 파싱이다.
📌 파싱이란 결국…
✔ 문자열을 단순 문자 덩어리로 읽는 게 아니라
✔ 의미 있는 “구조”로 변환하는 것.
그래서 파서는 다음을 해야 한다:
- 문자 하나하나 읽기
- 문법에 맞는지 검사하기
- 구조 분석하기(트리 만들기 등)
- 최종적으로 데이터 구조 / 객체로 변환
📌 왜 JSON을 파싱해야 할까?
서버는 항상 JSON을 문자열로 보낸다:
{"x":1}
이건 사람이 보면 객체처럼 보이지만,
컴퓨터 입장에서는 그냥 텍스트일 뿐.
그래서 이걸 JS 객체로 만들려면 파싱이 필요:
📌 비유로 설명하면
문자열은 레시피 책이고
파싱은 레시피를 읽어서 -> 실제 음식 재료/구조를 만드는 과정이다.
🔥 진짜로 완전 짧게 정리하면
파싱 = 텍스트를 의미 있는 데이터로 바꾸는 것.
원하면:
- 파싱 알고리즘(토큰화, AST 생성 과정)
- 파싱 오류가 왜 발생하는지
- 브라우저의 HTML 파서 동작 과정
이런 것도 더 깊게 알려줄게!
res.json() 은 **fetch()의 응답(Response 객체)**에 있는 메서드로,
서버에서 받은 응답 바디(body)를 -> JSON으로 파싱해서 -> JavaScript 객체로 변환해주는 함수야.
이게 어떤 식으로 동작하는지 정확히 설명해줄게.
✅ 1. res.json() 의 정확한 의미
fetch 후 서버 응답 객체는 Response 타입이야:
fetch("/api/user")
.then(res => res.json()) // ← 이게 JSON 파싱
.then(data => console.log(data));
fetch("/api/user")
.then(res => res.json()) // ← 이게 JSON 파싱
.then(data => console.log(data));
res.json() 은 다음 두 일을 함:
✔ 1) 응답 body 스트림을 모두 읽는다
(응답이 조각(chunk)으로 오면 모두 합침)
✔ 2) 그 문자열을 JSON.parse() 로 파싱한다
즉:
JSON.parse(responseText)
과 동일한 작업을 한다.
🧠 중요한 포인트: res.json()은 Promise를 반환한다
즉, res.json()은 즉시 결과 객체가 아니라 **비동기(Promise)**야.
const data = res.json(); // ❌ data는 아직 데이터가 아니라 Promise
맞는 코드는:
res.json()
.then(data => { console.log(data); });
또는 async/await:
const res = await fetch("/api/user");
const data = await res.json();
console.log(data);
⚠ res.json()은 응답 body가 JSON이 아닐 때 에러 남
서버가 다음 같은 내용을 보냈는데:
Hello World
이걸 .json()으로 읽으면 오류:
Unexpected token H in JSON at position 0
그래서 종종 응답 타입 체크 후 json() 호출하기도 함:
if (res.headers.get("content-type")?.includes("application/json")) {
const data = await res.json();
}
🎯 res.json() >= JSON.parse()보다 안전하고 편한 이유
✔ fetch는 응답 body가 “스트림”이라 json()이 필요함
단순히 문자열이 아님 → 네트워크로 들어오는 스트림.
✔ JSON을 문자열로 먼저 받지 않아도 됨
XHR에서는:
JSON.parse(xhr.responseText)
fetch는:
await res.json();
이 자체로 스트림 → 문자열 → 객체 변환이 이루어짐.
🔍 Response 객체에는 json() 말고도 다른 파서들도 있어
| 메서드 | 설명 |
| res.json() | JSON → JS 객체 |
| res.text() | 문자열 그대로 반환 |
| res.blob() | 이미지/파일 blob |
| res.arrayBuffer() | 바이너리 raw 데이터 |
| res.formData() | multipart/form-data 응답 처리 |
즉, 서버가 보내는 데이터 타입에 따라 골라쓰는 것.
예)
이미지라면:
const imgBlob = await res.blob();
텍스트라면:
const text = await res.text();
⭐ 정리
res.json()은:
- fetch Response의 메서드
- 응답 body 스트림을 완전히 읽고
- JSON.parse()를 적용하며
- Promise로 결과 객체를 반환하는 함수
한 줄로 적으면:
Response body → 스트림을 읽음 → 문자열로 합침 → JSON.parse() → JS 객체 반환
원하면:
- fetch의 body 스트림 구조
- 왜 json()만 먼저 한 번만 호출할 수 있는지
- fetch와 XHR의 응답 파싱 차이
도 설명해줄게!
Q. JSON 문자열 vs JS 객체
좋아, 이 부분은 “JSON 문자열” 과 “JavaScript 객체(진짜 객체)” 를 구분하면 바로 이해된다.
지금 헷갈린 지점은 JSON ≠ JavaScript 객체 라는 사실 때문이야.
🎯 핵심 결론
서버에서 보내는 JSON은 “문자열”이다.
res.json() 은 이 문자열을 -> 자바스크립트 객체로 변환(parse) 하는 함수다.
즉:
- 서버 → JSON 문자열
- 브라우저(fetch) → JSON 문자열을 객체로 파싱
이 과정이 res.json() 이 하는 일.
1️⃣ 서버에서 보내는 건 “JSON 객체”가 아니라 “JSON 문자열”
서버는 실제로 이렇게 보냄:
{ "name": "홍길동", "age": 20 }
이것은 그냥 텍스트 문자열임
예를 들면:
"{\"name\":\"홍길동\",\"age\":20}"
HTTP 응답 바디는 기본적으로 문자열 데이터이다.
(바이너리, 스트림일 수도 있지만 기본은 문자열)
JSON 형식일 뿐이지 자바스크립트 객체는 절대 아니다.
2️⃣ “JSON으로 파싱한다”는 말의 진짜 의미
✔ 문자열(JSON text)을
✔ JavaScript 객체로 바꾸는 것
즉:
"{\"name\": \"홍길동\"}" ← JSON 문자열
→ JSON.parse()
→ { name: "홍길동" } ← JavaScript 객체
그 변환을 fetch의 res.json()이 해준다.
3️⃣ res.json() 의 내부는 결국 JSON.parse
직접 보면 느낌이 잡혀.
const response = await fetch("/api");
const obj = await response.json();
이때 response.json() 은
- 응답 바디를 읽는다 → 문자열
- JSON.parse(문자열)를 호출한다 → JS 객체 반환
즉:
response.json() ≈ JSON.parse(responseBody)
4️⃣ 그래서 응답 바디가 JSON 형식이 아니면 오류
예:
응답 바디가:
Hello World
이런 텍스트라면 JSON.parse 가 실패함.
→ res.json() 도 똑같이 에러 발생.
즉 "JSON 아닌걸 JSON으로 파싱"하려 했으니까 당연한 에러.
5️⃣ 왜 이렇게 설계했을까?
HTTP 응답은 기본적으로 "문자열"이기 때문.
브라우저는 다음을 구분하지 못함:
- 이것이 JSON 객체인지
- 단순 텍스트인지
오직 “문자열 + Content-Type 헤더”만 보고 결정 가능.
서버가 응답 헤더에 이렇게 보내면:
Content-Type: application/json
브라우저는 "아 이것 JSON이겠구나" 정도로 추측할 뿐…
그래서 실제 파싱은 개발자가 res.json()으로 직접 해야 한다.
6️⃣ 진짜 예시로 더 확실하게
서버 응답:
{"x":1,"y":2}
브라우저가 실제로 받은 것은:
"{"x":1,"y":2}"
↑
문자열
res.json() 실행 후:
{ x: 1, y: 2 }
↑
객체
문자열 → 객체 변환이 발생했지?
그래서 "JSON을 JSON으로 파싱한다"가 아니라
JSON 문자열 → JavaScript 객체로 파싱한다가 정확한 표현이야.
📌 마지막 정리
서버:
- JSON은 항상 “문자열(text)”이다.
브라우저(fetch):
- 응답은 문자열로 받아진다.
- res.json() = JSON 문자열 → JS 객체로 변환
- 응답이 JSON 형식이 아니면 에러.
원하면:
- res.text(), res.blob(), res.arrayBuffer() 차이
- Content-Type 헤더와 파싱 관계
- JSON과 JavaScript 객체의 차이(규칙 vs 실제 객체)
이런 것도 더 설명해줄게!
Q. parseInt()
parseInt() 는 문자열(string)을 -> 정수(integer) 숫자로 바꿔주는 JavaScript 내장 함수야.
📌 1. 기본 개념
parseInt("123") // → 123 (숫자)
문자열을 읽어서 앞에서부터 숫자라고 해석할 수 있는 부분만 정수로 변환한다.
📌 2. 중요한 특징
✔ 앞에서부터 숫자로 읽을 수 있는 부분까지만 변환
parseInt("123abc") // → 123
parseInt("10px") // → 10
parseInt("3.14") // → 3 (정수만!)
숫자로 못 읽는 지점에서 멈춘다.
✔ 첫 글자가 숫자가 아니면 NaN
parseInt("abc123") // → NaN
✔ 공백은 무시하고 시작
parseInt(" 42") // → 42
✔ 정수만 변환한다
소수점은 정수 부분만 빼고 버림.
parseInt("5.99") // → 5
소수점을 제대로 처리하려면 parseFloat() 사용.
📌 3. 진수(radix) 지정 가능
두 번째 인자를 주면 문자열을 몇 진수로 해석할지 정할 수 있다.
parseInt("FF", 16) // → 255 (16진수)
parseInt("1010", 2) // → 10 (2진수)
parseInt("20", 8) // → 16 (8진수)
📌 4. 숫자로만 이루어진 문자열일 때는 Number() 로도 가능
Number("123") // → 123
하지만 Number() 는 문자열 전체가 완벽한 숫자여야 한다.
Number("10px") // → NaN
parseInt("10px") // → 10 ← 더 관대함
📌 5. parseInt() 언제 쓰나?
✔ CSS 값에서 숫자만 뽑고 싶을 때
parseInt("20px") // → 20
✔ 서버에서 받은 문자열 형태 숫자를 정수로 바꿀 때
✔ 사용자가 입력한 숫자 문자열 처리할 때
✔ 진수 변환할 때
📌 6. 왜 “parse”라는 단어를 쓰냐?
"parse" = 문자열을 읽어서 의미 있는 구조로 분석하는 것
즉 "123abc" 라는 문자열에서 “123이라는 정수"를 해석해내는 과정이기 때문.
필요하면 parseFloat() / Number() / + 연산자 숫자 변환 차이도 자세히 비교해줄게!
Q. "{\"name\":\"홍길동\",\"age\":20}"
서버가 보내는 JSON 문자열과,
이를 JS 코드에서 문자열 리터럴로 표현한 모습이 다르게 보이기 때문에 헷갈릴 수 있어.
결론부터 말하면:
✅ 1. 실제 JSON 문자열은 이렇게 생긴 게 맞다
서버가 보내는 JSON 텍스트:
{"name": "홍길동", "age": 20}
이게 순수한 JSON 문자열이며, 사람이 봐도 자연스럽고 브라우저 네트워크 탭에서도 이렇게 보인다.
이 자체는 그냥 문자열이다.
문자({, }, ", :, ,)로 구성된 텍스트일 뿐.
✅ 2. 그런데 JS 코드 안에서 JSON 문자열을 "문자열 리터럴" 로 표현하려 하면 이렇게 변한다
JS 문자열 안에서는 " 자체가 문자열 끝을 의미하기 때문에 -> 이스케이프(\) 해야 한다.
그래서 JS 파일, 콘솔, 코드 속에서 JSON을 문자열로 적으면 이렇게 보인다:
"{"name": "홍길동", "age": 20}"
"{\"name\":\"홍길동\",\"age\":20}"
여기서 \" 는 “JS 문자열에서 따옴표를 표현하기 위해 이스케이프한 것"이지 JSON의 실제 내용이 아니다.
🔍 즉, 차이는 "표현 방식"의 차이일 뿐
실제 JSON 텍스트:
{"name":"홍길동","age":20}
JavaScript 문자열 리터럴로 JSON 텍스트를 나타낸 모습:
"{\"name\":\"홍길동\",\"age\":20}"
두 번째에서 " 앞에 \ 가 들어가는 이유는:
- JS에서 " " 로 문자열을 감쌀 때
- 내부 " " 를 그대로 넣으면 문자열이 끝났다고 착각하므로
- \" 로 "문자를 이스케이프" 해야 한다
🔥 예시 비교
1) 서버 응답(JSON raw)
{"ok":true,"user":"홍길동"}
2) JS에서 변수에 담으면
const jsonText = "{\"ok\":true,\"user\":\"홍길동\"}";
3) 실제로 이걸 JSON.parse 하면
JSON.parse(jsonText) // → { ok: true, user: "홍길동" }
✅ 더 쉽게 말해볼게
✔ 서버가 보내는 건 “순수 문자열” ⇒ 이스케이프 필요 없음
✔ JS 코드에서 문자열로 적을 때는 "문자열 문법" 때문에 이스케이프가 들어감
=> 그래서 \" 가 생기는 것뿐
원하면
- 문자열 리터럴에서 언제 이스케이프해야 하는지
- JSON.parse() 동작 과정
도 자세히 설명해줄게!
Q. 리터럴 / 이스케이프
좋아, 지금 헷갈리는 건 “리터럴(literal)” 과 “이스케이프(escape)” 라는 개념이야. 차근차근 설명해줄게.
1️⃣ 리터럴(Literal)
정의:
프로그래밍 언어에서 그대로 값을 나타내는 표기를 리터럴이라고 한다.
즉, 변수에 담거나 연산할 때 코드 안에 직접 적힌 값.
예시
42 // 숫자 리터럴
"Hello" // 문자열 리터럴
true // 불리언 리터럴
null // null 리터럴
[1, 2, 3] // 배열 리터럴
{a:1, b:2} // 객체 리터럴
즉, 코드 안에서 직접 작성된 값이 바로 리터럴.
2️⃣ 이스케이프(Escape)
정의:
문자열 안에서 특별한 의미를 가진 문자를 문자 그대로 사용하고 싶을 때
앞에 \(백슬래시)를 붙여 “탈출(escape)”시키는 것.
왜 필요한가?
문자열은 기본적으로 큰따옴표 " " 나 작은따옴표 ' ' 로 감싼다.
그 안에 또 같은 따옴표가 들어가면 문자열이 끝났다고 인식해버림.
예시
// ❌ 오류
const str = "He said "Hello" to me";
// ✅ 올바른 방법: 이스케이프
const str = "He said \"Hello\" to me";
console.log(str); // He said "Hello" to me
3️⃣ 자주 쓰는 이스케이프 문자
| 이스케이프 | 의미 |
| \" | 큰따옴표 문자 자체 |
| \' | 작은따옴표 문자 자체 |
| \\ | 백슬래시 문자 자체 |
| \n | 줄바꿈(new line) |
| \t | 탭(tab) |
| \r | 캐리지 리턴 |
| \uXXXX | 유니코드 문자 |
4️⃣ JSON과 이스케이프
JSON 문자열을 JS 코드에서 리터럴(JSON 문자열 모양 그대로)로 쓸 때 이스케이프가 필요함.
// 실제 JSON 텍스트 (서버가 보내는 것)
{"name": "홍길동", "age": 20}
// JS 문자열 리터럴로 작성
const jsonText = "{\"name\":\"홍길동\",\"age\":20}";
// 내부 큰따옴표를 \"로 이스케이프
🔥 핵심 정리
- 리터럴: 코드 안에 직접 적힌 값 자체 (42, "Hello", [1,2,3])
- 이스케이프: 문자열 안에서 특별 문자를 문자 그대로 쓰고 싶을 때 \ 붙이는 것 (\", \n)
즉, JSON 문자열을 코드 안에 쓰려면 리터럴 안에서 이스케이프를 해주는 거야.
원하면, 내가 JSON 문자열 → JS 문자열 리터럴 → JS 객체 변환 과정을 그림으로 순서대로 보여줄 수도 있어.
그거 보여줄까?
'IT 인터넷' 카테고리의 다른 글
| 웹뷰 란? 크롬 웹뷰 vs 사파리 웹뷰 (0) | 2025.10.07 |
|---|---|
| SDK 란? (Software Development Kit):: .jar, .aar (0) | 2025.10.07 |
| SSO (Single Sing-On) 로그인 방식 (0) | 2025.10.03 |
| TCP/IP 란? (0) | 2025.10.02 |
| 프록시 란? (proxy) :: 일반 프록시 vs 리버스 프록시 (0) | 2025.10.02 |
| 운영체제:: 리눅스 vs 유닉스 vs 윈도우 (0) | 2025.10.02 |
| HTML vs XML (0) | 2025.09.30 |
| 컴퓨터 숫자 표현 방식 :: 2진수, 10진수, 16진수... 그외 1진수 3진수 5진수 8진수 12진수 60진수 (0) | 2025.09.30 |