091
[JS/React] REST 본문
1. REST
- REST(Representational State Transfer)는 웹의 자원을 URI로 표현하고 HTTP Method 메서드로 처리하는 방식을 의미합니다.
-> HTTP Method는 GET, POST, PUT/PATCH, DELETE로 나뉘며 각 역할은 데이터 조회, 등록, 전체수정, 일부수정, 삭제입니다.
-> 클라이언트에서 서버로 요청(Request)를, 서버에서 클라이언트로 응답(Response)를 주고받을 때 웹에서 HTTP 통신을 기본으로 HTTP 메세지를 주고받습니다. 위의 내용을 더 자세히 알고싶으면 아래 글을 참고하면 됩니다.
REST 아키텍처 & HTTP 메세지
1. REST(Representational State Transfer) - REST는 분산 하이퍼미디어 시스템(ex: 웹)을 위한 소프츠웨어 아키텍처의 한 형식으로, 시스템의 모든 것을 자원(Resource)으로 규정하고, 이 자원의 상태를 JSON/XML 등
in-ouput91.tistory.com
- HTTP Message 중 응답 메세지의 시작 줄은 프로토콜 버전+HTTP 상태 코드+상태 텍스트 구성됩니다. 이때 이 상태코드에 따라 서버가 클라이언트 요청을 어떻게 처리했는지를 알 수 있습니다.


