소개
이 랩에서는 최신 JavaScript 를 사용하여 웹 API 와 상호 작용하는 데 필수적인 기술을 배우게 됩니다. 웹 브라우저에 내장된 강력하고 유연한 도구인 fetch API 를 탐색하여 비동기 네트워크 요청을 수행합니다. 주요 목표는 서버에서 데이터를 요청하는 방법, 응답을 처리하는 방법, 잠재적인 오류를 관리하는 방법을 이해하여 동적 웹 애플리케이션 구축을 위한 기초 기술을 형성하는 것입니다.
기본 GET 요청을 만들어 데이터를 검색하는 것으로 시작한 다음, 응답을 처리하고 JSON 으로 파싱하며, 가져온 데이터를 HTML 요소 내에 표시하는 방법을 배우게 됩니다. 이 랩에서는 또한 강력한 오류 처리를 구현하고, POST 요청을 만들어 서버로 데이터를 보내고, API 키를 사용하여 요청을 인증하는 것과 같은 중요한 측면도 다룹니다.
fetch API 로 기본 GET 요청 만들기
이 단계에서는 JavaScript 에서 기본적인 API 호출인 GET 요청을 만드는 방법을 배우게 됩니다. 모든 최신 웹 브라우저에 내장되어 있고 Node.js 18+ 환경에서 사용할 수 있는 현대적이고 강력하며 유연한 도구인 fetch API 를 사용할 것입니다. 이를 통해 서버에서 비동기적으로 리소스를 요청할 수 있습니다.
fetch 함수는 promise 기반이므로 성공 여부에 관계없이 해당 요청에 대한 Response로 해결되는 Promise를 반환합니다. 이를 통해 비동기 작업이 완료될 때 그 결과를 처리할 수 있습니다.
먼저 코드를 작성할 파일을 생성해 보겠습니다. 화면 왼쪽의 파일 탐색기에서 ~/project 디렉터리에 index.js라는 새 파일을 만듭니다.
이 예제에서는 JSONPlaceholder API 를 사용할 것입니다. 이 API 는 테스트 및 프로토타이핑에 완벽한 무료 온라인 REST API 입니다. 단일 "todo" 항목을 요청할 것입니다.
이제 index.js 파일에 다음 코드를 추가합니다. 이 코드는 API 엔드포인트 URL 을 정의하고 fetch를 사용하여 GET 요청을 수행합니다.
// 단일 todo 항목에 대한 API URL 정의
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
// fetch API 를 사용하여 GET 요청 수행
fetch(apiUrl)
.then((response) => {
// fetch 함수는 promise 를 반환합니다.
// 첫 번째 .then() 블록은 Response 객체를 받습니다.
// 응답 본문 텍스트를 JSON 으로 파싱하려면 응답에서 .json() 메서드를 호출해야 합니다.
return response.json();
})
.then((data) => {
// 두 번째 .then() 블록은 파싱된 JSON 데이터를 받습니다.
console.log("데이터를 성공적으로 가져왔습니다:");
console.log(data);
})
.catch((error) => {
// fetch 작업 중에 오류가 발생하면 .catch() 블록이 실행됩니다.
console.error("데이터 가져오기 오류:", error);
});
코드를 자세히 살펴보겠습니다.
apiUrl: 연락하려는 API 엔드포인트의 URL 을 상수에 저장합니다.fetch(apiUrl): 지정된 URL 로 GET 요청을 시작하고Promise를 반환합니다..then(response => response.json()):Promise가 해결되면 이 함수가 호출됩니다.response객체는 실제 JSON 데이터가 아니라 전체 HTTP 응답의 표현입니다.response.json()메서드를 호출하여 JSON 본문 내용을 추출하며, 이 자체로 또 다른Promise를 반환합니다..then(data => { ... }): 이 두 번째.then()은response.json()에서 반환된Promise를 처리합니다.data매개변수에는 이제 API 의 실제 JSON 객체가 포함됩니다. 이 데이터를 콘솔에 기록합니다..catch(error => { ... }):Promise가 어떤 시점에서든 거부되면 (예: 네트워크 오류로 인해) 이 블록이 오류를 잡아 콘솔에 기록합니다.
스크립트를 실행하고 결과를 보려면 WebIDE 에서 새 터미널을 열고 다음 명령을 실행합니다.
node ~/project/index.js
API 에서 단일 "todo" 항목을 나타내는 가져온 데이터가 콘솔에 출력되는 것을 볼 수 있습니다.
예상 출력:
Data fetched successfully:
{ userId: 1, id: 1, title: 'delectus aut autem', completed: false }

