Ver3.5 JSON 데이터 교환과 API 통신을 위한경량 데이터 포맷 실전 가이드

JSON 데이터 교환과 API 통신을 위한
경량 데이터 포맷 실전 가이드
야 솔직히 말해봐ㅋㅋ 개발 처음 시작했을 때 JSON 보고 "이게 뭐야 괄호 잔치야?" 했던 사람 손 들어봐 🙋
근데 지금은? API 통신할 때 JSON 없으면 진짜 아무것도 못 하잖아ㅋㅋㅋ 그만큼 JSON은 현대 웹 개발의 핵심 중의 핵심이야. 프론트엔드, 백엔드, 모바일 앱, IoT까지 안 쓰이는 데가 없음.
이 글에서는 JSON이 뭔지부터 시작해서 API 통신에서 어떻게 쓰이는지, 실무에서 자주 쓰는 패턴까지 팩트 기반으로 빡세게 다뤄볼 거야. 채팅하듯 편하게 읽어봐! 😎
📦 1. JSON이 뭔데? 기초부터 제대로 알자
JSON은 JavaScript Object Notation의 약자야. 직역하면 "자바스크립트 객체 표기법"인데, 이름에 JavaScript가 들어가 있다고 해서 JS 전용이냐? 절대 아님!
JSON은 언어 독립적인 데이터 포맷이야. Python, Java, C#, Go, Ruby, PHP... 어떤 언어에서도 파싱하고 생성할 수 있어. 그냥 텍스트 기반의 데이터 표현 방식이거든.
더글라스 크록포드(Douglas Crockford)가 2001년에 처음 제안했고, 2013년에 ECMA 표준으로 공식 채택됐어.
사람이 읽기 쉽고(human-readable), 기계가 파싱하기도 쉬운(machine-parseable) 게 핵심 장점이야.
🤔 왜 JSON이 이렇게 대세가 됐냐고?
예전에는 XML이 데이터 교환의 왕이었어. 근데 XML은 태그가 너무 많아서 데이터 크기가 커지고, 파싱도 복잡했거든. JSON은 그 문제를 싹 해결했지.
보이지? 같은 데이터인데 JSON이 훨씬 간결하잖아ㅋㅋ 이게 바로 JSON이 XML을 밀어낸 이유야.
📝 2. JSON 문법 - 이것만 알면 끝
JSON 문법은 진짜 단순해. 6가지 데이터 타입만 지원하거든. 근데 이 6가지 조합으로 세상 모든 데이터를 표현할 수 있음ㅋㅋ
🔢 JSON이 지원하는 데이터 타입
| 타입 | 예시 | 설명 |
|---|---|---|
| 문자열 (String) | "안녕하세요" |
반드시 큰따옴표(" ") 사용 |
| 숫자 (Number) | 42, 3.14, -7 |
정수, 실수, 음수 모두 가능 |
| 불리언 (Boolean) | true, false |
소문자로만 작성 |
| null | null |
값이 없음을 표현 |
| 배열 (Array) | [1, 2, 3] |
대괄호로 감싸는 순서 있는 목록 |
| 객체 (Object) | {"key": "value"} |
중괄호로 감싸는 키-값 쌍 |
undefined는 지원 안 해! JavaScript에서 undefined를 JSON으로 변환하면 그냥 사라지거나 null로 처리돼. 이거 모르면 나중에 버그 잡다가 머리 뜯게 됨ㅋㅋ
📋 JSON 문법 규칙 - 이거 틀리면 파싱 에러남
2️⃣ 마지막 항목에 쉼표(trailing comma) 금지
3️⃣ 주석(comment) 사용 불가 (// 이런 거 ❌)
4️⃣ 문자열 내 특수문자는 이스케이프 처리 필요 (\n, \t, \" 등)
5️⃣ 숫자는 8진수, 16진수 표현 불가 (0x1F 이런 거 ❌)
// ❌ 잘못된 JSON (이렇게 쓰면 파싱 에러!)
{
'name': '홍길동', // 작은따옴표 사용 금지
"age": 25, // 마지막 쉼표 금지
// 주석도 금지 // 주석 사용 금지
}
// ✅ 올바른 JSON
{
"name": "홍길동",
"age": 25,
"isActive": true,
"score": null,
"skills": ["Python", "JavaScript"],
"address": {
"city": "서울",
"district": "강남구"
}
}
🔤 이스케이프 문자 - 이것도 알아야 해
| 이스케이프 시퀀스 | 의미 |
|---|---|
\" |
큰따옴표 |
\\ |
백슬래시 |
\/ |
슬래시 |
\n |
줄바꿈 |
\r |
캐리지 리턴 |
\t |
탭 |
\uXXXX |
유니코드 문자 (예: \uD55C = 한) |
🌐 3. API 통신에서 JSON이 어떻게 쓰이냐고?
자 이제 진짜 핵심으로 들어가보자. JSON이 API 통신에서 어떻게 활용되는지 실제로 뜯어볼 거야.
🔄 REST API와 JSON의 관계
REST API는 HTTP 프로토콜을 기반으로 클라이언트와 서버가 데이터를 주고받는 방식이야. 그리고 그 데이터를 담는 그릇이 바로 JSON이지.
📨 HTTP 헤더에서 JSON 설정하기
API 통신할 때 JSON을 주고받으려면 HTTP 헤더에 Content-Type을 제대로 설정해야 해. 이거 빠뜨리면 서버가 데이터를 못 읽는 경우가 생김ㅋㅋ
// 요청 헤더 설정
Content-Type: application/json // 내가 보내는 데이터가 JSON이야
Accept: application/json // 나는 JSON으로 응답받고 싶어
// JavaScript fetch API 예시
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer your-token-here'
},
body: JSON.stringify({
name: '홍길동',
email: 'hong@example.com',
age: 25
})
})
.then(response => response.json()) // 응답을 JSON으로 파싱
.then(data => console.log(data))
.catch(error => console.error('에러:', error));
🔁 JSON 직렬화(Serialization)와 역직렬화(Deserialization)
이 개념 모르면 API 개발할 때 진짜 헷갈려. 간단하게 설명할게.
프로그램의 객체/데이터를 JSON 문자열로 변환하는 것
JSON.stringify(obj) → JavaScriptjson.dumps(obj) → PythonObjectMapper.writeValueAsString() → Java
JSON 문자열을 프로그램의 객체/데이터로 변환하는 것
JSON.parse(str) → JavaScriptjson.loads(str) → PythonObjectMapper.readValue() → Java
// JavaScript에서 직렬화/역직렬화
// 객체 → JSON 문자열 (직렬화)
const user = { name: "홍길동", age: 25, skills: ["Python", "JS"] };
const jsonString = JSON.stringify(user);
// 결과: '{"name":"홍길동","age":25,"skills":["Python","JS"]}'
// 예쁘게 출력하고 싶을 때 (들여쓰기 2칸)
const prettyJson = JSON.stringify(user, null, 2);
// JSON 문자열 → 객체 (역직렬화)
const parsed = JSON.parse(jsonString);
console.log(parsed.name); // "홍길동"
// Python에서
import json
# 직렬화
data = {"name": "홍길동", "age": 25}
json_str = json.dumps(data, ensure_ascii=False) # 한글 깨짐 방지
# 역직렬화
parsed = json.loads(json_str)
print(parsed["name"]) # 홍길동
📐 4. JSON Schema - 데이터 유효성 검사의 핵심
API 개발하다 보면 "이 JSON 데이터가 올바른 형식인지 어떻게 검증하지?" 라는 고민이 생겨. 그때 쓰는 게 바로 JSON Schema야!
JSON Schema는 JSON 데이터의 구조와 유효성을 정의하는 메타 스키마야. 쉽게 말하면 "이 JSON은 이런 형식이어야 해"를 명세하는 문서라고 보면 돼.
// 사용자 데이터 JSON Schema 예시
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "사용자 정보 스키마",
"type": "object",
"required": ["name", "email", "age"],
"properties": {
"name": {
"type": "string",
"minLength": 2,
"maxLength": 50,
"description": "사용자 이름"
},
"email": {
"type": "string",
"format": "email",
"description": "이메일 주소"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150,
"description": "나이"
},
"skills": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"description": "보유 기술 목록"
},
"isActive": {
"type": "boolean",
"default": true
}
},
"additionalProperties": false
}
🛡️ JSON Schema 주요 키워드
| 키워드 | 설명 | 예시 |
|---|---|---|
type |
데이터 타입 지정 | "type": "string" |
required |
필수 필드 목록 | "required": ["name", "email"] |
minimum/maximum |
숫자 범위 제한 | "minimum": 0, "maximum": 100 |
minLength/maxLength |
문자열 길이 제한 | "minLength": 2 |
pattern |
정규식 패턴 검증 | "pattern": "^[0-9]{10,11}$" |
enum |
허용 값 목록 | "enum": ["admin", "user", "guest"] |
format |
특정 형식 검증 | "format": "date-time" |
$ref |
다른 스키마 참조 | "$ref": "#/$defs/Address" |
⚡ 5. 실무에서 자주 쓰는 JSON API 응답 패턴
실제 프로젝트에서 API 응답 JSON을 어떻게 설계하느냐에 따라 프론트엔드 개발 편의성이 완전 달라져. 업계에서 많이 쓰는 패턴들 알려줄게.
📦 패턴 1: 표준 응답 래퍼 (Standard Response Wrapper)
가장 많이 쓰는 패턴이야. 성공/실패 여부, 메시지, 실제 데이터를 일관된 구조로 감싸는 방식.
// ✅ 성공 응답
{
"success": true,
"status": 200,
"message": "사용자 정보를 성공적으로 조회했습니다.",
"data": {
"id": 1,
"name": "홍길동",
"email": "hong@example.com"
},
"timestamp": "2024-01-15T10:30:00Z"
}
// ❌ 실패 응답
{
"success": false,
"status": 404,
"message": "사용자를 찾을 수 없습니다.",
"error": {
"code": "USER_NOT_FOUND",
"details": "ID 999에 해당하는 사용자가 존재하지 않습니다."
},
"timestamp": "2024-01-15T10:30:00Z"
}
📋 패턴 2: 페이지네이션 응답 (Pagination Response)
목록 데이터를 가져올 때 한 번에 다 가져오면 서버 터짐ㅋㅋ 그래서 페이지 단위로 나눠서 가져오는 패턴이야.
// 페이지네이션 응답 구조
{
"success": true,
"data": {
"items": [
{ "id": 1, "name": "홍길동" },
{ "id": 2, "name": "김철수" }
],
"pagination": {
"currentPage": 1,
"totalPages": 10,
"totalItems": 98,
"itemsPerPage": 10,
"hasNextPage": true,
"hasPrevPage": false
}
}
}
// 커서 기반 페이지네이션 (SNS에서 많이 씀)
{
"data": [...],
"cursor": {
"next": "eyJpZCI6MTAwfQ==", // Base64 인코딩된 커서
"hasMore": true
}
}
🚨 패턴 3: 에러 응답 표준화 (RFC 7807 Problem Details)
에러 응답도 표준이 있어! RFC 7807에서 정의한 "Problem Details for HTTP APIs" 형식이야. 대형 서비스들이 많이 채택하고 있음.
// RFC 7807 Problem Details 형식
{
"type": "https://example.com/errors/validation-error",
"title": "유효성 검사 실패",
"status": 422,
"detail": "요청 데이터가 올바르지 않습니다.",
"instance": "/api/users/create",
"errors": [
{
"field": "email",
"message": "올바른 이메일 형식이 아닙니다.",
"rejectedValue": "not-an-email"
},
{
"field": "age",
"message": "나이는 0 이상이어야 합니다.",
"rejectedValue": -5
}
]
}
🔗 패턴 4: HATEOAS (Hypermedia as the Engine of Application State)
REST API의 성숙도 레벨 3에 해당하는 패턴이야. 응답에 관련 링크를 포함시켜서 클라이언트가 다음에 뭘 할 수 있는지 알려주는 방식.
// HATEOAS 응답 예시
{
"id": 1,
"name": "홍길동",
"email": "hong@example.com",
"_links": {
"self": { "href": "/api/users/1" },
"update": { "href": "/api/users/1", "method": "PUT" },
"delete": { "href": "/api/users/1", "method": "DELETE" },
"orders": { "href": "/api/users/1/orders" },
"profile": { "href": "/api/users/1/profile" }
}
}
🚀 6. JSON 성능 최적화 - 이거 모르면 느린 API 만듦
JSON 쓰는 건 알겠는데 성능까지 신경 쓰는 개발자가 진짜 고수야ㅋㅋ 실무에서 쓸 수 있는 최적화 기법들 알려줄게.
🔧 실무 최적화 기법 상세
GraphQL이 이 문제를 해결하기 위해 나온 기술이기도 해.
REST API에서는
?fields=id,name,email 같은 쿼리 파라미터로 구현할 수 있어.
Node.js에서는
stream-json 라이브러리로 스트리밍 파싱 가능.Python에서는
ijson 라이브러리 사용하면 메모리 효율적으로 처리 가능.
• MessagePack: JSON과 호환되는 바이너리 포맷, 크기 20~30% 절약
• Protocol Buffers (Protobuf): Google이 만든 바이너리 직렬화, 매우 빠름
• CBOR: Concise Binary Object Representation, IoT에서 많이 씀
• BSON: MongoDB가 사용하는 바이너리 JSON
// NDJSON (Newline Delimited JSON) - 스트리밍에 최적화
// 각 줄이 독립적인 JSON 객체 (대용량 데이터 처리에 유리)
{"id":1,"name":"홍길동","score":95}
{"id":2,"name":"김철수","score":87}
{"id":3,"name":"이영희","score":92}
// Node.js에서 NDJSON 스트리밍 처리
const { createReadStream } = require('fs');
const readline = require('readline');
const rl = readline.createInterface({
input: createReadStream('large-data.ndjson')
});
rl.on('line', (line) => {
const obj = JSON.parse(line);
// 한 줄씩 처리 → 메모리 효율적!
processData(obj);
});
🔒 7. JSON 보안 - 이거 모르면 해킹당함
JSON 쓸 때 보안도 진짜 중요해. 모르고 쓰다가 보안 취약점 생기면 진짜 큰일남ㅋㅋ 주요 보안 이슈들 알아보자.
위험한 코드:
const json = '{"name":"' + userInput + '"}';만약 userInput이
","admin":true,"x":" 라면?→
{"name":"","admin":true,"x":""} 이 되어버림! 😱해결책: 반드시
JSON.stringify() 사용해서 직렬화할 것!
현재는 대부분 해결됐지만, 여전히 JSON 응답은 객체로 감싸는 게 좋은 관행이야.
// ❌ 위험 (구형 환경)[{"id":1,"secret":"xxx"}]// ✅ 안전{"data": [{"id":1,"secret":"xxx"}]}
• 비밀번호 해시값 절대 응답에 포함 금지
• 내부 시스템 정보 (서버 경로, DB 구조 등) 노출 금지
• 개인정보는 마스킹 처리 (예: 전화번호 010-****-5678)
// ✅ 안전한 JSON API 처리 패턴
// 1. 입력 검증 (JSON Schema 활용)
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = {
type: 'object',
required: ['name', 'email'],
properties: {
name: { type: 'string', maxLength: 100 },
email: { type: 'string', format: 'email' }
},
additionalProperties: false // 정의되지 않은 필드 거부
};
const validate = ajv.compile(schema);
const valid = validate(requestBody);
if (!valid) {
throw new Error('유효하지 않은 입력 데이터');
}
// 2. 응답 시 민감 정보 제거
function sanitizeUser(user) {
const { password, internalId, ...safeUser } = user;
return safeUser; // 비밀번호, 내부ID 제외하고 반환
}
// 3. JSON 파싱 에러 처리
try {
const data = JSON.parse(requestBody);
} catch (e) {
return res.status(400).json({
error: '잘못된 JSON 형식입니다.'
});
}
__proto__ 오염(Prototype Pollution) 공격에 취약할 수 있어. 신뢰할 수 없는 소스의 JSON을 파싱할 때는 JSON.parse() 전에 반드시 입력 검증을 해야 해!
💻 8. 언어별 JSON 처리 - 실전 코드 모음
각 언어마다 JSON 처리하는 방법이 조금씩 달라. 자주 쓰는 언어들 기준으로 핵심만 정리해줄게!
🟨 JavaScript / Node.js
// 기본 파싱/직렬화
const obj = JSON.parse('{"name":"홍길동"}');
const str = JSON.stringify(obj, null, 2);
// fetch API로 JSON 받기
const response = await fetch('/api/users');
const data = await response.json();
// axios로 JSON 통신
const { data } = await axios.post('/api/users', {
name: '홍길동',
email: 'hong@example.com'
});
// JSON 깊은 복사 (간단한 방법)
const deepCopy = JSON.parse(JSON.stringify(original));
// ⚠️ 단, undefined, 함수, Symbol은 복사 안 됨!
🐍 Python
import json
import requests
# 기본 파싱/직렬화
data = json.loads('{"name": "홍길동", "age": 25}')
json_str = json.dumps(data, ensure_ascii=False, indent=2)
# 파일에서 JSON 읽기/쓰기
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
with open('output.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# requests로 API 통신
response = requests.post(
'https://api.example.com/users',
json={'name': '홍길동', 'email': 'hong@example.com'}, # json= 파라미터 사용
headers={'Authorization': 'Bearer token'}
)
result = response.json() # 자동으로 JSON 파싱
# dataclass와 JSON 연동
from dataclasses import dataclass, asdict
import json
@dataclass
class User:
name: str
age: int
email: str
user = User(name="홍길동", age=25, email="hong@example.com")
json_str = json.dumps(asdict(user), ensure_ascii=False)
☕ Java (Jackson 라이브러리)
// Maven 의존성
// <dependency>
// <groupId>com.fasterxml.jackson.core</groupId>
// <artifactId>jackson-databind</artifactId>
// <version>2.16.0</version>
// </dependency>
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
// POJO 클래스
public class User {
@JsonProperty("name")
private String name;
@JsonProperty("age")
private int age;
// getter, setter 생략
}
// 직렬화/역직렬화
ObjectMapper mapper = new ObjectMapper();
// 객체 → JSON 문자열
User user = new User("홍길동", 25);
String jsonStr = mapper.writeValueAsString(user);
// JSON 문자열 → 객체
User parsed = mapper.readValue(jsonStr, User.class);
// JSON 문자열 → Map
Map<String, Object> map = mapper.readValue(jsonStr,
new TypeReference<Map<String, Object>>() {});
// Spring Boot에서는 @RestController 사용하면 자동으로 JSON 변환
@RestController
@RequestMapping("/api")
public class UserController {
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
// @RequestBody가 자동으로 JSON → User 변환
return ResponseEntity.ok(userService.save(user));
}
}
🦫 Go
package main
import (
"encoding/json"
"fmt"
)
// 구조체 정의 (json 태그로 필드명 매핑)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"` // 빈 값이면 JSON에서 제외
}
func main() {
// 직렬화 (Marshal)
user := User{Name: "홍길동", Age: 25, Email: "hong@example.com"}
jsonBytes, err := json.Marshal(user)
if err != nil {
panic(err)
}
fmt.Println(string(jsonBytes))
// 역직렬화 (Unmarshal)
jsonStr := `{"name":"김철수","age":30}`
var parsed User
err = json.Unmarshal([]byte(jsonStr), &parsed)
if err != nil {
panic(err)
}
fmt.Println(parsed.Name) // 김철수
}
🛠️ 9. JSON 개발에 유용한 도구들
개발할 때 JSON 관련 도구 잘 쓰면 생산성이 진짜 올라가ㅋㅋ 꼭 알아야 할 도구들 소개할게.
| 도구 | 용도 | 특징 |
|---|---|---|
| JSONLint | JSON 유효성 검사 | 웹 기반, 무료, jsonlint.com |
| jq | CLI JSON 처리 | 터미널에서 JSON 필터링/변환 |
| Postman | API 테스트 | GUI 기반 API 요청/응답 테스트 |
| Swagger/OpenAPI | API 문서화 | JSON Schema 기반 API 스펙 정의 |
| JSON Formatter | JSON 포맷팅 | 가독성 있게 들여쓰기 정렬 |
| quicktype | 타입 생성 | JSON에서 TypeScript/Java 타입 자동 생성 |
| JSON Diff | JSON 비교 | 두 JSON 파일의 차이점 시각화 |
🔍 jq 실전 사용법 - 터미널 JSON 처리의 신
# jq 기본 사용법 (터미널에서)
# JSON 파일 예쁘게 출력
jq '.' data.json
# 특정 필드만 추출
jq '.name' data.json
# 배열에서 특정 필드만 추출
jq '.[].name' users.json
# 조건 필터링 (age가 25 이상인 사용자)
jq '.[] | select(.age >= 25)' users.json
# 필드 변환
jq '{fullName: .name, userAge: .age}' data.json
# API 응답을 jq로 바로 처리
curl -s 'https://api.example.com/users' | jq '.[0].name'
# 배열 길이 확인
jq '. | length' users.json
# 특정 키만 선택해서 새 JSON 생성
jq '{id, name, email}' user.json
⚖️ 10. JSON vs 다른 데이터 포맷 - 언제 뭘 써야 해?
JSON이 최고긴 한데, 모든 상황에서 JSON이 최선은 아니야. 상황에 따라 다른 포맷이 더 나을 수도 있어.
| 포맷 | 장점 | 단점 | 적합한 상황 |
|---|---|---|---|
| JSON | 가독성 높음, 범용성, 생태계 풍부 | 바이너리 대비 크기 큼 | 웹 API, 설정 파일 |
| XML | 스키마 검증, 네임스페이스 | 장황함, 파싱 복잡 | 엔터프라이즈, SOAP API |
| YAML | 가독성 최고, 주석 가능 | 파싱 느림, 들여쓰기 민감 | 설정 파일 (Docker, K8s) |
| Protobuf | 매우 빠름, 크기 작음 | 사람이 읽기 어려움 | 마이크로서비스, gRPC |
| MessagePack | JSON 호환, 바이너리 효율 | 디버깅 어려움 | 실시간 통신, 게임 |
| CSV | 단순함, 엑셀 호환 | 중첩 구조 불가 | 테이블형 데이터 내보내기 |
🆕 11. JSON5와 JSONC - JSON의 진화형
JSON이 너무 엄격해서 불편하다는 개발자들의 요구로 나온 확장 포맷들이야. 특히 설정 파일에서 많이 쓰여.
✅ 주석 허용 (
// 한 줄, /* 여러 줄 */)✅ 마지막 쉼표(trailing comma) 허용
✅ 작은따옴표 문자열 허용
✅ 16진수 숫자 허용 (
0xFF)✅ 키에 따옴표 없이 사용 가능 (식별자인 경우)
✅ 여러 줄 문자열 허용
사용처: Babel 설정, 일부 Node.js 프로젝트
settings.json, tsconfig.json)에서 사용해.✅ 주석 허용 (
// 한 줄, /* 여러 줄 */)✅ 마지막 쉼표 허용 (일부 구현체)
사용처: VS Code 설정, TypeScript 설정 파일
// JSON5 예시 (tsconfig.json 같은 설정 파일에서 자주 봄)
{
// 이건 JSON5 형식이야
name: 'MyProject', // 키에 따옴표 없어도 됨
version: '1.0.0',
/*
여러 줄 주석도 가능!
설정 파일에서 진짜 유용함
*/
settings: {
debug: true,
maxRetries: 3,
timeout: 0xFF, // 16진수 = 255
tags: [
'production',
'stable', // trailing comma OK!
],
},
}
🏗️ 12. 실전 프로젝트에서 JSON API 설계하기
자 이제 진짜 실무 레벨로 가보자. 재능넷 같은 플랫폼에서 API를 설계한다면 어떻게 할까? 실제 프로젝트 시나리오로 설명할게.
📋 API 설계 원칙
모든 API 응답이 동일한 구조를 가져야 해. 어떤 엔드포인트는 data 키에 담고, 어떤 건 result 키에 담으면 프론트엔드 개발자가 멘붕옴ㅋㅋ
HTTP 상태 코드 + 커스텀 에러 코드 조합으로 에러를 명확하게 전달해야 해. "에러가 났어요"만으로는 부족함.
API URL에 버전을 포함시켜 (
/api/v1/, /api/v2/). 나중에 API 구조 바꿀 때 기존 클라이언트 안 깨짐.
날짜는 반드시 ISO 8601 형식 사용 (
2024-01-15T10:30:00Z). 타임존 명시 필수!
// 실전 API 응답 설계 예시 (재능 거래 플랫폼 기준)
// GET /api/v1/talents/123 - 재능 상세 조회
{
"success": true,
"data": {
"id": 123,
"title": "React 웹 개발 도와드립니다",
"category": {
"id": 5,
"name": "프로그래밍",
"slug": "programming"
},
"seller": {
"id": 456,
"nickname": "개발왕",
"profileImage": "https://cdn.example.com/profiles/456.jpg",
"rating": 4.8,
"reviewCount": 127
},
"pricing": {
"basic": {
"price": 50000,
"description": "기본 패키지",
"deliveryDays": 3
},
"standard": {
"price": 100000,
"description": "스탠다드 패키지",
"deliveryDays": 5
}
},
"tags": ["React", "JavaScript", "프론트엔드"],
"stats": {
"viewCount": 1523,
"orderCount": 89,
"favoriteCount": 234
},
"createdAt": "2024-01-10T09:00:00+09:00",
"updatedAt": "2024-01-15T14:30:00+09:00"
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2024-01-15T15:00:00Z"
}
}
// POST /api/v1/orders - 주문 생성
// 요청 Body
{
"talentId": 123,
"packageType": "standard",
"requirements": "React로 쇼핑몰 메인 페이지 만들어주세요",
"attachments": [
{
"type": "image",
"url": "https://cdn.example.com/uploads/ref1.jpg"
}
]
}
// 응답
{
"success": true,
"data": {
"orderId": "ORD-2024-001234",
"status": "pending_payment",
"amount": 100000,
"paymentDeadline": "2024-01-15T16:00:00+09:00"
},
"message": "주문이 생성되었습니다. 결제를 완료해주세요."
}
이런 식으로 재능넷처럼 다양한 재능을 거래하는 플랫폼에서도 JSON API 설계가 핵심이야. 일관된 구조와 명확한 데이터 타입이 개발 생산성을 엄청 높여줘.
🔮 13. GraphQL과 JSON - REST API의 대안
요즘 GraphQL 많이 들어봤지? GraphQL도 JSON을 기반으로 동작해. REST API의 over-fetching, under-fetching 문제를 해결하기 위해 Facebook이 만든 쿼리 언어야.
GraphQL: 클라이언트가 필요한 데이터 구조를 직접 요청 → 딱 필요한 것만 받음
// GraphQL 쿼리 예시
query GetUser($id: ID!) {
user(id: $id) {
name
email
posts {
title
createdAt
}
}
}
// GraphQL 응답 (JSON 형식)
{
"data": {
"user": {
"name": "홍길동",
"email": "hong@example.com",
"posts": [
{
"title": "첫 번째 포스트",
"createdAt": "2024-01-10T09:00:00Z"
}
]
}
}
}
// GraphQL 에러 응답
{
"errors": [
{
"message": "사용자를 찾을 수 없습니다.",
"locations": [{"line": 2, "column": 3}],
"path": ["user"],
"extensions": {
"code": "USER_NOT_FOUND"
}
}
],
"data": null
}
🐛 14. JSON 트러블슈팅 - 자주 만나는 에러들
개발하다 보면 JSON 관련 에러 진짜 많이 만나ㅋㅋ 자주 나오는 에러들과 해결법 정리해줄게.
해결: JSONLint로 유효성 검사 → 문제 위치 확인 → 수정
해결:
json.dumps(data, ensure_ascii=False)
해결: ISO 8601 문자열로 변환 후 직렬화
JSON.stringify(date.toISOString())
해결:
JSON.stringify()의 replacer 함수로 순환 참조 제거또는
flatted, circular-json 라이브러리 사용
해결: 큰 숫자는 문자열로 전송 (
"id": "9007199254740993")또는 BigInt 처리 라이브러리 사용
// 순환 참조 해결 예시
const obj = { name: "홍길동" };
obj.self = obj; // 순환 참조!
// ❌ 에러 발생
JSON.stringify(obj); // TypeError: Converting circular structure to JSON
// ✅ replacer 함수로 해결
const seen = new WeakSet();
const safe = JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return '[Circular]';
seen.add(value);
}
return value;
});
// 큰 숫자 처리
const bigId = 9007199254740993n; // BigInt
const json = JSON.stringify({
id: bigId.toString() // 문자열로 변환
});
// {"id":"9007199254740993"}
🎯 마무리 - JSON 마스터가 되는 길
자 여기까지 JSON의 기초부터 실무 패턴, 보안, 성능 최적화까지 다 다뤘어! 진짜 길었지?ㅋㅋ 근데 이 정도는 알아야 진짜 API 개발자라고 할 수 있어.
□ 직렬화/역직렬화 개념 및 각 언어별 구현
□ JSON Schema로 데이터 유효성 검증
□ REST API 응답 패턴 (래퍼, 페이지네이션, 에러)
□ HTTP 헤더 Content-Type 설정
□ JSON 보안 취약점 인지 및 방어
□ 성능 최적화 기법 (압축, 캐싱, 스트리밍)
□ jq 등 JSON 도구 활용
□ 트러블슈팅 능력 (순환 참조, 큰 숫자, 인코딩)
개발 공부하면서 JSON 관련 실습이 필요하다면, 재능넷에서 API 개발 전문가를 찾아서 1:1 멘토링을 받아보는 것도 좋은 방법이야. 이론만큼 실전 경험이 중요하거든!
JSON은 단순해 보이지만 깊이 파면 팔수록 알아야 할 게 많아. 오늘 배운 내용들을 실제 프로젝트에 적용해보면서 감을 익혀봐. 처음엔 어색해도 하다 보면 자연스럽게 손에 익을 거야 💪
그리고 JSON 관련 최신 트렌드도 계속 팔로우해봐. JSON-LD, JSON:API 스펙, OpenAPI 3.1 같은 것들도 알면 알수록 개발 레벨이 올라가거든ㅋㅋ 화이팅! 🚀
댓글 작성
이 글에 대한 여러분의 생각을 들려주세요
로그인이 필요합니다
댓글을 작성하려면 먼저 로그인해주세요.
댓글 0
지식인의 숲 - 지적 재산권 보호 고지
지적 재산권 보호 고지
- 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
- AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
- 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
- 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
- AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.
아직 댓글이 없습니다.