| 클래스 | 범위 | 의미 | 발생 주체 |
| 2XX | 200~299 | 성공(Success) | 정상처리 |
| 4XX | 400~499 | 클라이언트 오류 | 요청한 쪽 잘못 |
| 5XX | 500~599 | 서버 오류 | 응답하는 쪽 잘못 |
• 200 OK: 요청이 정상적으로 처리됨(가장 많이 보는 성공 코드)
• 201 Created: 요청이 성공적으로 처리되어 리소스가 새로 생성됨
• 400 Bad Request: 잘못된 문법 등으로 서버가 요청을 이해할 수가 없음
• 401 Unauthorized: 인증이 필요하거나 인증 실패
• 403 Forbidden: 서버가 요청을 이해했지만 권한 부족 등으로 거부
• 404 Not Found: 요청한 리소스(페이지 등)을 찾을 수 없음
• 500 Internal Sever Error: 서버 내부 오류로 요청 처리 실패
• 502 Bad Gateway: 게이트웨이/프록시 서버가 잘못된 응답을 받음
• 503 Service Unavailable: 서버가 일시적으로 요청을 처리할 수 없음(과부하, 점검 등)
*더 추가적인 내용은 아래 글을 통해 학습하면됩니다.
HTTP 상태 코드(Status Code)
1. HTTP 상태 코드- HTTP 상태코드는 클라이언트가 서버로 보낸 요청이 성공했는지, 실패했다면 누구의 책임인지를 3자리 숫자로 규격화한 국제 통신 표준입니다. 백의 자리를 숫자로 5개의 클래스
in-ouput91.tistory.com
2. Axios
- XHR은 [브라우저->OS->네트워크->서버] 이 일련의 과정을 처리해주는, 서버에 요청을 보낼 수 있게 브라우저가 제공하는 내장 객체입니다. 원래 XHR가 없었을 때는 서버에 데이터를 오게하기 위해서 개발자가 TCP 소켓을 열어 IP 주소를 찾고 HTTP 메세지를 직접 텍스트로 조립하여 바이트 단위로 데이터를 전송하고 응답 바이트를 수신한 뒤 파싱하여 연결을 닫아야했습니다.
- Fetch는 XHR의 콜백지옥을 보완하기 위해 나온 브라우저 내장 함수이고, Axios 역시 XHR의 콜백지옥을 Promise 객체로 해결한 서드파티 라이브러리입니다.
| 항목 | Fetch API | Axios |
| 설치 | 불필요(브라우저 내장) | npm install axios |
| json 변환 | res.json() 수동 호출 | 자동(res.data로 즉시 사용) |
| 에러 처리 | 4xx, 5xx도 .then()으로 들어옴 | 4xx, 5xx는 .catch()로 자동 분기 |
| 타임아웃•인터셉터 | 직접 구현 | 옵션 한 줄로 지원 |
| 구형 브라우저 | 일부 미지원 | 폭넓게 지원 |
// Fetch
fetch('/posts/1')
.then(res => res.json()) // JSON 변환 수동
.then(data => console.log(data));
// Axios
axios.get('/posts/1')
- Axios는 브라우저 및 Node.js를 위한 HTTP 비동신 통신 라이브러리로, 다양한 HTTP 요청 메서드를 지원하고 Promise 기반으로 설계되어 then, catch, finally 메서드 등을 사용 가능합니다.
| 메서드 | 시그니처 | 용도 | body 유무 |
| GET | axios.get(url[, config]) | 데이터 조회 | X |
| POST | axios.post(url, data[, config]) | 데이터 등록 | O |
| PUT | axios.put(url, data[, config]) | 데이터 수정 | O |
| DELETE | axios.delete(url[, config]) | 데이터 삭제 | X |
-> 시그니처에서 대괄호의 위치가 어색하게 느껴질 수 있지만, []는 선택사항이라는 표시로 config는 선택사항이라는 의미입니다.
-> config는 axios에게 요청할 때 추가 옵션을 전달하는 객체로, baseURL(서버 주소), params(쿼리스트링), headers(HTTP 헤더), timeout(타임아웃) 등을 넣을 수 있습니다.
-> Promise는 비동기 언어인 JS의 내장 객체로, 비동기 작업의 결과를 담습니다. pending, fulfilled, rejected 총 3가지 상태가 있습니다. pending은 아직 결과가 없는 상태로, 서버에서 아직 응답이 오지 않은 상태입니다. 서버의 응답이 오면 fulfilled 상태가 되어 .then()을 실행하고, 에러가 나면 rejected 상태가 되어 .catch()를 실행합니다.
-> async/await은 Promise 체이닝의 가독성 문제를 해결하기 위한 문법적 설탕으로, 내부적으로 Promise와 동일하게 동작하지만, 코드가 위에서 아래로 읽혀 직관적입니다. async는 함수 앞에 붙여 해당 함수가 Promise를 반환하도록 하고, await는 async 함수 안에서만 사용 가능하며 Promise가 fulfilled 상태가 될 때까지 함수 내부에서 기다립니다. 에러처리는 try/catch를 사용합니다.
// Promise 체이닝
axios.get('/posts')
.then(res => setData(res.data))
.catch(err => setError(err.message))
.finally(() => setLoading(false));
// async/await
const fetchData = async () => {
try {
const res = await axios.get('/posts');
setData(res.data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
- 실무 표준 패턴 3-state은 서버 통신에서 존재하는 3가지 상황을 나타내는 로딩 중, 실패, 성공을 각각 상황에 맞게 화면에 보여주는 패턴을 의미합니다.
import { useEffect, useState } from 'react';
import axios from 'axios';
export default function State3(){
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(()=>{
const fetchPosts = async () =>{
try {
setLoading(true);
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
setData(response.data);
} catch (error) {
setError(error.message);
} finally {
setLoading(false); //성공,실패와 무관하게 항상 실행
}
};
fetchPosts();
}, []);
if(loading) return <p>데이터 불러오는 중...</p>;
if(error) return <p style={{color: 'red'}}>에러:{error}</p>
return(
<div>
<h1>Posts</h1>
<ul>
{data.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
)
}
-> 3개의 상태를 두고 상황에 맞게 각 화면을 다르게 띄우면 됩니다.
-> fetch api나 axios 경우 Promise 객체를 반환하고 useEffect(()=>{},[]) 콜백함수의 경우 cleanup함수만을 return할 수 있기 때문에 useEffect를 직접 async로 만들 수 없습니다. 따라서 useEffect 내부에서는 따로 함수로 선언한 뒤에 호출하는 방식으로 사용합니다.

3. 백엔드 서버 연동
- node.js란 브라우저 밖에서 JavaScript를 실행할 수 있는 환경으로, 원래 자바스크립트는 브라우저 안에서만 실행이 가능했습니다. node.js의 등장으로 터미널에서도 실행이 가능해졌습니다. 그런 node.js로 서버를 쉽게 만들게 해주는 프레임워크가 Express입니다.
mkdir apiServer //새 폴더를 생성해줍니다.
cd apiServer
npm init -y # package.json 생성
npm install express cors # express, cors 설치
-> 위의 코드를 통해 my-app 내부에 apiServer 폴더를 만들고 이후에 package.json을 만들어 나중에 사용할 때도 수월하게 만들어줍니다.(다른 사람이 프로젝트를 받았을 때 npm install을 치면 package.json에 있는 라이브러리가 전부 설치됩니다.)
- CORS는 브라우저가 막는 것으로, 해결은 서버에서 해야합니다. 응답 시에 허용 헤더를 함께 보내면 됩니다. 자세한 내용을 알고 싶으면 아래 글을 참고하면 됩니다.
CORS(Cross-Origin Resource Sharing)
1. CORS - 브라우저는 기본적으로 다른 출처의 리소스를 함부로 가져오면 안된다는 보안 정책을 가지고 있습니다. 이런 보안 정책을 SOP(Same Origin Policy)라고 합니다.-> 여기서 Origin(출처)란 프로토콜
in-ouput91.tistory.com
- 실습: node.js + express 기반 웹 서버
const express = require('express'); //express 라이브러리 불러오기
const cors = require('cors'); //cors 라이브러리 불러오기
const app = express(); //express 실행해서 app 객체 생성, 서버 설정 용도
const PORT = 3001; // PORT 번호
app.use(cors()); //cors 허용, 없으면 react(5173)에서 express(3001) 요청 시 차단
app.use(express.json()); //모든 요청의 body를 json으로 자동 파싱
// GET 요청 처리
app.get('/data', (req, res) => {
console.log('RECV[GET] ' +
req.query.name + ", " + req.query.age);
res.json({
message: 'GET 요청 성공!',
data: [1, 2, 3, 4],
});
});
// POST 요청 처리
app.post('/data', (req, res) => {
console.log('RECV[POST] ' +
req.body.name + ", " + req.body.age);
res.json({
message: 'POST 요청 성공!',
data: [1, 2, 3, 4],
});
});
// 서버 시작
app.listen(PORT, () => {
console.log(`서버가 http://localhost:${PORT} 에서 실행 중`);
});
-> express, cors를 require를 통해 불러와줍니다. 그리고 express()를 호출하여 서버를 만드는데 필요한 기능들이 담긴 객체를 반환해줍니다. 이 app은 미들웨어 등록, Json파싱(.use()), 요청 처리 등록(.get(), .post()), 서버 실행(.listen()) 등을 할 때 사용됩니다.

- 로그인 실습
import React, { useState } from 'react';
import axios from 'axios';
export default function LoginForm() {
const [id, setId] = useState('');
const [password, setPassword] = useState('');
const [result, setResult] = useState(null);
/*
const handleLogin = () => {
axios.post('http://localhost:3001/login', {
id: id, //id라고만 적어도됨(ES6 문법, 키와 변수명이 같으면 하나로 작성 가능)
password: password,
})
.then((response) => { //성공
setResult(response.data.message);
})
.catch((error) => { //실행
if (error.response) {
setResult(error.response.data.message);
}
});
};
*/
const handleLogin = async () => {
try {
const res = await axios.post('http://localhost:3001/login', {id,password});
setResult(res.data.message);
} catch (err) {
if (error.response) {
setResult(err.response.data.message);
}
}
};
return (
<div>
<h2>로그인</h2>
<input
type="text"
placeholder=
"아이디"
value={id}
onChange={(e) =>
setId(e.target.value)}
/>
<br />
<input
type="password"
placeholder=
"비밀번호"
value={password}
onChange={(e) =>
setPassword(e.target.value)}
/>
<br />
<button onClick={handleLogin}>
로그인 </button>
<p>{result}</p>
</div>
);
}
-> then/catch를 async/await로 더 간단하게 작성할 수 있습니다.
const express = require('express'); //express 라이브러리 불러오기
const cors = require('cors'); //cors 라이브러리 불러오기
const app = express(); //express 실행해서 app 객체 생성, 서버 설정 용도
const PORT = 3001; // PORT 번호
app.use(cors()); //cors 허용, 없으면 react(5173)에서 express(3001) 요청 시 차단
app.use(express.json()); //모든 요청의 body를 json으로 자동 파싱
const USER = {
id: 'admin',
password: '1234',
}
app.post('/login',(req, res) => {
const {id, password } = req.body;
if(id === USER.id && password === USER.password){
res.json({
success: true,
message: '로그인에 성공!',
})
} else {
res.status(401).json({
success: false,
message:'아이디 또는 비밀번호가 틀렸습니다.',
})
}
});
app.listen(PORT, () => {
console.log(`서버 실행중: http://localhost:${PORT}`);
});'Programming Language > JavaScript&TypeScript' 카테고리의 다른 글
| [TS/React] TypeScript (1) | 2026.06.07 |
|---|---|
| [JS/React] Shared State, Context (0) | 2026.06.06 |
| [JS/React] 리액트 라우터(React Router) (0) | 2026.05.24 |
| [JS/React] 리스트와 키, 입력 폼 (0) | 2026.04.18 |
| [JS/React] 이벤트 핸들링 & 조건부 렌더링 (0) | 2026.04.12 |