응답 처리 및 JSON 데이터 파싱
이 단계에서는 API 호출 응답을 더 깊이 처리하는 방법을 알아보겠습니다. fetch를 사용하면 서버에서 Response 객체를 반환합니다. 이 객체에 무엇이 포함되어 있는지, 그리고 애플리케이션에서 사용하기 위해 본문에서 JSON 데이터를 올바르게 파싱하는 방법을 살펴보겠습니다.
첫 번째 .then() 블록에서 받는 Response 객체는 데이터 자체가 아닙니다. 이는 상태 코드 (예: OK 의 경우 200), 헤더 및 응답 본문을 포함한 전체 HTTP 응답의 표현입니다. 본문은 데이터 스트림이며, 사용하려면 읽어야 합니다.
fetch API 는 이를 위해 일반 텍스트의 경우 .text() 및 JSON 데이터 파싱의 경우 .json()과 같은 여러 메서드를 제공합니다. .json() 메서드는 응답 스트림을 끝까지 읽고 본문 텍스트를 JavaScript 객체로 파싱한 결과로 해결되는 새 promise 를 반환합니다. 이것이 실제 데이터를 사용하기 위해 두 번째 .then()을 연결하는 이유입니다.
이를 시연하기 위해 ~/project/index.js 파일을 수정해 보겠습니다. 전체 데이터 객체를 기록하는 대신, 특정 속성에 액세스하여 기록함으로써 일반 JavaScript 객체로 작업하고 있음을 보여줄 것입니다.
~/project/index.js 파일의 내용을 다음 코드로 업데이트합니다.
// 단일 todo 항목에 대한 API URL 정의
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
fetch(apiUrl)
.then((response) => {
// response.json() 메서드는 응답의 JSON 본문을 파싱하고
// 결과 JavaScript 객체로 해결되는 promise 를 반환합니다.
return response.json();
})
.then((data) => {
// 이제 'data'는 JavaScript 객체입니다. 속성에 액세스할 수 있습니다.
console.log("JSON 데이터를 성공적으로 파싱했습니다:");
console.log(`Todo 제목: ${data.title}`);
console.log(`완료 여부: ${data.completed}`);
})
.catch((error) => {
// fetch 작업 중에 오류가 발생하면 .catch() 블록이 실행됩니다.
console.error("데이터 가져오기 또는 파싱 오류:", error);
});
이 업데이트된 코드에서 두 번째 .then() 블록은 이제 data를 JavaScript 객체로 받습니다. 템플릿 리터럴 (백틱 ` 구문)을 사용하여 data.title 및 data.completed의 값을 포함하는 문자열을 생성하여 JSON 이 성공적으로 파싱되었음을 보여줍니다.
이제 터미널에서 스크립트를 다시 실행하여 새 출력을 확인합니다.
node ~/project/index.js
파싱된 JSON 객체의 속성에 성공적으로 액세스했음을 확인하는 더 구조화된 출력을 볼 수 있습니다.
예상 출력:
Successfully parsed JSON data:
Todo Title: delectus aut autem
Is Completed: false
HTML 요소에 가져온 데이터 표시하기
이 단계에서는 API 에서 가져온 데이터를 웹 페이지에 표시하는 방법을 배우게 됩니다. 개발에는 콘솔에 데이터를 기록하는 것이 유용하지만, 최종 목표는 종종 이 정보를 사용자에게 제공하는 것입니다. 이를 위해서는 콘텐츠를 구조화할 HTML 파일과 Document Object Model(DOM) 을 조작할 JavaScript 가 필요합니다.
먼저 HTML 파일이 필요합니다. 왼쪽 파일 탐색기에서 ~/project 디렉터리에 index.html이라는 새 파일을 만듭니다.
다음 기본 HTML 구조를 index.html 파일에 추가합니다. 이 파일에는 제목과 data-output ID 를 가진 div 요소가 포함되어 있으며, 이는 가져온 데이터를 위한 컨테이너 역할을 합니다. 본문 끝에 있는 <script> 태그는 HTML 요소가 로드된 후 JavaScript 가 실행되도록 합니다.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>API 데이터 표시</title>
</head>
<body>
<h1>가져온 Todo 항목</h1>
<div id="data-output">
<p>데이터 로딩 중...</p>
</div>
<script src="index.js"></script>
</body>
</html>
다음으로 이 HTML 과 상호 작용하도록 ~/project/index.js 파일을 수정해야 합니다. 스크립트는 콘솔에 기록하는 대신 ID 로 div 요소를 찾아 API 의 데이터로 해당 콘텐츠를 업데이트합니다.
~/project/index.js의 내용을 다음 코드로 바꿉니다.
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
// 데이터를 표시할 HTML 요소 선택
const outputElement = document.getElementById("data-output");
fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
// 데이터가 있으면 HTML 콘텐츠를 업데이트합니다.
// innerHTML 을 사용하여 "Loading..." 메시지를 구조화된 데이터로 바꿉니다.
outputElement.innerHTML = `
<p><strong>제목:</strong> ${data.title}</p>
<p><strong>완료 여부:</strong> ${data.completed}</p>
`;
})
.catch((error) => {
// 오류가 발생하면 사용자에게 오류 메시지를 표시합니다.
outputElement.textContent = "데이터를 로드하지 못했습니다.";
console.error("데이터 가져오기 오류:", error);
});
이제 결과를 보려면 이 파일들을 웹 서버를 통해 제공해야 합니다. LabEx 환경에는 Python 이 포함되어 있으며, 간단한 내장 웹 서버가 있습니다.
- WebIDE 에서 새 터미널을 엽니다.
- 다음 명령을 실행하여 웹 서버를 시작합니다. 이렇게 하면 현재 디렉터리 (
~/project) 의 파일이 포트 8080 에서 제공됩니다.
python3 -m http.server 8080
- LabEx 플랫폼은 실행 중인 이 서비스를 감지하고
index.html페이지를 미리 볼 수 있는 "Web 8080" 탭을 제공합니다.

이제 초기 "Loading data..." 메시지를 대체하여 가져온 "todo" 항목의 제목과 완료 상태를 표시하는 웹 페이지를 볼 수 있습니다.
API 호출을 위한 오류 처리 구현
이 단계에서는 적절한 오류 처리를 구현하여 API 호출을 더욱 강력하게 만드는 데 중점을 둘 것입니다. API 요청은 잘못된 URL, 네트워크 문제 또는 서버 측 문제와 같은 다양한 이유로 실패할 수 있습니다. 더 나은 사용자 경험을 제공하려면 이러한 잠재적 실패를 우아하게 처리하는 것이 중요합니다.
fetch API 에 대한 중요한 세부 정보는 promise 가 404(찾을 수 없음) 또는 500(내부 서버 오류) 과 같은 HTTP 오류 상태에서 거부되지 않는다는 것입니다. 요청이 완료되지 못하게 하는 네트워크 장애가 있는 경우에만 거부됩니다. HTTP 오류를 처리하려면 성공적인 응답 (상태 코드 200-299) 에 대해 true인 부울 값인 response.ok 속성을 확인해야 합니다.
응답 상태를 확인하고 잠재적 오류를 처리하도록 ~/project/index.js를 업데이트해 보겠습니다. 첫 번째 .then() 블록 내에서 확인을 추가합니다.
~/project/index.js 파일의 내용을 다음 코드로 바꿉니다.
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
const outputElement = document.getElementById("data-output");
fetch(apiUrl)
.then((response) => {
// 응답이 성공했는지 확인합니다.
// 'ok' 속성은 상태 코드가 200-299 범위에 있으면 true 인 부울 값입니다.
if (!response.ok) {
// 그렇지 않으면 .catch() 블록에서 처리할 오류를 throw 합니다.
throw new Error(`HTTP 오류! 상태: ${response.status}`);
}
return response.json();
})
.then((data) => {
outputElement.innerHTML = `
<p><strong>제목:</strong> ${data.title}</p>
<p><strong>완료 여부:</strong> ${data.completed}</p>
`;
})
.catch((error) => {
// 사용자 친화적인 오류 메시지를 HTML 요소에 표시합니다.
outputElement.textContent =
"데이터를 로드하지 못했습니다. 나중에 다시 시도해 주세요.";
// 디버깅 목적으로 기술적 오류를 콘솔에 기록합니다.
console.error("데이터 가져오기 오류:", error);
});
오류 처리가 작동하는 것을 보기 위해 의도적으로 잘못된 API URL 을 사용해 보겠습니다. ~/project/index.js에서 apiUrl을 존재하지 않는 리소스를 가리키도록 수정합니다. 이렇게 하면 API 에서 404 찾을 수 없음 오류가 반환됩니다.
index.js 파일에서 이 줄을 변경합니다.
const apiUrl = 'https://jsonplaceholder.typicode.com/todos/1';
다음과 같이 변경합니다.
const apiUrl = 'https://jsonplaceholder.typicode.com/invalid-path/1';
이제 결과를 보겠습니다. 이전 단계의 Python 웹 서버가 계속 실행 중이라면 브라우저의 미리 보기 탭을 새로 고치기만 하면 됩니다. 중지했다면 터미널에서 다시 시작합니다.
python3 -m http.server 8080
그런 다음 미리 보기를 엽니다. 데이터 대신 페이지에 오류 메시지가 표시되어야 합니다. if (!response.ok) 확인이 404 오류를 잡았기 때문입니다.
웹 페이지의 예상 출력:
Failed to load data. Please try again later.
중요: 다음 단계로 진행하기 전에 apiUrl을 올바른 URL 인 https://jsonplaceholder.typicode.com/todos/1로 다시 변경하는 것을 잊지 마십시오.
데이터 전송을 위한 POST 요청 만들기
이 단계에서는 POST 요청을 사용하여 서버로 데이터를 보내는 방법을 배우게 됩니다. 지금까지는 데이터를 가져오기 (또는 "GET") 만 했습니다. POST 요청은 지정된 리소스에 데이터를 제출하는 데 사용되며, 종종 상태 변경을 유발하거나 서버에 새 항목을 생성합니다.
이를 위해 요청 메서드, 보내는 데이터를 설명하는 헤더, 요청 본문의 데이터 자체를 포함하여 fetch 함수에 더 많은 정보를 제공해야 합니다.
먼저 데이터를 입력하여 API 로 보낼 수 있도록 ~/project/index.html 파일을 업데이트합니다. index.html의 전체 내용을 다음으로 바꿉니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>POST Request Example</title>
</head>
<body>
<h1>새로운 Todo 항목 생성</h1>
<form id="add-todo-form">
<input
type="text"
id="todo-title"
placeholder="새로운 todo 제목 입력"
required
/>
<button type="submit">Todo 추가</button>
</form>
<hr />
<h2>서버 응답:</h2>
<div id="response-output"></div>
<script src="index.js"></script>
</body>
</html>
이 HTML 은 텍스트 입력과 제출 버튼이 있는 간단한 폼과 서버 응답을 표시할 div를 생성합니다.
다음으로 폼 제출을 처리하고 POST 요청을 만들기 위해 ~/project/index.js의 코드를 완전히 바꿉니다.
~/project/index.js의 내용을 다음 코드로 바꿉니다.
// 새 todo 를 생성하기 위한 API 엔드포인트
const apiUrl = "https://jsonplaceholder.typicode.com/todos";
// DOM 에서 폼과 응답 출력 요소를 가져옵니다.
const todoForm = document.getElementById("add-todo-form");
const responseOutput = document.getElementById("response-output");
// 폼의 submit 이벤트에 대한 이벤트 리스너를 추가합니다.
todoForm.addEventListener("submit", function (event) {
// 기본 폼 제출 동작을 방지합니다.
event.preventDefault();
// 입력 필드에서 제목을 가져옵니다.
const todoTitle = document.getElementById("todo-title").value;
// POST 요청에서 보내려는 데이터
const newTodo = {
title: todoTitle,
completed: false,
userId: 1
};
// fetch 요청에 대한 옵션
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newTodo)
};
// POST 요청을 보냅니다.
fetch(apiUrl, requestOptions)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP 오류! 상태: ${response.status}`);
}
// API 는 새 'id'를 포함한 생성된 객체를 반환합니다.
return response.json();
})
.then((data) => {
// 서버의 응답을 출력 div 에 표시합니다.
responseOutput.innerHTML = `<p>Todo 가 성공적으로 생성되었습니다!</p><pre>${JSON.stringify(data, null, 2)}</pre>`;
})
.catch((error) => {
responseOutput.textContent = "Todo 를 생성하지 못했습니다.";
console.error("오류:", error);
});
});
새로운 requestOptions 객체를 자세히 살펴보겠습니다.
method: 'POST':fetch에 POST 요청을 수행하도록 지시합니다.headers: { 'Content-Type': 'application/json' }: 이 헤더는 본문의 데이터가 JSON 형식임을 서버에 알립니다.body: JSON.stringify(newTodo): 이것이 우리가 보내는 실제 데이터입니다. 보내기 전에 JSON 문자열로 변환해야 합니다.
이제 실행 중이 아니면 웹 서버를 다시 시작합니다.
python3 -m http.server 8080
미리 보기를 열고 입력 필드에 새 todo 항목의 제목을 입력한 다음 "Todo 추가" 버튼을 클릭합니다. 성공 메시지와 서버에서 반환된 데이터가 표시되어야 하며, 여기에는 "생성한" 항목의 새 id가 포함됩니다.

