Skip to content

Commit 401b7f5

Browse files
committed
Update chapter_44, chapter_45, chapter_46
1 parent d578362 commit 401b7f5

File tree

3 files changed

+1516
-0
lines changed

3 files changed

+1516
-0
lines changed

book/이용우/chapter_44.md

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
### Chapter 44 - REST API
2+
3+
REST는 HTTP를 기반으로 클라이언트가 서버의 리소스에 접근하는 방식을 규정한 아키텍처이고
4+
REST API는 REST를 기반으로 서비스 API를 구현한 것을 의미한다.
5+
6+
<br>
7+
8+
### REST API의 구성
9+
10+
REST API는 자원, 행위, 표현 3가지 요소로 구성된다.
11+
12+
- 자원: URI
13+
- 행위: HTTP 요청 메서드
14+
- 표현: 페이로드
15+
16+
<br><br>
17+
18+
### REST API 설계 원칙
19+
REST에서 가장 중요한 기본 원칙은 2가지이다.
20+
- URI는 리소스를 표현하는데 집중한다.
21+
- 행위에 대한 정의는 HTTP 요청 메소드를 통한다.
22+
23+
<br>
24+
25+
#### URI는 리소스를 표현하는데 집중한다.
26+
URI는 리소스를 표현하는 데 중점을 두어야 한다.
27+
리소스를 식별할 수 있는 이름은 동사보다는 명사를 사용한다.
28+
``` text
29+
GET /todos/1
30+
GET /users/1
31+
```
32+
33+
<br>
34+
35+
#### 행위에 대한 정의는 HTTP 요청 메소드를 통한다.
36+
HTTP 요청 메서드는 클라이언트가 서버에게 요청의 종류와 목적을 알리는 수단이다.
37+
주로 5가지 요청 메소드(GET, POST, PUT, PATCH, DELETE)를 사용하여 CRUD를 구현한다.
38+
39+
| 요청 메서드 | 종류 |
40+
|:---:|:---:|
41+
|GET|리소스 조회|
42+
|POST|리소스 생성|
43+
|PUT|리소스 전체 변경|
44+
|PATCH|리소스 부분 변경|
45+
|DELETE|리소스 삭제|
46+
47+
<br>
48+
49+
리소스에 대한 행위는 HTTP 요청 메소드를 통해 표현한다.
50+
51+
``` text
52+
DELETE /todos/1
53+
```
54+
55+
<br><br>
56+
57+
### JSON Server를 이용한 REST API 실습
58+
59+
#### JSON Server 설치
60+
61+
``` bash
62+
$ mkdir json-server-exam && cd json-server-exam
63+
$ npm init -y
64+
$ npm install json-server --save-dev
65+
```
66+
67+
<br>
68+
69+
#### db.json 파일 생성
70+
프로젝트 루트 폴더(/json-server-exam)에 db.json 파일을 생성한다.
71+
db.json 파일은 리소스를 제공하는 데이터베이스 역할을 한다.
72+
73+
``` json
74+
{
75+
"todos": [
76+
{ "id": 1, "content": "HTML", "completed": false },
77+
{ "id": 2, "content": "CSS", "completed": true },
78+
{ "id": 3, "content": "JavaScript", "completed": false }
79+
]
80+
}
81+
```
82+
83+
<br>
84+
85+
#### JSON Server 실행
86+
JSON Server를 실행한다.
87+
JSON Server가 데이터베이스 역할을 하는 db.json 파일의 변경을 감지하게 하려면 `watch` 옵션을 추가한다.
88+
89+
``` bash
90+
$ json-server --watch db.json --port 4000
91+
```
92+
93+
<br>
94+
95+
매번 명령어 입력하는 것이 번거롭다면 `package.json` 파일의 scripts를 아래와 같이 수정하여 JSON Server를 실행하면 된다.
96+
97+
``` json
98+
{
99+
"name": "json-server-exam",
100+
"version": "1.0.0",
101+
"scripts": {
102+
"start": "json-server --watch db.json --port 4000"
103+
},
104+
"devDependencies": {
105+
"json-server": "^0.17.0"
106+
}
107+
}
108+
```
109+
110+
<br>
111+
112+
터미널에서 `npm start` 명령어를 실행하면 JSON Server가 실행된다.
113+
``` bash
114+
$ npm start
115+
```
116+
117+
<br><br>
118+
119+
#### GET 요청
120+
JSON Server의 루트 폴더(/json-server-exam)에 `public` 폴더를 생성하고 그 안에 `get_index.html` 파일을 생성한다.
121+
이후 서버를 종료 후 재시작하자.
122+
123+
`todos` 리소스에서 모든 todo를 취득한다.
124+
125+
``` html
126+
<!DOCTYPE html>
127+
<html>
128+
<body>
129+
<pre></pre>
130+
<script>
131+
const xhr = new XMLHttpRequest();
132+
xhr.open('GET', '/todos');
133+
xhr.send();
134+
135+
xhr.onload = () => {
136+
if (xhr.status === 200) {
137+
document.querySelector('pre').textContent = xhr.response;
138+
} else {
139+
console.error('Error', xhr.status, xhr.statusText);
140+
}
141+
}
142+
</script>
143+
</body>
144+
</html>
145+
```
146+
147+
<br>
148+
149+
`todos` 리소스에서 id를 사용하여 특정 `todo`를 취득(retrieve)해보자.
150+
public 폴더에 `get_retrieve.html`을 추가해보자.
151+
152+
`todo` 리소스에서 특정 todo를 취득한다.
153+
154+
``` html
155+
<!DOCTYPE html>
156+
<html>
157+
<body>
158+
<pre></pre>
159+
<script>
160+
const xhr = new XMLHttpRequest();
161+
xhr.open('GET', '/todos/1');
162+
xhr.send();
163+
164+
xhr.onload = () => {
165+
if (xhr.status === 200) {
166+
document.querySelector('pre').textContent = xhr.response;
167+
} else {
168+
console.error('Error', xhr.status, xhr.statusText);
169+
}
170+
}
171+
</script>
172+
</body>
173+
</html>
174+
```
175+
176+
<br><br>
177+
178+
#### POST 요청
179+
public 폴더에 `post.html` 파일을 추가해보자.
180+
181+
todo 리소스에 새로운 todo를 생성한다.
182+
POST 요청 시에는 `setRequestHeader` 메소드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.
183+
184+
``` html
185+
<!DOCTYPE html>
186+
<html>
187+
<body>
188+
<pre></pre>
189+
<script>
190+
const xhr = new XMLHttpRequest();
191+
xhr.open('POST', '/todos');
192+
193+
// 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정
194+
xhr.setRequestHeader('Content-type', 'application/json');
195+
196+
// HTTP 요청 전송
197+
// 요청 몸체에 담아 서버로 전송할 페이로드를 인수로 전달
198+
xhr.send(JSON.stringify({
199+
id: 4,
200+
content: 'Angular',
201+
completed: false
202+
}));
203+
204+
xhr.onload = () => {
205+
// 응답 상태 코드가 200(OK) 또는 201(Created)인 경우 정상 처리된 것으로 판단
206+
if (xhr.status === 200 || xhr.status === 201) {
207+
document.querySelector('pre').textContent = xhr.response;
208+
} else {
209+
console.error('Error', xhr.status, xhr.statusText);
210+
}
211+
}
212+
</script>
213+
</body>
214+
</html>
215+
```
216+
217+
<br><br>
218+
219+
#### PUT 요청
220+
`PUT`은 특정 리소스 전체를 교체할 때 사용한다.
221+
PUT 요청 시에는 `setRequestHeader` 메소드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.
222+
223+
``` html
224+
<!DOCTYPE html>
225+
<html>
226+
<body>
227+
<pre></pre>
228+
<script>
229+
const xhr = new XMLHttpRequest();
230+
231+
// todos 리소스에서 id가 1인 리소스 전체를 교체
232+
xhr.open('PUT', '/todos/4');
233+
234+
xhr.setRequestHeader('Content-type', 'application/json');
235+
236+
xhr.send(JSON.stringify({
237+
id: 4,
238+
content: 'TypeScript',
239+
completed: false
240+
}));
241+
242+
// 요청이 완료되었을 경우 발생하는 이벤트 핸들러
243+
xhr.onload = () => {
244+
if (xhr.status === 200 || xhr.status === 201) {
245+
document.querySelector('pre').textContent = xhr.response;
246+
} else {
247+
console.error('Error', xhr.status, xhr.statusText);
248+
}
249+
}
250+
</script>
251+
</body>
252+
</html>
253+
```
254+
255+
<br>
256+
257+
#### PATCH 요청
258+
`PATCH`는 특정 리소스 일부를 변경할 때 사용한다.
259+
PATCH 요청 시에는 `setRequestHeader` 메소드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.
260+
261+
``` html
262+
<!DOCTYPE html>
263+
<html>
264+
<body>
265+
<pre></pre>
266+
<script>
267+
const xhr = new XMLHttpRequest();
268+
xhr.open('PATCH', '/todos/4');
269+
270+
xhr.setRequestHeader('Content-type', 'application/json');
271+
272+
xhr.send(JSON.stringify({
273+
content: 'TypeScript',
274+
completed: false
275+
}));
276+
277+
// 요청이 완료되었을 경우 발생하는 이벤트 핸들러
278+
xhr.onload = () => {
279+
if (xhr.status === 200 || xhr.status === 201) {
280+
document.querySelector('pre').textContent = xhr.response;
281+
} else {
282+
console.error('Error', xhr.status, xhr.statusText);
283+
}
284+
}
285+
</script>
286+
</body>
287+
</html>
288+
```
289+
290+
291+
<br><br>
292+
293+
#### DELETE 요청
294+
`DELETE`는 특정 리소스를 삭제할 때 사용한다.
295+
DELETE 요청 시에는 `setRequestHeader` 메소드를 사용하여 요청 몸체에 담아 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다.
296+
297+
``` html
298+
<!DOCTYPE html>
299+
<html>
300+
<body>
301+
<pre></pre>
302+
<script>
303+
const xhr = new XMLHttpRequest();
304+
xhr.open('DELETE', '/todos/4');
305+
306+
xhr.send();
307+
308+
xhr.onload = () => {
309+
if (xhr.status === 200 || xhr.status === 201) {
310+
document.querySelector('pre').textContent = xhr.response;
311+
} else {
312+
console.error('Error', xhr.status, xhr.statusText);
313+
}
314+
}
315+
</script>
316+
</body>
317+
</html>
318+
```
319+

0 commit comments

Comments
 (0)