Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
79e12a7
docs: 트랜잭션 문서작성
Leesowon Sep 21, 2025
6abfd9c
docs: Node.js 이벤트 루프 설명
minzunim Sep 21, 2025
14dbb5a
fix: 날짜 수정
minzunim Sep 21, 2025
e7c8a5b
fix: 볼드 처리, 개행 수정, uv_threadpool_size 내용 추가
minzunim Sep 21, 2025
2b0af03
fix: h3 추가, 개행 처리 등
minzunim Sep 23, 2025
e07b7e6
docs: react race condition #176
ansmeer008 Sep 26, 2025
c590465
docs: 트랜잭션 격리 수준 문서 작성 (#179)
starbea Sep 28, 2025
e5f7a8d
docs: 트랜잭션 문서작성
Leesowon Sep 28, 2025
fb93368
docs: 트랜잭션 문서작성
Leesowon Sep 28, 2025
5c1b0c1
docs: spof 문서 작성 (#190)
tkdtn4657 Sep 28, 2025
92a358b
Update spof.mdx
tkdtn4657 Sep 28, 2025
875ac83
docs: 제목 수정 (#190)
tkdtn4657 Sep 28, 2025
b60b784
docs: 트랜잭션 문서작성
Leesowon Sep 30, 2025
44be1af
docs: 이미지 수정 (#179)
starbea Oct 4, 2025
973d67d
chore: 폴더명 node.js 로 변경
minzunim Oct 4, 2025
7d138c5
docs: storage, cookie, session
ansmeer008 Oct 6, 2025
21cc508
docs: RESTful API 설계 원칙 작성
seongm1n Oct 10, 2025
e6ea253
docs: 포워드 프록시와 리버스 프록시 문서 작성 (#202)
starbea Oct 11, 2025
b83ea33
docs: DNS 문서작성
Leesowon Oct 11, 2025
9c7edd8
docs: DNS 문서작성
Leesowon Oct 11, 2025
e2ce0e5
docs: 이미지 삭제
starbea Oct 11, 2025
47c5617
Merge pull request #164 from Leesowon/docs/Leesowon/transaction
waterbinnn Oct 12, 2025
f48781a
Merge pull request #168 from minzunim/docs/minzunim/nodejs-eventloop
waterbinnn Oct 12, 2025
68ba865
Merge pull request #177 from ansmeer008/docs/ansmeer008/race-condition
waterbinnn Oct 12, 2025
428f430
docs: 날짜 수정
seongm1n Oct 13, 2025
9c4be5a
docs: 소제목 구조 개선으로 가독성 향상
seongm1n Oct 13, 2025
3a8e54f
Merge pull request #201 from seongm1n/docs/theo/restful-api
seongm1n Oct 13, 2025
35aa744
docs: DNS 문서작성
Leesowon Oct 13, 2025
335417d
docs: DNS 문서작성
Leesowon Oct 16, 2025
6fc107e
docs: 오탈자 수정 (#202)
starbea Oct 17, 2025
cf87c0a
docs: http 버전별 특징 정리
SUPINKIM Oct 18, 2025
1b97fb8
Merge pull request #191 from tkdtn4657/docs/tkdtn4657/cs_2
waterbinnn Oct 19, 2025
1c16664
Merge pull request #181 from mk-star/docs/mk-star/transaction-isolati…
starbea Oct 19, 2025
8b3bcc4
Merge pull request #199 from ansmeer008/docs/ansmeer008/fi-storage
waterbinnn Oct 19, 2025
f2226e0
Merge pull request #203 from mk-star/docs/mk-star/proxy
waterbinnn Oct 19, 2025
03d3b2f
Merge pull request #204 from Leesowon/docs/Leesowon/DNS
waterbinnn Oct 19, 2025
e41c4a3
feat: sidebar resize, 메뉴 여닫이 기능 추가
waterbinnn Sep 13, 2025
5c1d9b1
chore: add shadcn resizable
waterbinnn Sep 13, 2025
18d2e87
fix: 오픈 상태를 디폴트로 변경
waterbinnn Oct 19, 2025
01f6dc8
chore: yarn --frozen-lockfile
waterbinnn Oct 19, 2025
a533623
chore: version 1.0.10
waterbinnn Oct 19, 2025
6f1cfb2
chore: 설정 롤백
waterbinnn Oct 19, 2025
cc6c960
Merge pull request #215 from delook-dev/feat/sidebar
waterbinnn Oct 19, 2025
6640c7c
chore: 코드 리뷰 반영
SUPINKIM Oct 19, 2025
43e322a
fix: 오타 수정
SUPINKIM Oct 19, 2025
00e5c2f
Merge pull request #213 from SUPINKIM/docs/SUPINKIM/http
waterbinnn Oct 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
346 changes: 346 additions & 0 deletions docs/posts/cs/restful-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
---
title: 'RESTful API 설계 원칙'
type: 'concept'
language: 'CS'
tags:
- API
- REST
- HTTP
- Web
dateModified: 2025.10.10
---

# RESTful API

REST(Representational State Transfer)는 웹의 장점을 최대한 활용하는 네트워크 아키텍처 스타일입니다. RESTful API는 REST 원칙을 따르는 API로, 자원(Resource)을 URI로 표현하고 HTTP 메서드를 통해 자원에 대한 행위를 정의합니다.

## REST의 6가지 제약 조건

REST 아키텍처는 다음 6가지 제약 조건을 따릅니다.

**1. 클라이언트-서버 (Client-Server)**
- 클라이언트와 서버가 독립적으로 분리되어 있어야 합니다.
- 각각 독립적으로 개선될 수 있습니다.

**2. 무상태성 (Stateless)**
- 각 요청은 독립적이며, 서버는 클라이언트의 상태를 저장하지 않습니다.
- 모든 요청에는 필요한 정보가 포함되어야 합니다.

**3. 캐시 가능 (Cacheable)**
- 응답은 캐시 가능 여부를 명시해야 합니다.
- 클라이언트는 응답을 재사용하여 성능을 향상시킬 수 있습니다.

**4. 계층화 시스템 (Layered System)**
- 클라이언트는 직접 서버에 연결되었는지, 중간 서버(프록시, 게이트웨이 등)를 통해 연결되었는지 알 수 없어야 합니다.

**5. 인터페이스 일관성 (Uniform Interface)**
- 일관된 인터페이스를 통해 시스템 아키텍처를 단순화하고, 상호작용의 가시성을 높입니다.

**6. 코드 온 디맨드 (Code on Demand) - 선택사항**
- 서버가 클라이언트에게 실행 가능한 코드를 전송하여 기능을 확장할 수 있습니다.
- 이는 선택적 제약 조건입니다.

## HTTP 메서드와 CRUD 매핑

REST API는 HTTP 메서드를 사용하여 자원에 대한 행위를 표현합니다.

| HTTP 메서드 | CRUD | 역할 | 멱등성 |
|------------|------|------|--------|
| GET | Read | 자원 조회 | O |
| POST | Create | 자원 생성 | X |
| PUT | Update | 자원 전체 수정 | O |
| PATCH | Update | 자원 부분 수정 | X |
| DELETE | Delete | 자원 삭제 | O |

### 멱등성 (Idempotent)

같은 요청을 여러 번 수행해도 결과가 동일한 성질을 말합니다. GET, PUT, DELETE는 멱등성을 가지지만, POST와 PATCH는 멱등성을 보장하지 않습니다.

#### 예시

```javascript
// GET - 멱등성 O (여러 번 조회해도 결과 동일)
GET /api/users/123

// POST - 멱등성 X (요청마다 새로운 자원 생성)
POST /api/users
{
"name": "홍길동",
"email": "hong@example.com"
}

// PUT - 멱등성 O (여러 번 수정해도 최종 결과 동일)
PUT /api/users/123
{
"name": "홍길동",
"email": "hong@example.com"
}

// DELETE - 멱등성 O (이미 삭제된 자원을 다시 삭제해도 결과 동일)
DELETE /api/users/123
```

## URI 설계 규칙

RESTful API의 URI는 자원을 명확하게 표현해야 합니다. 다음은 좋은 URI를 설계하기 위한 핵심 원칙들입니다.

**1. 명사를 사용하고 복수형으로 표현**
- 자원을 나타낼 때는 동사가 아닌 명사를 사용하고, 복수형으로 표현합니다.

**2. 계층 관계는 슬래시(/)로 표현**
- 자원 간의 계층 관계를 명확하게 나타냅니다.

**3. URI 마지막에 슬래시(/) 포함하지 않기**
- 불필요한 혼란을 방지합니다.

**4. 하이픈(-)은 사용 가능, 언더스코어(_)는 지양**
- 가독성을 위해 하이픈을 사용합니다.

**5. 소문자 사용**
- URI는 대소문자를 구분하므로 일관성을 위해 소문자를 사용합니다.

**6. 파일 확장자는 URI에 포함하지 않기**
- Content-Type 헤더로 미디어 타입을 지정합니다.

```javascript
// ✅ 좋은 예
GET /api/users
GET /api/users/123
GET /api/users/123/orders
GET /api/users/123/orders/456
GET /api/order-items
GET /api/users/123/profile-image

// ❌ 나쁜 예
GET /api/getUsers
GET /api/user
GET /api/users/123/
GET /api/Users/123/ProfileImage
GET /api/order_items
GET /api/users/123/profile-image.png
```

## HTTP 상태 코드 활용

적절한 HTTP 상태 코드를 사용하여 응답 결과를 명확히 전달합니다.

| 상태 코드 | 의미 | 설명 | 사용 시점 |
|----------|------|------|-----------|
| **2xx - 성공** ||||
| 200 OK | 요청 성공 | 요청이 성공적으로 처리됨 | GET, PUT, PATCH |
| 201 Created | 자원 생성 성공 | 새로운 자원이 생성됨 | POST |
| 204 No Content | 요청 성공, 응답 본문 없음 | 요청은 성공했지만 반환할 내용이 없음 | DELETE |
| **3xx - 리다이렉션** ||||
| 301 Moved Permanently | 영구 이동 | 자원의 URI가 영구적으로 변경됨 | URI 변경 |
| 302 Found | 임시 이동 | 자원의 URI가 일시적으로 변경됨 | 임시 URI 변경 |
| **4xx - 클라이언트 오류** ||||
| 400 Bad Request | 잘못된 요청 | 요청 형식이 잘못되었거나 유효하지 않음 | 잘못된 파라미터 |
| 401 Unauthorized | 인증 필요 | 인증이 필요한 요청 | 로그인 필요 |
| 403 Forbidden | 권한 없음 | 인증은 되었지만 권한이 없음 | 권한 부족 |
| 404 Not Found | 자원을 찾을 수 없음 | 요청한 자원이 존재하지 않음 | 존재하지 않는 URI |
| 409 Conflict | 충돌 | 요청이 현재 서버 상태와 충돌 | 중복된 자원 생성 |
| **5xx - 서버 오류** ||||
| 500 Internal Server Error | 서버 내부 오류 | 서버에서 예상치 못한 오류 발생 | 서버 에러 |
| 502 Bad Gateway | 게이트웨이 오류 | 게이트웨이나 프록시 서버에서 오류 발생 | 프록시 에러 |
| 503 Service Unavailable | 서비스 이용 불가 | 서버가 일시적으로 요청을 처리할 수 없음 | 서버 과부하 |

### 예시

```javascript
// 사용자 조회 성공
GET /api/users/123
Response: 200 OK
{
"id": 123,
"name": "홍길동",
"email": "hong@example.com"
}

// 사용자 생성 성공
POST /api/users
Response: 201 Created
Location: /api/users/124
{
"id": 124,
"name": "김철수",
"email": "kim@example.com"
}

// 사용자 삭제 성공
DELETE /api/users/123
Response: 204 No Content

// 존재하지 않는 사용자 조회
GET /api/users/999
Response: 404 Not Found
{
"error": "User not found"
}

// 잘못된 요청
POST /api/users
{
"name": "" // 빈 이름
}
Response: 400 Bad Request
{
"error": "Name is required"
}
```

## RESTful API 설계 예시

### 사용자 관리 API

```javascript
// 사용자 목록 조회
GET /api/users

// 특정 사용자 조회
GET /api/users/123

// 사용자 생성
POST /api/users
{
"name": "홍길동",
"email": "hong@example.com"
}

// 사용자 전체 수정
PUT /api/users/123
{
"name": "홍길동",
"email": "hong@example.com",
"phone": "010-1234-5678"
}

// 사용자 부분 수정 (이메일만 변경)
PATCH /api/users/123
{
"email": "newemail@example.com"
}

// 사용자 삭제
DELETE /api/users/123
```

### 사용자의 주문 목록 조회

```javascript
// 특정 사용자의 모든 주문 조회
GET /api/users/123/orders

// 특정 사용자의 특정 주문 조회
GET /api/users/123/orders/456

// 특정 사용자의 새 주문 생성
POST /api/users/123/orders
{
"productId": 789,
"quantity": 2
}
```

### 검색 및 필터링

```javascript
// 쿼리 파라미터를 사용한 검색
GET /api/users?name=홍길동

// 페이지네이션
GET /api/users?page=1&limit=20

// 정렬
GET /api/users?sort=createdAt&order=desc

// 복합 필터링
GET /api/users?status=active&role=admin&page=1&limit=10
```

## REST vs GraphQL

REST API의 대안으로 GraphQL이 있습니다. 각각의 특징을 비교하면 다음과 같습니다.

| 특징 | REST | GraphQL |
|------|------|---------|
| 데이터 요청 | 여러 엔드포인트 | 단일 엔드포인트 |
| 응답 형태 | 서버가 정의한 고정 구조 | 클라이언트가 필요한 데이터만 요청 |
| Over-fetching | 발생 가능 (불필요한 데이터 포함) | 없음 (필요한 데이터만) |
| Under-fetching | 발생 가능 (추가 요청 필요) | 없음 (한 번에 모든 데이터) |
| 캐싱 | HTTP 캐싱 활용 용이 | 추가 구현 필요 |
| 학습 곡선 | 낮음 | 높음 |

#### 예시

```javascript
// REST API - 사용자 정보와 게시글을 가져오려면 2번의 요청 필요
GET /api/users/123
GET /api/users/123/posts

// GraphQL - 한 번의 요청으로 필요한 데이터만 가져오기
POST /graphql
{
query {
user(id: 123) {
name
email
posts {
title
createdAt
}
}
}
}
```

## 실무 적용 팁

**1. API 버저닝**

API가 변경될 때 기존 클라이언트에 영향을 주지 않도록 버전 관리를 합니다.

```javascript
// URI에 버전 포함
GET /api/v1/users
GET /api/v2/users

// 헤더에 버전 포함
GET /api/users
Accept: application/vnd.company.v1+json
```

**2. 에러 응답 일관성 유지**

에러 응답 형식을 일관되게 유지하여 클라이언트에서 처리하기 쉽게 합니다.

```javascript
{
"error": {
"code": "USER_NOT_FOUND",
"message": "사용자를 찾을 수 없습니다.",
"details": {
"userId": 123
}
}
}
```

**3. HATEOAS (Hypermedia As The Engine Of Application State)**

응답에 다음 가능한 행동을 링크로 포함하여 클라이언트가 API를 탐색할 수 있게 합니다.

```javascript
{
"id": 123,
"name": "홍길동",
"email": "hong@example.com",
"_links": {
"self": { "href": "/api/users/123" },
"orders": { "href": "/api/users/123/orders" },
"edit": { "href": "/api/users/123" },
"delete": { "href": "/api/users/123" }
}
}
```

RESTful API는 웹의 기본 원칙을 따르면서도 확장 가능하고 유지보수가 쉬운 API를 설계할 수 있게 해줍니다. 위의 원칙들을 잘 이해하고 적용하면 클라이언트와 서버 간의 효율적인 통신을 구현할 수 있습니다.
Loading