이 파일의 학습 목적
03a — 동기·비동기·Ajax·Promise를 왜 배우나?
React에서 axios.get()을 쓸 때 왜 await를 붙이는지, .then()과 async/await의 차이가 뭔지 모르면 통신 코드가 이해되지 않는다.
03a는 동기/비동기 개념부터 시작해서 Ajax 20년 발전사, 콜백 지옥 → Promise → async/await 진화 과정을 한 번에 정리한다.
이 파일에서 배울 4가지
- ① 동기 vs 비동기 — 왜 UI가 멈추지 않고 요청을 보내는가
- ② Ajax 발전사 — XMLHttpRequest → jQuery → fetch → axios
- ③ 콜백 지옥 → Promise → async/await — 코드 가독성 진화
- ④ Ajax와 React의 관계 — useEffect + axios 패턴
프로젝트 코드 연결
- · 2·3차 React에서 axios로 API 호출 전체
- ·
const res = await axios.post('/api/user/login')
- ·
useEffect(() => { fetchBoards() }, [])
시리즈 순서:
01 Java 기초 → 02 Spring 기초 →
03a ← 지금 여기
→ 03b CORS·axios·@PathVariable
01 — 동기 vs 비동기
작업을 기다리냐 기다리지 않느냐 — 웹 통신의 핵심 개념
⏱️
동기(Synchronous) vs 비동기(Asynchronous)
Core Concept
🏦 동기 — 은행 창구 줄서기
1번 고객 업무 시작
⏳ 1번 끝날 때까지 대기
⏳ 아무것도 못함
1번 완료 → 2번 시작
순서대로 하나씩 처리
🍽️ 비동기 — 식당 진동벨
주문 완료 → 진동벨 받음
✅ 자리에서 다른 거 함
✅ 스마트폰 보기
✅ 대화하기
벨 울리면 음식 가져옴
🌐 웹에서의 비동기 — 왜 필요한가?
서버에 데이터 요청 → 응답이 올 때까지 0.5초 걸림
동기라면 → 0.5초 동안 브라우저 완전 멈춤 → 스크롤·클릭 아무것도 안 됨
비동기라면 → 요청 보내고 → 다른 작업 계속 → 응답 오면 화면 업데이트
→ Ajax가 비동기인 이유
JavaScript — 동기 vs 비동기 코드 비교
console.log("1번");
console.log("2번");
console.log("3번");
console.log("1번");
setTimeout(() => console.log("2번"), 1000);
console.log("3번");
💡 await = 비동기를 동기처럼 읽히게 만드는 문법
실제 동작은 비동기지만 코드는 위에서 아래로 읽힘
→ await axios.get(...) → 응답 올 때까지 다음 줄 실행 안 함 (코드 읽기엔 동기처럼 보임)
→ 실제로는 비동기로 동작 — 브라우저는 멈추지 않음
02 — Ajax 발전사 20년
XMLHttpRequest(2005) → jQuery → fetch → async/await → axios — 우리 프로젝트까지
📜
Ajax란?
History
📡 Ajax = Asynchronous JavaScript And XML
페이지 전체를 새로고침하지 않고 → 서버에서 데이터만 비동기로 가져오는 기술
1차 프로젝트 = 페이지 이동할 때마다 전체 새로고침 (Ajax 없음)
2·3차 프로젝트 = React + axios(Ajax) → 페이지 이동 없이 데이터만 가져옴
1
2005년
XMLHttpRequest — Ajax 원조
비동기 통신 최초 등장. 코드가 너무 복잡하고 콜백이 중첩되는 "콜백 지옥" 발생.
2
2006년
jQuery $.ajax — 간결하게 감쌈
XMLHttpRequest를 쓰기 쉽게 포장. 코드는 짧아졌지만 콜백 지옥은 여전히 존재.
3
2015년
fetch API — Promise로 콜백 지옥 해결
브라우저 내장 API. Promise 도입으로 .then().catch() 체인 방식 — 콜백 지옥 해결.
4
2017년
async/await — 동기 코드처럼 읽힘
Promise를 동기 코드처럼 읽히게 만든 문법. 내부적으로는 여전히 비동기. 가장 읽기 쉬운 방식.
5
현재 — 우리 프로젝트
axios — fetch보다 편리한 라이브러리 ⭐
fetch 기반이지만 더 많은 기능 추가. JSON 자동 변환, interceptor, baseURL 설정, 에러 처리가 훨씬 편함.
03 — 콜백 지옥 → Promise → async/await
같은 작업을 3가지 방식으로 — 왜 async/await이 표준이 됐는가
🔄
3가지 방식 비교 — 로그인 후 게시글 목록 가져오기
Evolution
JavaScript — 1단계: 콜백 지옥 (읽기 어려움)
login(username, password, function(user) {
getProfile(user.id, function(profile) {
getBoards(profile.role, function(boards) {
console.log(boards);
});
});
});
JavaScript — 2단계: Promise .then() 체인 (개선)
login(username, password)
.then(user => getProfile(user.id))
.then(profile => getBoards(profile.role))
.then(boards => console.log(boards))
.catch(error => console.log(error));
JavaScript — 3단계: async/await — 우리 프로젝트 방식 ⭐
async function loadData() {
try {
const user = await login(username, password);
const profile = await getProfile(user.id);
const boards = await getBoards(profile.role);
console.log(boards);
} catch (error) {
console.log(error);
}
}
💡 async/await 규칙
await는 반드시 async 함수 안에서만 사용 가능
async function은 항상 Promise를 반환
에러 처리는 try/catch로
04 — Ajax와 React의 관계
React가 Ajax를 대체한 게 아님 — React 안에서 axios(Ajax)를 사용하는 것
🤝
axios + React = 데이터 가져오기 + 화면 그리기
우리 프로젝트
axios (Ajax)
서버에서 데이터를
비동기로 가져오는 기술
GET /api/board/list
→ JSON 데이터 수신
React + useState
가져온 데이터로
화면을 만드는 기술
setBoards(data)
→ 화면 자동 업데이트
JavaScript — 우리 프로젝트 React 컴포넌트 실제 패턴
import axios from 'axios';
import { useState, useEffect } from 'react';
function BoardList() {
const [boards, setBoards] = useState([]);
useEffect(() => {
loadBoards();
}, []);
const loadBoards = async () => {
try {
const res = await axios.get('/api/board/list');
setBoards(res.data);
} catch (err) {
console.log(err);
}
};
return (
<ul>
{boards.map(board => <li>{board.title}</li>)}
</ul>
);
}
📌 우리 프로젝트에서
axios(Ajax)로 데이터 가져오고 →
useState(React)로 화면 자동 업데이트
→ baseURL은 src/api/api.js에서 Spring Boot 주소로 설정