API 키로 요청 인증하기
이 단계에서는 API 키를 사용하여 API 요청을 인증하는 방법을 배우게 됩니다. 많은 API 는 사용자를 식별하고, 데이터 접근을 제어하며, 사용량을 추적하기 위해 인증을 요구합니다. API 키는 API 사용 권한이 있음을 증명하기 위해 요청에 포함하는 고유한 문자열입니다.
API 키를 보내는 데는 여러 가지 방법이 있지만, 일반적이고 안전한 방법은 요청 헤더에 포함하는 것이며, 일반적으로 Authorization 헤더를 사용합니다.
이 예시에서는 API 키가 필요한 보호된 사용자 데이터를 가져오는 것을 시뮬레이션할 것입니다. 인증 정보를 보내는 표준 방법인 "Bearer" 토큰과 함께 Authorization 헤더를 포함하도록 코드를 수정할 것입니다.
먼저, 가져온 사용자 데이터만 표시하도록 ~/project/index.html 파일을 단순화해 보겠습니다. 내용을 다음으로 바꿉니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>인증된 API 요청</title>
</head>
<body>
<h1>사용자 프로필 (보호됨)</h1>
<div id="user-profile">
<p>사용자 데이터 로딩 중...</p>
</div>
<script src="index.js"></script>
</body>
</html>
다음으로, ~/project/index.js의 내용을 아래 코드로 바꿉니다. 이 스크립트는 GET 요청을 만들어 사용자 데이터를 가져오고 헤더에 가짜 API 키를 포함합니다.
// 사용자 프로필을 위한 API URL 정의
const apiUrl = "https://jsonplaceholder.typicode.com/users/1";
// 실제 애플리케이션에서는 이 키를 API 제공업체로부터 가져옵니다.
const apiKey = "YOUR_SECRET_API_KEY_HERE";
// 출력을 위한 HTML 요소 선택
const userProfileElement = document.getElementById("user-profile");
// 인증을 위한 헤더를 포함하여 요청 옵션 객체 생성
const requestOptions = {
method: "GET",
headers: {
Authorization: `Bearer ${apiKey}`
}
};
// 인증된 GET 요청 보내기
fetch(apiUrl, requestOptions)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP 오류! 상태: ${response.status}`);
}
return response.json();
})
.then((data) => {
// 가져온 사용자 데이터 표시
userProfileElement.innerHTML = `
<p><strong>이름:</strong> ${data.name}</p>
<p><strong>이메일:</strong> ${data.email}</p>
<p><strong>웹사이트:</strong> ${data.website}</p>
`;
})
.catch((error) => {
userProfileElement.textContent = "사용자 프로필을 로드하지 못했습니다.";
console.error("오류:", error);
});
이 코드에서:
- 플레이스홀더
apiKey를 정의합니다. requestOptions객체를 생성합니다.headers안에Authorization키를 추가합니다.Bearer ${apiKey}값은 일반적인 형식으로, "Bearer"는 토큰 유형이고 그 뒤에 키 자체가 옵니다.
참고: 사용하고 있는 JSONPlaceholder API 는 공개 API 이며 실제로 API 키가 필요하지 않습니다. 이 헤더는 단순히 무시될 것입니다. 그러나 이 코드는 인증이 필요한 많은 실제 API 에 사용할 표준 방법을 보여줍니다.
결과를 보려면 웹 서버가 아직 실행 중이 아니라면 시작합니다.
python3 -m http.server 8080
그런 다음 미리 보기를 엽니다. 페이지에 사용자 프로필이 성공적으로 로드되어 표시되며, 인증된 API 요청을 올바르게 구조화했음을 보여줍니다.
요약
이 실습에서는 최신 fetch API 를 사용하여 JavaScript 에서 API 를 호출하는 방법을 배웠습니다. 공개 API 엔드포인트에서 데이터를 검색하기 위해 기본적인 GET 요청을 만드는 것부터 시작했습니다. Promise 를 사용하여 fetch의 비동기적 특성을 처리하고, .then() 블록을 연결하여 응답을 처리하고 본문 텍스트를 JSON 으로 파싱하는 연습을 했습니다. 주요 기술에는 HTML 요소 내에서 가져온 데이터를 동적으로 표시하고, 잠재적인 네트워크 오류를 관리하기 위해 .catch() 블록으로 강력한 오류 처리를 구현하는 것이 포함되었습니다.
이러한 기본 사항을 바탕으로 필요한 헤더와 JSON 페이로드를 포함하여 POST 요청을 구성하고 실행하여 서버로 데이터를 보내는 방법을 탐색했습니다. 마지막으로, 보호된 리소스에 대한 권한 있는 액세스를 얻기 위해 API 키를 포함하는 것을 포함하여 요청을 인증함으로써 API 통신을 보호하는 일반적인 방법을 배웠습니다.



