JS LAB
JS 5.5 · 5부. 비동기 프로그래밍

fetch로 데이터 가져오기

서버에 요청을 보내고 응답과 상태 코드를 다룹니다.

예상 학습 시간 16분 실행 단추가 있는 예제는 고쳐서 실행해 볼 수 있습니다 난이도 중급
개념 설명

서버에 요청을 보냅니다

지금까지 데이터를 코드에 직접 적어 두었습니다. 실제 화면은 서버에서 받아 옵니다. 그 일을 하는 것이 fetch 입니다.

fetch 는 Promise 를 돌려줍니다(5.3). 그래서 await 로 받습니다(5.4). 두 단계입니다.

  1. await fetch(주소) — 응답을 받습니다.
  2. await 응답.json() — 본문을 객체로 바꿉니다.

둘째 단계에도 await 가 필요합니다. 본문은 응답 머리보다 나중에 도착하기 때문입니다.

최소 예제 · 편집 가능

하나 가져오기

아래 예제는 실제로 인터넷에 요청을 보냅니다. 연습용으로 공개된 주소입니다.

script.js
const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");

console.log(response.status);
console.log(response.ok);

const data = await response.json();

console.log(data.id);
console.log(data.title);
출력
200 true 1 delectus aut autem

status 는 서버가 돌려준 상태 코드입니다. 200 은 성공입니다. ok 는 200부터 299 사이인지를 알려 줍니다.

상세 사용법

목록 가져와 다루기

받아 온 것이 객체 배열이면 3부에서 배운 방법을 그대로 사용합니다.

script.js
const response = await fetch("https://jsonplaceholder.typicode.com/todos?_limit=3");
const todos = await response.json();

console.log(todos.length);

todos.forEach(todo => console.log(`${todo.id}. ${todo.title}`));
출력
3 1. delectus aut autem 2. quis ut nam facilis et officia qui 3. fugiat veniam minus

json() 이 하는 일은 3.8 의 JSON.parse 와 같습니다. 서버가 보낸 글자를 객체로 되돌립니다.

상세 사용법

실패해도 예외가 아닙니다

가장 자주 틀리는 자리입니다. 서버가 404 나 500 을 돌려줘도 fetch 는 예외를 던지지 않습니다. 요청이 갔다 왔으면 성공으로 봅니다.

script.js
const response = await fetch("https://jsonplaceholder.typicode.com/todos/99999");

console.log(response.status);
console.log(response.ok);
console.log("예외는 나지 않았습니다");
출력
404 false 예외는 나지 않았습니다

그래서 ok 를 직접 확인해야 합니다. 확인하지 않고 json() 을 부르면 엉뚱한 자리에서 오류가 납니다.

script.js
async function loadTodo(id) {
	const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);

	if (!response.ok) {
		throw new Error(`서버가 ${response.status} 를 돌려주었습니다`);
	}

	return response.json();
}

console.log((await loadTodo(1)).title);

try {
	await loadTodo(99999);
} catch (error) {
	console.log(error.message);
}
출력
delectus aut autem 서버가 404 를 돌려주었습니다

return response.json()await 를 붙이지 않아도 됩니다. async 함수가 돌려주는 Promise 는 안쪽 Promise 가 끝날 때까지 함께 기다립니다(5.4).

상세 사용법

보낼 때

기본은 받아 오는 요청입니다. 보낼 때는 방법과 머리, 본문을 함께 적습니다.

모양
const response = await fetch("https://example.com/todos", {
	method: "POST",
	headers: { "Content-Type": "application/json" },
	body: JSON.stringify({ title: "새 할 일" })
});

본문은 글자여야 하므로 3.8 의 JSON.stringify 로 바꿔 보냅니다. 받는 쪽이 그것을 객체로 되돌립니다.

이 예제에는 실행 단추가 없습니다. 아무 데나 보낼 수는 없어 주소를 예시로 적어 두었습니다.

흔한 실수

처음에 자주 걸리는 것

1. ok 를 확인하지 않습니다

404 여도 예외가 나지 않습니다. 확인하지 않으면 없는 데이터를 그대로 다루다가 엉뚱한 자리에서 오류가 납니다.

2. json() 에 await 를 빠뜨립니다

json() 도 Promise 를 돌려줍니다. 빠뜨리면 값이 아니라 Promise 가 담깁니다(5.4).

const data = response.json();        // Promise 가 담깁니다
const data = await response.json();  // 이렇게 적습니다
3. 아무 주소나 부릅니다

브라우저는 다른 주소로 가는 요청을 함부로 허락하지 않습니다. 서버가 허락한다고 응답 머리에 적어야 읽을 수 있습니다. 이 규칙을 CORS 라고 합니다. 허락하지 않는 주소에서는 아래 오류가 납니다.

TypeError: Failed to fetch
실습 문제

직접 해보기

1. 다른 번호 가져오기 난이도 하

todos/5 를 가져와 제목과 완료 여부를 출력하세요.

const response = await fetch("https://jsonplaceholder.typicode.com/todos/5"); const todo = await response.json(); console.log(todo.title); console.log(todo.completed);
2. 완료된 것만 세기 난이도 중

할 일 10개를 가져와 completed 가 참인 것의 개수와 제목을 출력하세요.

받아 온 뒤는 그냥 객체 배열입니다. 3.3 의 filtermap 을 사용하세요.
const response = await fetch("https://jsonplaceholder.typicode.com/todos?_limit=10"); const todos = await response.json(); const done = todos.filter(todo => todo.completed); console.log(done.length); done.forEach(todo => console.log(todo.title));
요약

이 단원의 정리

  • fetch 는 Promise 를 돌려줍니다. await 로 받습니다.
  • 본문은 await 응답.json() 으로 한 번 더 받습니다.
  • 404 여도 예외가 나지 않습니다. ok 를 직접 확인합니다.
  • 보낼 때는 method · headers · body 를 적고 본문을 글자로 바꿉니다.
  • 서버가 허락하지 않는 주소는 읽을 수 없습니다(CORS).