웹에서 데이터를 가져오거나 서버로 데이터를 보내기 위한 도구야.
쉽게 말해, 웹 브라우저와 서버가 대화할 수 있도록 도와주는 메신저라고 생각하면 돼!
Axios는 배달 앱처럼 동작해!
클라이언트(사용자): "피자를 주문할게요!" 하고 요청을 보냄.
Axios(배달 앱): 주문 요청을 가게(서버)로 전달하고, 결과를 받아옴.
서버(가게): 요청을 처리하고, 피자(데이터)를 배달 앱(Axios)에게 전달.
클라이언트(사용자): 배달 앱(Axios)을 통해 데이터를 받아 결과를 확인.
1️⃣ Axios 설치
| 패키지 매니저 | 설치 명령어 |
|---|---|
| yarn | yarn add axios |
| pnpm | pnpm add axios |
2️⃣ GET 요청 예제 (서버에서 데이터 가져오기)
import axios from 'axios';
axios.get('https://jsonplaceholder.typicode.com/posts')
.then((response) => {
console.log(response.data); // 가져온 데이터를 출력
})
.catch((error) => {
console.error('데이터 가져오기 실패:', error);
});
// axios.get()은 서버에 데이터를 요청하는 코드야. 요청이 성공하면 response.data로 데이터를 받아오고, 실패하면 catch에서 에러를 처리해.
3️⃣ POST 요청 예제 (서버로 데이터 보내기)
import axios from 'axios';
axios.post('https://jsonplaceholder.typicode.com/posts', {
title: '새 게시글',
body: '내용입니다.',
userId: 1
})
.then((response) => {
console.log('성공적으로 추가됨:', response.data);
})
.catch((error) => {
console.error('추가 실패:', error);
});
//axios.post()는 데이터를 서버로 보내는 코드야, 여기서는 새로운 게시글 정보를 서버로 전송해.
axios.get
get은 서버의 데이터를 조회할 때 사용.// url에는 서버의 url이 들어가고, config에는 기타 여러가지 설정 추가가능. // config는 axios 공식문서에서 확인해봐! axios.get(url[, config]) // GET(url은 매개변수, 대괄호([]) 안의 값은 선택 입력사항.
// src/App.js
import React, { useEffect, useState } from "react";
import axios from "axios"; // axios import
const App = () => {
const [todos, setTodos] = useState(null);
// axios를 통해서 get 요청을 하는 함수를 생성.
// 비동기처리를 해야하므로 async/await 구문을 통해서 처리.
const fetchTodos = async () => {
const { data } = await axios.get("http://localhost:4000/todos");
setTodos(data); // 서버로부터 fetching한 데이터를 useState의 state로 set.
};
// 생성한 함수를 컴포넌트가 mount된 후 실행하기 위해 useEffect를 사용.
useEffect(() => {
// effect 구문에 생성한 함수를 넣어 실행.
fetchTodos();
}, []);
// data fetching이 정상적으로 되었는지 콘솔을 통해 확인.
console.log(todos);
return <div>App</div>;
};
export default App;
axios.post
post는 보통 서버에 데이터를 추가할 때 사용.// 보통은 클라이언트의 데이터를 body형태로 서버에 보내고자 할 때 사용. axios.post(url[, data[, config]]) // POST
// src/App.jsx
import React, { useEffect, useState } from "react";
import axios from "axios"; // axios import
const App = () => {
// 새롭게 생성하는 todo를 관리하는 state
const [todo, setTodo] = useState({
title: "",
});
const [todos, setTodos] = useState(null);
const fetchTodos = async () => {
const { data } = await axios.get("http://localhost:4000/todos");
setTodos(data);
};
// (원리를 꼭 이해!!!)
// HTTP에서는 body에 javascript 객체를 direct로 넣을 수 없어!
// axios는 내부적으로 JSON.stringify를 적용하기 때문에 이처럼 편리하게 사용하는 것 뿐이야.
const onSubmitHandler = async(todo) => {
await axios.post("http://localhost:4000/todos", todo);
};
// 만일 fetch를 사용했다면, 이렇게 JSON.stringify를 '직접' 해줘야 해.
// await fetch("http://localhost:4000/todos", {
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify(todo),
// });
useEffect(() => {
fetchTodos();
}, []);
return (
<>
<form
onSubmit={(e) => {
// 👇 submit했을 때 브라우저의 새로고침을 방지.
e.preventDefault();
onSubmitHandler(todo);
}}
>
<input
type="text"
onChange={(ev) => {
const { value } = ev.target;
setTodo({
...todo,
title: value,
});
}}
/>
<button>추가하기</button>
</form>
<div>
{todos?.map((todo) => (
<div key={todo.id}>{todo.title}</div>
))}
</div>
</>
);
};
export default App;
axios.delete
delete는 저장되어 있는 데이터를 삭제요청 할때 사용.axios.delete(url[, config]) // delete
// src/App.jsx
import React, { useEffect, useState } from "react";
import axios from "axios";
const App = () => {
const [todo, setTodo] = useState({
title: "",
});
const [todos, setTodos] = useState(null);
const fetchTodos = async () => {
const { data } = await axios.get("http://localhost:4000/todos");
setTodos(data);
};
const onSubmitHandler = (todo) => {
axios.post("http://localhost:4000/todos", todo);
};
// 새롭게 추가한 삭제 버튼 이벤트 핸들러
const onClickDeleteButtonHandler = (todoId) => {
axios.delete(`http://localhost:4000/todos/${todoId}`);
};
useEffect(() => {
fetchTodos();
}, []);
return (
<>
<form
onSubmit={(e) => {
e.preventDefault();
onSubmitHandler(todo);
}}
>
<input
type="text"
onChange={(ev) => {
const { value } = ev.target;
setTodo({
...todo,
title: value,
});
}}
/>
<button>추가하기</button>
</form>
<div>
{todos?.map((todo) => (
<div key={todo.id}>
{todo.title}
<button
type="button"
onClick={() => onClickDeleteButtonHandler(todo.id)}
>
삭제하기
</button>
</div>
))}
</div>
</>
);
};
export default App;
axios.patch
patch는 어떤 데이터를 수정요청 할때 사용.axios.patch(url[, data[, config]]) // patch
// src/App.jsx
import React, { useEffect, useState } from "react";
import axios from "axios";
const App = () => {
const [todo, setTodo] = useState({
title: "",
});
const [todos, setTodos] = useState(null);
// patch에서 사용할 id, 수정값의 state를 추가
const [targetId, setTargetId] = useState(null);
const [editTodo, setEditTodo] = useState({
title: "",
});
const fetchTodos = async () => {
const { data } = await axios.get("http://localhost:4000/todos");
setTodos(data);
};
const onSubmitHandler = (todo) => {
axios.post("http://localhost:4000/todos", todo);
};
const onClickDeleteButtonHandler = (todoId) => {
axios.delete(`http://localhost:4000/todos/${todoId}`);
};
// 수정버튼 이벤트 핸들러 추가 👇
const onClickEditButtonHandler = (todoId, edit) => {
axios.patch(`http://localhost:4000/todos/${todoId}`, edit);
};
useEffect(() => {
fetchTodos();
}, []);
return (
<>
<form
onSubmit={(e) => {
e.preventDefault();
onSubmitHandler(todo);
}}
>
{/* 👇 수정기능에 필요한 id, 수정값 input2개와 수정하기 버튼을 추가 */}
<div>
<input
type="text"
placeholder="수정하고싶은 Todo ID"
onChange={(ev) => {
setTargetId(ev.target.value);
}}
/>
<input
type="text"
placeholder="수정값 입력"
onChange={(ev) => {
setEditTodo({
...editTodo,
title: ev.target.value,
});
}}
/>
<button
// type='button' 을 추가해야 form의 영향에서 벗어남
type="button"
onClick={() => onClickEditButtonHandler(targetId, editTodo)}
>
수정하기
</button>
</div>
<input
type="text"
onChange={(ev) => {
const { value } = ev.target;
setTodo({
...todo,
title: value,
});
}}
/>
<button>추가하기</button>
</form>
<div>
{todos?.map((todo) => (
<div key={todo.id}>
{/* todo의 아이디를 화면에 표시 */}
{todo.id} :{todo.title}
<button
type="button"
onClick={() => onClickDeleteButtonHandler(todo.id)}
>
삭제하기
</button>
</div>
))}
</div>
</>
);
};
export default App;
네트워크 탭을 확인하면서 개발을 진행해야 해, 어떤 문제가 생겼을 때 이정보를 통해 디버깅을 할 수 있기 때문이야.Axios는 웹에서 데이터를 주고받는 작업을 간단하고 효율적으로 처리할 수 있도록 도와주는 도구야. "서버와 대화할 때 쓰는 편리한 메신저"로 생각하면 쉽다!
| 항목 | Axios | Fetch |
|---|---|---|
| 사용 편의성 | 간단한 문법과 추가 기능 제공 | 기본적으로 약간의 추가 코드 필요 |
| JSON 자동 처리 | 요청 및 응답에서 JSON 자동 처리 | JSON 변환을 수동으로 처리해야 함 |
| 요청 취소 기능 | 기본적으로 요청 취소 기능 제공 | 추가 라이브러리(AbortController) 필요 |
| 오류 처리 | HTTP 오류를 자동으로 .catch에서 처리 | HTTP 오류를 직접 확인 후 처리 필요 |
| 브라우저 지원 | 모든 브라우저에서 동작 | 최신 브라우저만 지원 (구형 브라우저 제한) |
| 추가 기능 | 타임아웃 설정, 헤더 관리 등 추가 기능 제공 | 기본 기능만 제공 |
Axios를 사용해서 GET 요청 코드를 작성하기에 앞서, 어떤 방식으로 요청 해야할지는 우리가 사용하는 json-server의 방식을 알아봐야 해.
다시 말해, Axios는 GET 요청을 할 수 있도록 도와주는 패키지일뿐이지, “어떻게 요청을 해야하지?” 와 같은 방식에 대한 확인은 우리가 사용할 API 명세서를 보아야 한다는 뜻이야. 예를 들어 GET 요청을 할 때 path variable로 해야할지, query로 보내야할지는 API를 만든 사람이 하라는대로 해야 하기때문이지.
.env와 .gitignore란?
.env(환경 변수 파일)
.env 파일은 중요한 설정 값이나 비밀 정보를 저장하는 파일이야.
(예) API 키, 데이터베이스 비밀번호, 서버 URL 등.
코드에 직접 노출하지 않고, 안전하게 관리하기 위해 사용해.
.env 사용법
.envAPI_KEY=123456789
DATABASE_URL=https://example.com
SECRET_KEY=mysecret
require('dotenv').config();
console.log(process.env.API_KEY); // "123456789"
.gitignore(Git 제외 파일 설정)
.gitignore 파일은 Git에 포함시키지 않을 파일이나 폴더를 지정하는 파일야.
(예) node_modules, .env, 빌드 파일 등.
민감한 정보나 불필요한 파일이 저장소에 올라가지 않도록 방지해.
.gitignore# node_modules 폴더 제외
node_modules/
# 환경 변수 파일 제외
.env
# 로그 파일 제외
*.log
# 운영 시스템별 파일 제외 (예: macOS)
.DS_Store
git rm --cached 파일이름
- .env가 중요한 이유:
- 보안: 중요한 정보를 코드에 직접 노출하지 않음.
- 환경별 설정 관리: 로컬 개발, 스테이징, 프로덕션 환경별로 다른 설정을 쉽게 관리.
- .gitignore가 중요한 이유:
- 저장소 정리: 프로젝트와 관련 없는 파일을 Git에 올리지 않아, 저장소가 깔끔해.
- 보안: 민감한 정보(.env 파일 등)가 저장소에 올라가지 않도록 방지.
- 한줄요약
.env민감한 정보(예: API 키, 비밀번호)를 안전하게 저장..gitignoreGit에 올리지 않을 파일을 지정해 저장소를 깨끗하고 안전하게 관리.