BioPlayground

🧬
목록으로

Ajax란 — 비동기 웹 통신

Ajax의 개념부터 fetch API 사용법까지. 페이지 전체를 다시 불러오지 않고 서버와 데이터를 주고받는 핵심 기술을 배웁니다.

중급
|
12
|
검증 완료 (2026-07)
Ajaxfetch API비동기 통신XMLHttpRequestREST API
진행률0/26 (0%)

Ajax란 — 비동기 웹 통신

이 토픽을 마치면

페이지 새로고침 없이 서버와 데이터를 주고받는 Ajax의 원리를 이해하고, fetch API로 GET/POST 요청을 보낼 수 있습니다.


새로고침의 문제

전통적인 웹에서는 서버에 뭔가를 요청하면 페이지 전체가 새로 불러와졌습니다. 검색어를 입력하고 Enter를 누르면 화면이 하얗게 깜빡이면서 결과 페이지가 통째로 로딩됩니다.

구글 검색은 다릅니다. 검색어를 입력하면 추천 검색어가 밑에 쏙쏙 뜹니다. 페이지가 새로고침되지 않습니다. 이게 Ajax입니다 — 페이지를 새로 불러오지 않고, 필요한 데이터만 서버에서 가져옵니다.

Ajax는 Asynchronous JavaScript and XML의 약자인데, 지금은 XML 대신 JSON을 씁니다. 이름만 남아있는 셈입니다.


옛날 방식 — XMLHttpRequest

javascript
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/users');
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    const data = JSON.parse(xhr.responseText);
    console.log(data);
  }
};
xhr.send();

보시다시피 번거롭습니다. readyState 값을 확인하고, 상태 코드를 체크하고, 응답을 직접 파싱해야 합니다. 이 코드가 콜백 안에 콜백으로 중첩되면 소위 "콜백 지옥"이 됩니다.


현재 표준 — fetch API

javascript
const response = await fetch('/api/users');
const data = await response.json();
console.log(data);

세 줄입니다. fetch는 Promise를 반환하니까 async/await과 자연스럽게 결합됩니다.


GET — 데이터 가져오기

javascript
async function getUsers() {
  const res = await fetch('/api/users');

  if (!res.ok) {
    throw new Error(`HTTP ${res.status}`);
  }

  const users = await res.json();
  return users;
}

주의할 점: fetch404나 500에서도 reject하지 않습니다. 네트워크 에러(서버 연결 실패)에서만 reject합니다. 그래서 res.ok(200~299인지)를 직접 확인해야 합니다.


POST — 데이터 보내기

javascript
async function createUser(name, email) {
  const res = await fetch('/api/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ name, email }),
  });

  if (!res.ok) {
    throw new Error(`HTTP ${res.status}`);
  }

  return await res.json();
}

body에 넣을 데이터를 JSON.stringify로 문자열로 바꾸고, Content-Typeapplication/json으로 설정합니다. 이 헤더가 없으면 서버가 본문을 JSON으로 파싱하지 않습니다.


실전 패턴 — 로딩/에러/성공

javascript
const resultDiv = document.getElementById('result');

async function loadUsers() {
  resultDiv.textContent = '로딩 중...';

  try {
    const res = await fetch('/api/users');
    if (!res.ok) throw new Error(`서버 오류: ${res.status}`);

    const users = await res.json();
    resultDiv.textContent = users
      .map(u => `${u.name} (${u.email})`)
      .join('\n');
  } catch (err) {
    resultDiv.textContent = `오류: ${err.message}`;
  }
}

이 세 가지 상태(로딩/성공/에러)를 관리하는 건 프론트엔드 개발에서 반복되는 패턴입니다. React에서는 useState로, Vue에서는 ref로 같은 구조를 만듭니다.


fetch vs XMLHttpRequest 비교

XMLHttpRequestfetch
문법콜백 기반, 장황함Promise 기반, 간결
JSON 파싱JSON.parse(xhr.responseText) 수동.json() 메서드 제공
에러 처리readyState + status 직접 확인res.ok + try/catch
스트리밍불가ReadableStream 지원
취소xhr.abort()AbortController
쿠키 전송기본 포함credentials: 'include' 명시 필요

자주 하는 실수

  1. Content-Type 누락 — POST에서 headers를 안 넣으면 서버가 req.body를 파싱 못합니다
  2. 이중 .json() 호출res.json()은 한 번만 호출 가능합니다. body stream은 한 번 읽으면 소진됩니다
  3. CORS 에러 — 다른 도메인으로 fetch하면 브라우저가 차단합니다. 서버에서 Access-Control-Allow-Origin 헤더를 설정해야 합니다

핵심

Ajax는 페이지 새로고침 없이 서버와 데이터를 주고받는 기술입니다. 현대 웹에서는 fetch API + async/await이 표준입니다. fetch는 네트워크 에러에서만 reject하므로, res.ok를 반드시 확인하세요.