챕터 4.1: Fetch API의 기본
학습 시간: 45분
1. Fetch API: 관제 센터의 "주요 안테나"
여러분의 비행 관제 센터에 우주선과 통신하기 위한 거대한 무선 안테나가 있다고 상상해보세요. 여러분은 이 안테나를 필요한 주파수에 맞춰 명령을 보내고 응답을 기다릴 수 있습니다.
Fetch API는 최신 브라우저에 내장된 "안테나"와 같습니다. 서버에 HTTP 요청을 수행하기 위한 표준 JavaScript 인터페이스입니다. 이를 통해 다음을 수행할 수 있습니다:
- 📡 우리 API에 "명령"(GET, POST, PUT, DELETE)을 보냅니다.
- 🛰️ 서버로부터 "텔레메트리"(JSON 데이터)를 받습니다.
- ⚙️ 비동기적으로 작동하여 응답을 기다리는 동안 사용자 인터페이스를 "멈추지" 않습니다.
💡 우주 비유:
fetch()
는 "안테나, 연결 설정!"이라는 명령입니다. 여러분은 여기에 다음을 전달합니다:
- 목표 좌표 (우리 API의 URL).
- 명령 유형 (메서드: GET, POST).
- 명령 내용 (요청 본문, 헤더).
응답으로 실제 데이터를 받는 것이 아니라, 데이터가 올 것이라는 약속 (Promise)을 받습니다.
2. 비동기성: 광속 통신
멀리 떨어진 우주선과의 통신은 시간이 걸립니다. 관제 센터의 모든 작업을 중단하고 응답이 올 때까지 기다릴 수는 없습니다. 명령을 보내고 계속 작업하며, 응답이 오면 시스템이 여러분에게 알립니다.
이것이 바로 비동기성입니다. JavaScript는 서버로부터 응답을 기다리는 동안 나머지 코드의 실행을 차단하지 않습니다. 이 프로세스를 관리하기 위해 Fetch API는 프로미스 (Promises)를 사용합니다.
프로미스 (Promise)는 여러분이 요청을 보냈다는 "영수증"입니다. 다음 세 가지 상태를 가집니다:
pending
(대기 중): 신호가 아직 전송 중입니다.fulfilled
(이행됨): 응답이 성공적으로 수신되었습니다!rejected
(거부됨): 오류가 발생했습니다 (예: 연결 없음).
3. 첫 번째 요청: ISS의 위치 알아내기
fetch
를 사용하여 첫 번째 요청을 보내봅시다. 간단한 HTML 파일과 <script>
태그를 사용할 것입니다.
단계 1: index.html
생성
새 폴더(예: frontend_fleet_control
)에 index.html
파일을 생성하세요.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>관제 센터 - Fetch API</title>
</head>
<body>
<h1>ISS 통신 상태</h1>
<div id="iss-status">데이터 대기 중...</div>
<script>
// 우리의 JavaScript 코드가 여기에 옵니다
</script>
</body>
</html>
단계 2: fetch
코드를 작성합니다
<script>
태그 안에 Open Notify의 공개 API에 대한 첫 번째 fetch
요청을 추가합니다.
// index.html -> <script>
const issApiUrl = 'http://api.open-notify.org/iss-now.json';
const statusDiv = document.getElementById('iss-status');
console.log('ISS 좌표를 가져오기 위한 요청을 보냅니다...');
fetch(issApiUrl)
.then(response => {
// 첫 번째 .then()은 HTTP 응답 자체를 처리합니다
console.log('서버로부터 응답을 받았습니다!', response);
// 응답 본문을 JSON으로 변환합니다. 이것 또한 비동기 작업입니다.
return response.json();
})
.then(data => {
// 두 번째 .then()은 이미 파싱된 JSON 데이터를 받습니다.
console.log('데이터가 성공적으로 JSON으로 변환되었습니다!', data);
const position = data.iss_position;
statusDiv.innerHTML = `ISS는 현재 여기에 있습니다:
<strong>위도:</strong> ${position.latitude},
<strong>경도:</strong> ${position.longitude}`;
})
.catch(error => {
// .catch()는 네트워크 오류가 발생했을 때 작동합니다
console.error('ISS 통신 오류!', error);
statusDiv.textContent = '데이터를 가져올 수 없습니다. 연결을 확인하세요.';
});
fetch(url)
: GET 요청을 보냅니다. 프로미스를 반환합니다..then(callback)
: 프로미스가 성공적으로 이행되었을 때 (fulfilled
) 실행됩니다. 첫 번째.then
은Response
객체를 받습니다.response.json()
: 응답 본문을 읽고 JSON으로 파싱하는 메서드입니다. 이 또한 프로미스를 반환합니다!.catch(callback)
: 프로미스가 거부되었을 때 (rejected
), 예를 들어 네트워크 오류로 인해 실행됩니다.
단계 3: 브라우저에서 열기
브라우저에서 index.html
파일을 열기만 하면 됩니다. "데이터 대기 중..."이 현재 ISS 좌표로 바뀌는 것을 볼 수 있을 것입니다. 개발자 콘솔(F12)을 열어 로그를 확인하세요.
4. "만약 ...이라면?": 서버 오류 처리
만약 존재하지 않는 URL을 요청하면 어떻게 될까요?
fetch('http://api.open-notify.org/non-existent-endpoint')
fetch
는 .catch()
가 네트워크 오류(인터넷 없음, DNS를 찾을 수 없음)가 발생했을 때만 작동하도록 설계되어 있습니다. 하지만 404
또는 500
코드의 응답은 fetch
에게는 성공적으로 수신된 응답입니다! 단지 오류 코드를 포함하고 있을 뿐이죠.
올바른 확인 방법:
fetch('http://api.open-notify.org/non-existent-endpoint')
.then(response => {
// 200-299 상태 코드에 대해 true인 .ok 속성을 확인합니다.
if (!response.ok) {
// 응답이 "OK"가 아니면, .catch()로 이동하기 위해 사용자 지정 오류를 생성합니다.
throw new Error(`HTTP 오류! 상태: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('요청 실행 중 오류가 발생했습니다:', error);
});
response.ok
: 이것이 여러분의 주요 성공 지표입니다.throw new Error()
:.catch
블록으로 이동하기 위해 프로미스 체인을 수동으로 "실패"시킵니다.
정리를 위한 퀴즈
🚀 장 요약:
관제 센터의 "메인 안테나"를 설정하고 요청을 보내고 응답을 받는 방법을 배웠습니다.
- 📡
fetch()
의 기본 구문을 마스터했습니다. - 🛰️ 프로미스(Promises)가 무엇이며
.then()
및.catch()
를 사용하는 방법을 이해했습니다. - ⚙️
response.ok
를 확인하여 서버 응답을 올바르게 처리하는 방법을 배웠습니다.
연결되었습니다! 다음 장에서는 관제 센터를 FastAPI로 생성한 우주 함대 API에 연결하고 함선 목록을 가져와 표시하는 방법을 배웁니다.
📌 확인:
index.html
파일이 ISS 좌표를 올바르게 표시하는지 확인하세요.- 의도적으로 URL을 깨뜨린 다음 개발자 콘솔에 어떤 오류가 출력되는지 확인해 보세요.
⚠️ 코드가 작동하지 않는 경우:
- CORS 오류: 로컬 FastAPI API(
http://127.0.0.1:8000
등)에file:///...
로 열린 파일에서 요청하려고 하면 브라우저는 CORS 보안 정책으로 인해 요청을 차단합니다. 이 문제는 다음 장에서 해결할 것입니다. 현재는 이를 허용하는 공개 API를 사용하고 있습니다.- HTTP/HTTPS:
http://api.open-notify.org
는 HTTP로 작동합니다. 일부 브라우저는 이에 대해 경고할 수 있습니다. HTTPS 웹사이트에서 작업하는 경우 HTTP 리소스에 대한 요청이 차단될 수 있습니다.