브라우저 JavaScript에서 API(응용 프로그래밍 인터페이스)는 직접 작성하지 않고도 작업을 수행하기 위해 호출할 수 있는 개체 및 함수 집합입니다. 브라우저는 모든 페이지에 Web API라는 대규모 세트를 제공합니다.
세 가지를 먼저 만나보실 수 있습니다: 페이지용 document, 브라우저 및 장치용 navigator, 네트워크용 fetch.
두 번째 의미는 서버 API입니다. 이는 데이터(주로 JSON)로 요청에 응답하는 인터넷의 또 다른 프로그램입니다. 브라우저에서는 그 자체가 웹 API인 fetch를 사용하여 접근할 수 있습니다. 이 가이드에서는 두 가지 모두를 다룹니다.
첫 번째 것을 시도해 보세요. 버튼을 누른 다음 창 크기를 조정하세요.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Web APIs in one page</title>
<style>
body { margin: 0; padding: 18px; font-family: system-ui, sans-serif; background: #f4f5f7; color: #1d2330; }
button { font: inherit; padding: 9px 16px; border: 0; border-radius: 8px; background: #2563eb; color: #fff; cursor: pointer; }
table { margin-top: 14px; width: 100%; max-width: 460px; border-collapse: collapse; background: #fff; border-radius: 10px; overflow: hidden; }
td { padding: 8px 10px; border-bottom: 1px solid #eceef2; font-size: 14px; }
td code { font-size: 12.5px; color: #6b7280; }
td:last-child { font-weight: 600; text-align: right; }
</style>
</head>
<body>
<button id="ask">Ask the browser</button>
<table>
<tr><td>Language<br><code>navigator.language</code></td><td id="lang">?</td></tr>
<tr><td>Window width<br><code>window.innerWidth</code></td><td id="width">?</td></tr>
<tr><td>Online<br><code>navigator.onLine</code></td><td id="online">?</td></tr>
<tr><td>Page title<br><code>document.title</code></td><td id="title">?</td></tr>
</table>
<script>
// document, navigator and window are objects the browser gives every page
const show = (id, value) => document.getElementById(id).textContent = value;
function ask() {
show('lang', navigator.language);
show('width', window.innerWidth + 'px');
show('online', navigator.onLine ? 'yes' : 'no');
show('title', document.title);
}
document.getElementById('ask').addEventListener('click', ask);
// APIs also send events: update the width when the window is resized
window.addEventListener('resize', () => show('width', window.innerWidth + 'px'));
</script>
</body>
</html>
여기에는 아무것도 설치되지 않았습니다. navigator, window 및 document는 모든 페이지에 존재하며 바로 사용할 수 있습니다.
JavaScript와 Web API는 같은 것이 아닙니다
JavaScript 언어는 Math, JSON, Date 및 Promise와 같은 기능을 제공합니다. 페이지, 장치 또는 네트워크에 닿는 모든 것은 브라우저에서 나옵니다. MDN은 "JavaScript 언어 위에 위치하는" 브라우저 API 구성을 호출합니다.

이는 도움을 검색할 때 중요합니다. 페이지의 텍스트 변경에 대한 질문은 JavaScript 구문 질문이 아니라 DOM 질문입니다.
모든 API의 구성 방식
브라우저 API는 동일한 패턴을 따르므로 한 번 사용하면 다음은 익숙합니다.
- 진입점. 시작하는 개체:
document,navigator.geolocation, 캔버스의getContext(). navigator.language와 같이 읽는 속성.- 메서드 호출(예:
document.getElementById()). - 이벤트 API가
resize와 같이 보내는 이벤트입니다. addEventListener로 청취합니다.
일부 최신 API는 HTTPS를 통해 제공되는 페이지에서만 실행되며 일부는 먼저 사용자에게 권한을 요청합니다. 예를 들어 알림 API는 권한 프롬프트를 표시합니다.
| 종류 | 그것이 사는 곳 | 예 | 요구 사항 |
|---|---|---|---|
| 브라우저 API | 브라우저 내부 | document, navigator |
아무것도; 그것은 내장되어있다 |
| 권한이 있는 브라우저 API | 브라우저 내부 | 알림, 지리적 위치 | 사용자가 그렇다고 대답함 |
| 서버 API | HTTP를 통해 도달한 또 다른 프로그램 | fetch('/api/products') |
URL; 때로는 열쇠 |
API를 사용하기 전에 API가 존재하는지 확인하세요.
모든 브라우저에 모든 API가 있는 것은 아닙니다. 누락된 항목을 호출하면 오류가 발생하고 나머지 스크립트가 중지됩니다. MDN의 대답은 기능 감지입니다. 해당 속성이 상위 개체에 존재하는지 확인하세요.
if ('geolocation' in navigator) {
navigator.geolocation.getCurrentPosition(show);
} else {
showManualForm();
}
이 페이지는 브라우저에서 다음과 같은 8가지 검사를 실행합니다.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Feature detection</title>
<style>
body { margin: 0; padding: 18px; font-family: system-ui, sans-serif; background: #f4f5f7; color: #1d2330; }
p { margin: 0 0 12px; font-size: 14px; }
ul { list-style: none; margin: 0; padding: 0; max-width: 460px; background: #fff; border-radius: 10px; }
li { display: flex; justify-content: space-between; gap: 10px; padding: 8px 12px; border-bottom: 1px solid #eceef2; font-size: 14px; }
li code { font-size: 13px; }
.yes { color: #0f5132; font-weight: 600; }
.no { color: #9a3412; font-weight: 600; }
</style>
</head>
<body>
<p>Secure context: <b id="secure"></b></p>
<ul id="list"></ul>
<script>
// Each check asks: does this object have this property?
const checks = [
['fetch', 'fetch' in window],
['navigator.geolocation', 'geolocation' in navigator],
['navigator.clipboard', 'clipboard' in navigator],
['navigator.share', 'share' in navigator],
['navigator.vibrate', 'vibrate' in navigator],
['navigator.serviceWorker', 'serviceWorker' in navigator],
['Notification', 'Notification' in window],
['IntersectionObserver', 'IntersectionObserver' in window],
];
const list = document.getElementById('list');
for (const [name, ok] of checks) {
const li = document.createElement('li');
li.innerHTML = '<code>' + name + '</code><span class="' + (ok ? 'yes">available' : 'no">missing') + '</span>';
list.append(li);
}
document.getElementById('secure').textContent = window.isSecureContext ? 'yes' : 'no';
</script>
</body>
</html>
Chromium, Firefox 및 WebKit 엔진을 사용한 테스트에서 navigator.vibrate는 Chromium에서만 사용할 수 있었습니다. 이것이 바로 수표가 귀하의 코드에 속하는 이유입니다. HTML의 위치정보는 하나의 권한 기반 API의 전체 예를 보여줍니다.
가져오기를 사용하여 서버 API 호출
서버 API는 데이터를 반환하는 URL입니다. fetch(url)는 Response로 해결되는 약속을 반환합니다. 그런 다음 그것을 확인하고 본문을 읽으십시오.

async function loadProducts() {
const response = await fetch('/api/products');
if (!response.ok) throw new Error('Server answered ' + response.status);
const products = await response.json();
// put products on the page
}
두 개의 키워드가 대기를 수행합니다. await는 약속이 확정될 때까지 일시 중지됩니다. 비동기 및 대기가 이에 대해 설명합니다. response.json()는 JSON.parse와 동일한 작업인 본문을 구문 분석합니다.
항상 response.ok를 확인하세요
fetch는 네트워크 오류 또는 잘못된 URL과 같은 오류가 있는 경우 거부합니다. 서버가 404 또는 500으로 응답하면 가져오기는 계속 성공하고 오류 페이지가 본문으로 도착합니다.

확인하지 않고 json()는 HTML 오류 페이지를 구문 분석하려고 시도하고 SyntaxError를 발생시킵니다. 하나의 if (!response.ok) 라인은 이를 명확한 메시지로 바꿉니다.
완성된 예: 로드, 실패, 재시도
이 버전에는 각 실패에 대한 로딩 메시지, 목록 및 읽을 수 있는 오류가 있습니다. 대체 기능이 네트워크를 대체합니다. fakeFetch는 실제 Response 개체를 반환하므로 그 뒤의 코드는 fetch로 작성하는 코드와 정확히 같습니다.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Show API data</title>
<style>
body { margin: 0; padding: 18px; font-family: system-ui, sans-serif; background: #f4f5f7; color: #1d2330; }
.bar { display: flex; flex-wrap: wrap; gap: 8px; }
button { font: inherit; font-size: 14px; padding: 8px 12px; border: 1px solid #d5d9e0; border-radius: 8px; background: #fff; cursor: pointer; }
button.main { background: #2563eb; border-color: #2563eb; color: #fff; }
#status { margin: 12px 0 8px; font-size: 14px; color: #6b7280; }
#status.error { color: #9a3412; font-weight: 600; }
ul { list-style: none; margin: 0; padding: 0; max-width: 460px; }
li { display: flex; justify-content: space-between; padding: 9px 12px; margin-bottom: 6px; background: #fff; border-radius: 8px; font-size: 14px; }
</style>
</head>
<body>
<div class="bar">
<button class="main" data-case="ok">Load products</button>
<button data-case="404">Server says 404</button>
<button data-case="offline">Network fails</button>
</div>
<p id="status">Press a button.</p>
<ul id="list"></ul>
<script>
// Stand-in for fetch(url): it returns a real Response object, without the network.
// On your own site, replace fakeFetch(...) with fetch('/api/products').
function fakeFetch(kind) {
return new Promise((resolve, reject) => setTimeout(() => {
if (kind === 'offline') reject(new TypeError('Failed to fetch'));
else if (kind === '404') resolve(new Response('Not found', { status: 404 }));
else resolve(new Response(JSON.stringify([
{ name: 'Notebook', price: 4.5 },
{ name: 'Pen set', price: 7 },
{ name: 'Desk lamp', price: 24.99 },
]), { headers: { 'Content-Type': 'application/json' } }));
}, 600));
}
const status = document.getElementById('status');
const list = document.getElementById('list');
async function load(kind) {
status.className = '';
status.textContent = 'Loading...';
list.innerHTML = '';
try {
const response = await fakeFetch(kind);
// a 404 or 500 does not throw by itself, so check ok
if (!response.ok) throw new Error('Server answered ' + response.status);
const products = await response.json(); // text -> objects
for (const p of products) {
const li = document.createElement('li');
li.innerHTML = '<span></span><b></b>';
li.firstChild.textContent = p.name; // textContent: data is never run as HTML
li.lastChild.textContent = '$' + p.price.toFixed(2);
list.append(li);
}
status.textContent = products.length + ' products loaded.';
} catch (err) {
status.className = 'error';
status.textContent = 'Could not load: ' + err.message;
}
}
document.querySelectorAll('[data-case]').forEach((btn) =>
btn.addEventListener('click', () => load(btn.dataset.case)));
</script>
</body>
</html>
- 로드 상태:
await앞에 상태 텍스트를 설정합니다. - 오류: 하나의
try...catch가 잘못된 상태와 네트워크 오류를 모두 처리합니다. - 안전한 출력:
textContent는 페이지에 API 데이터를 텍스트로 표시하므로 HTML로 실행되지 않습니다.
실제 서버를 사용하려면 fakeFetch(kind)를 fetch('/api/products')로 바꾸세요. 그러면 페이지가 아닌 서버에 따라 두 가지 사항이 달라집니다.
CORS: a server on another site must send Access-Control-Allow-Origin
for your page, or the browser hides the answer from your script.
Keys: if the API needs a secret key, call it from your own server.
MDN warns never to embed API keys in front-end code
unless the API vendor explicitly allows it.
CORS 설명에서 첫 번째 항목을 자세히 다룹니다.
작동하지 않을 때
| 당신이 보는 것 | 원인 | 수정 |
|---|---|---|
| null 속성을 읽을 수 없습니다. | 요소가 존재하기 전에 스크립트가 실행되었습니다. | body 끝에 있는 요소 뒤의 스크립트를 넣으세요. |
데이터 대신 [object Promise] |
await 누락 |
await async 함수 내부 호출 |
json()의 구문 오류 |
서버가 HTML 오류 페이지를 보냈습니다. | json() 이전에 response.ok를 확인하세요. |
| 콘솔의 CORS 오류 | 다른 사이트에서는 귀하의 페이지를 허용하지 않습니다 | 이를 허용하는 API를 사용하거나 서버에서 호출하세요. |
... is not a function 또는 정의되지 않음 |
이 브라우저에는 API가 없거나 페이지가 HTTPS가 아닙니다. | 기능 감지 및 HTTPS를 통해 페이지 제공 |
| 로드 시 소리가 시작되지 않습니다. | 자동재생 정책 | 버튼 클릭으로 오디오 시작 |
아무것도 실행되지 않으면 HTML JavaScript가 작동하지 않음을 순서대로 해결하세요.
링크로 공유하세요
브라우저 API를 호출하는 페이지는 설명하는 것보다 시도해 보는 것이 더 쉽습니다. 스크린샷은 클릭할 수 없으며, 스크린샷에 표시되는 값은 독자의 것이 아닌 브라우저에 속합니다.
작업 버전을 보내려면 페이지를 NOS 문서에 붙여넣고 공유 링크 만들기를 선택하세요. 링크할 HTML이 이를 안내합니다.
페이지는 작성된 대로 렌더링되고 해당 스크립트가 실행되므로 링크가 있는 사람은 누구나 계정 없이 자신의 브라우저에서 버튼을 누를 수 있습니다. 나중에 코드를 변경하면 동일한 링크에 새 버전이 표시됩니다.
한 가지 제한 사항: 공유 NOS 페이지에서는 다른 사이트에 대한 가져오기 호출이 차단됩니다. DOM과 같은 브라우저 API가 작동하므로 완성된 예제에서는 라이브 서버 대신 독립 Response를 사용합니다.