리액트(React)는 현대 웹 애플리케이션 개발에서 가장 인기 있는 라이브러리 중 하나입니다. 특히, 서버와의 통신을 통해 데이터를 처리하는 기능은 현대 애플리케이션에서 필수적입니다. 이 글에서는 API와 서버와의 통신 방법, CRUD(생성, 조회, 수정, 삭제) 기능을 리액트로 구현하는 방법에 대해 다루겠습니다.
1. API란?
API(Application Programming Interface)는 소프트웨어 간의 상호작용을 위해 정의된 인터페이스입니다. 웹 API는 HTTP 프로토콜을 통해 데이터와 기능에 접근할 수 있는 방법을 제공합니다. 일반적으로 API를 통해 RESTful 서비스를 사용하여 데이터를 CRUD 방식으로 처리합니다.
2. CRUD 기능 이해하기
CRUD는 Create(생성), Read(조회), Update(수정), Delete(삭제)의 약자로, 데이터 관리의 기본적 기능을 의미합니다. 리액트 애플리케이션에서 CRUD 기능을 효율적으로 구현하기 위해 서버와 통신하는 방식에 대해 알아볼 것입니다. 우리가 사용할 API는 JSONPlaceholder라는 무료 API를 사용할 것입니다.
2.1. JSONPlaceholder API 소개
JSONPlaceholder는 REST API를 제공하여 가상의 데이터를 테스트하고 예제 코드를 작성할 수 있는 서비스입니다. 여러 종류의 리소스를 제공하며, 특히 다음과 같은 리소스를 사용할 것입니다:
- Posts (게시글)
- Comments (댓글)
- Users (사용자)
3. 환경 설정
리액트 프로젝트를 시작하기 위해, 먼저 Create React App을 사용하여 새로운 리액트 프로젝트를 생성합니다. 다음 명령어를 터미널에 입력하여 프로젝트를 생성합니다:
npx create-react-app my-crud-app
프로젝트가 생성되면, 해당 디렉토리로 이동하고 의존성을 설치합니다:
cd my-crud-app
4. API 통신을 위한 Axios 설치하기
API 통신을 위해 Axios 라이브러리를 사용합니다. 다음 명령어로 Axios를 설치합니다:
npm install axios
5. 기본 구조 만들기
이제 리액트 애플리케이션의 기본 구조를 만들겠습니다. src
디렉토리 안에 components
폴더를 만들고, 그 안에 PostList.js
파일을 생성합니다. 이 파일은 게시글 목록을 표시하는 컴포넌트입니다:
// src/components/PostList.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
const PostList = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
setPosts(response.data);
} catch (error) {
console.error('Error fetching posts:', error);
}
};
fetchPosts();
}, []);
return (
게시글 목록
{posts.map(post => (
-
{post.title}
{post.body}
))}
);
};
export default PostList;
6. CRUD 구현하기
이제 CRUD 기능을 Implement 해보겠습니다. 게시글을 추가할 수 있는 폼을 추가하고, 수정 및 삭제 기능도 구현할 것입니다.
6.1. 게시글 추가하기
새로운 게시글을 추가하기 위해, 폼을 구성하고 Axios를 사용하여 POST 요청을 보내겠습니다. PostForm.js
파일을 생성합니다:
// src/components/PostForm.js
import React, { useState } from 'react';
import axios from 'axios';
const PostForm = ({ onAddPost }) => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await axios.post('https://jsonplaceholder.typicode.com/posts', {
title,
body,
});
onAddPost(response.data);
setTitle('');
setBody('');
} catch (error) {
console.error('Error adding post:', error);
}
};
return (
);
};
export default PostForm;
6.2. 게시글 수정하기
게시글을 수정하기 위해, 선택된 게시글의 데이터를 업데이트할 수 있는 기능을 추가하겠습니다. EditPost.js
파일을 생성합니다:
// src/components/EditPost.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const EditPost = ({ postId, onUpdatePost }) => {
const [post, setPost] = useState(null);
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
useEffect(() => {
const fetchPost = async () => {
try {
const response = await axios.get(`https://jsonplaceholder.typicode.com/posts/${postId}`);
setPost(response.data);
setTitle(response.data.title);
setBody(response.data.body);
} catch (error) {
console.error('Error fetching post:', error);
}
};
fetchPost();
}, [postId]);
const handleUpdate = async (e) => {
e.preventDefault();
try {
const response = await axios.put(`https://jsonplaceholder.typicode.com/posts/${postId}`, {
title,
body,
});
onUpdatePost(response.data);
} catch (error) {
console.error('Error updating post:', error);
}
};
if (!post) return null;
return (
);
};
export default EditPost;
6.3. 게시글 삭제하기
게시글 삭제 기능을 위해 게시글 목록에서 삭제할 수 있는 버튼을 추가하겠습니다:
// 수정된 src/components/PostList.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import PostForm from './PostForm';
import EditPost from './EditPost';
const PostList = () => {
const [posts, setPosts] = useState([]);
const [editingPostId, setEditingPostId] = useState(null);
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
setPosts(response.data);
} catch (error) {
console.error('Error fetching posts:', error);
}
};
fetchPosts();
}, []);
const handleAddPost = (newPost) => {
setPosts((prevPosts) => [...prevPosts, newPost]);
};
const handleUpdatePost = (updatedPost) => {
setPosts((prevPosts) =>
prevPosts.map((post) => (post.id === updatedPost.id ? updatedPost : post))
);
setEditingPostId(null);
};
const handleDeletePost = async (postId) => {
try {
await axios.delete(`https://jsonplaceholder.typicode.com/posts/${postId}`);
setPosts((prevPosts) => prevPosts.filter((post) => post.id !== postId));
} catch (error) {
console.error('Error deleting post:', error);
}
};
return (
게시글 목록
{editingPostId ? (
) : null}
{posts.map((post) => (
-
{post.title}
{post.body}
))}
);
};
export default PostList;
7. 최종 결과물 조합하기
이제 모든 컴포넌트를 App.js
에서 조합해 보겠습니다:
// src/App.js
import React from 'react';
import PostList from './components/PostList';
const App = () => {
return (
리액트 CRUD 예제
);
};
export default App;
8. 결론
이번 글에서는 리액트를 사용하여 API와의 통신을 통해 CRUD 기능을 구현하는 방법에 대해 알아보았습니다. API를 통해 데이터를 처리하는 경험은 실전 개발에서도 매우 유용하게 사용됩니다. 리액트와 Axios를 활용하여 효과적인 데이터 관리 및 사용자 인터페이스를 구축하는 방법을 익혔길 바랍니다.
9. 추가적인 학습 자료
리액트와 API 통신에 대한 더 많은 내용을 학습하고 싶다면 다음 자료를 참고하십시오: