희힁 오늘은 체크리스트 정리 ★ 1일차
Q1. JWT 인증 서버
JWT 인증서버 (회원가입.로그인,프로필 수정만 제공하고 accessToken만 발급)를 이용해 회원가입,로그인,프로필 수정 기능을 구현하고, 로그인된 상태 관리를 할 수 있다.
[설명]
1. 상태 관리
const [user, setUser] = useState(null);
const [accessToken, setAccessToken] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
- user: 현재 로그인된 사용자의 정보를 저장.
- accessToken: 로그인 성공 시 서버로부터 받은 인증 토큰.
- email과 password: 입력 필드의 상태를 저장.
2. 회원가입 함수
const signup = async () => {
try {
await axios.post('/api/signup', { email, password });
alert('회원가입이 완료되었습니다. 로그인 해주세요.');
} catch (error) {
console.error(error);
alert('회원가입 실패');
}
};
- axios.post를 통해 /api/signup 엔드포인트로 email과 password 데이터를 전송.
- 성공 시 회원가입 완료 메시지 표시, 실패 시 에러 메시지 출력.
3. 로그인 함수
const login = async () => {
try {
const response = await axios.post('/api/login', { email, password });
setAccessToken(response.data.accessToken); // accessToken 저장
setUser(response.data.user); // 사용자 정보 저장
alert('로그인이 완료되었습니다.');
} catch (error) {
console.error(error);
alert('로그인 실패!');
}
};
- /api/login 엔드포인트로 로그인 요청을 전송.
- 성공 시 반환된 accessToken과 사용자 정보를 상태에 저장.
- 실패 시 에러 메시지 출력.
4. 프로필 업데이트 함수
const updateProfile = async (profileData) => {
try {
const response = await axios.put('/api/profile', profileData, {
headers: { Authorization: `Bearer ${accessToken}` },
});
setUser(response.data.user);
alert('프로필이 업데이트되었습니다.');
} catch (error) {
console.error(error);
alert('프로필 업데이트 실패');
}
};
- axios.put를 사용하여 /api/profile 엔드포인트로 사용자 프로필 데이터를 업데이트.
- Authorization 헤더에 Bearer ${accessToken}을 포함해 인증을 처리.
- 업데이트된 사용자 정보를 상태에 저장.
5. 로그아웃 함수
const logout = () => {
setAccessToken('');
setUser(null);
};
- accessToken과 user 상태를 초기화해 로그아웃 처리.
6. useEffect 활용
useEffect(() => {
// 필요 시 accessToken으로 사용자 정보 로드
}, []);
- 컴포넌트가 처음 렌더링될 때(componentDidMount) 실행.
- 예를 들어, 토큰이 있으면 사용자 정보를 로드하는 로직을 추가할 수 있음.
7. UI 구성
return (
<div>
{user ? (
<div>
<h1>환영합니다, {user.email}님!</h1>
<button onClick={logout}>로그아웃</button>
<button onClick={() => updateProfile({ email: 'newemail@example.com' })}>
프로필 수정
</button>
</div>
) : (
<div>
<h2>로그인 또는 회원가입</h2>
<input
type="email"
placeholder="이메일"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="비밀번호"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={login}>로그인</button>
<button onClick={signup}>회원가입</button>
</div>
)}
</div>
);
- 사용자가 로그인된 상태인지에 따라 다른 UI를 표시:
- 로그인 상태:
- 환영 메시지와 함께 로그아웃 및 프로필 수정 버튼 제공.
- 비로그인 상태:
- 이메일 및 비밀번호 입력 필드와 로그인/회원가입 버튼 제공.
- 로그인 상태:
8. 내보내기
export default AuthApp;
- AuthApp 컴포넌트를 기본 내보내기(export)로 지정.
전체 기능 요약
- 회원가입: 새로운 사용자를 생성.
- 로그인: 인증 토큰 및 사용자 정보를 서버에서 가져옴.
- 프로필 업데이트: 사용자 정보를 수정.
- 로그아웃: 인증 토큰과 사용자 정보를 초기화.
- UI: 상태에 따라 동적으로 변경되는 UI 제공.
Q2. Axios를 이용한 API 요청
axios를 이용하여 API요청을 보낼 수 있다.
[설명]
1. 상태 관리
const [posts, setPosts] = useState([]);
- posts: API에서 가져온 데이터를 저장하는 상태 변수.
- setPosts: posts 상태를 업데이트하는 함수.
- 초기값은 빈 배열([])로 설정되어 있습니다.
2. useEffect를 사용한 데이터 가져오기
useEffect(() => {
axios
.get('https://jsonplaceholder.typicode.com/posts')
.then((response) => {
setPosts(response.data); // API로부터 가져온 데이터를 posts 상태에 저장
})
.catch((error) => {
console.error('포스트를 가져오는 중 에러 발생:', error);
});
}, []);
- useEffect:
- 컴포넌트가 처음 렌더링될 때(componentDidMount) 실행됩니다.
- 두 번째 매개변수로 빈 배열([])을 전달하면, 이 함수는 한 번만 실행됩니다.
- axios.get:
- axios를 사용하여 외부 API(https://jsonplaceholder.typicode.com/posts)로 GET 요청을 보냅니다.
- 성공 시 response.data를 받아 posts 상태를 업데이트합니다.
- 에러 처리:
- 요청 중 에러가 발생하면 .catch() 블록이 실행되어 콘솔에 에러 메시지를 출력합니다.
3. 데이터 렌더링
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
- posts.map:
- posts 배열을 순회하며 각 포스트 데이터를 <li> 태그로 렌더링.
- key 속성:
- React에서 각 리스트 아이템에 고유한 key 값을 제공해야 효율적으로 렌더링을 관리합니다.
- 여기서는 post.id가 사용됩니다.
- post.title:
- API로부터 가져온 데이터 중 각 포스트의 제목(title)을 표시합니다.
4. 전체 동작 요약
- 컴포넌트가 처음 렌더링되면 useEffect가 실행되어 axios.get 요청을 보냅니다.
- 요청이 성공하면 서버로부터 받은 데이터가 posts 상태에 저장됩니다.
- posts 상태가 업데이트되면 컴포넌트가 다시 렌더링되며, 각 포스트의 제목이 <ul> 리스트로 표시됩니다.
- 요청 실패 시 콘솔에 에러 메시지가 출력됩니다.
5. axios 요청 결과
- 요청 URL: https://jsonplaceholder.typicode.com/posts
- 반환 데이터 예시:
[
{ "userId": 1, "id": 1, "title": "포스트 제목 1" },
{ "userId": 1, "id": 2, "title": "포스트 제목 2" },
{ "userId": 1, "id": 3, "title": "포스트 제목 3" }
]
위 데이터를 기반으로 컴포넌트는 아래와 같은 HTML을 렌더링합니다:
<ul>
<li>포스트 제목 1</li>
<li>포스트 제목 2</li>
<li>포스트 제목 3</li>
</ul>
코드의 사용 목적
- 외부 API와의 통신을 통해 데이터를 가져오고, 이를 화면에 표시하는 간단한 예제입니다.
- React 컴포넌트와 axios, useEffect의 기본적인 사용 방법을 학습하기 적합합니다.
Q3. axios 인스턴스
axios 인스턴스가 무엇인지를 알고 , 이를 구별 할 수 있다.(인터셉터는 필수가 아님)
[설명]
1. axios 인스턴스 생성
const apiClient = axios.create({
baseURL: 'https://api.example.com', // 모든 요청의 기본 URL
timeout: 1000, // 요청 제한 시간: 1000ms (1초)
headers: { 'X-Custom-Header': 'foobar' }, // 모든 요청에 공통적으로 포함될 헤더
});
- axios.create:
- axios를 사용하여 설정이 미리 정의된 새로운 인스턴스를 생성합니다.
- 이 인스턴스를 통해 여러 요청에 동일한 설정을 재사용할 수 있습니다.
설정 내용
- baseURL:
- 모든 요청에 공통으로 사용되는 기본 URL입니다. 예를 들어, apiClient.get('/users')는 실제 요청 URL을 https://api.example.com/users로 만듭니다.
- timeout:
- 요청 제한 시간입니다. 여기서는 요청이 1초 안에 완료되지 않으면 에러가 발생합니다.
- headers:
- 모든 요청에 공통적으로 포함될 HTTP 헤더를 설정합니다. 여기서는 X-Custom-Header라는 사용자 정의 헤더가 포함되어 있습니다.
2. axios 인스턴스를 사용하여 요청 보내기
const fetchUsers = async () => {
try {
const response = await apiClient.get('/users'); // '/users' 엔드포인트로 GET 요청
console.log('사용자 목록:', response.data); // 요청 성공 시 데이터 출력
} catch (error) {
console.error('사용자 정보를 가져오는 중 에러 발생:', error); // 요청 실패 시 에러 메시지 출력
}
};
작동 방식
- apiClient.get('/users'):
- apiClient 인스턴스를 사용해 /users 엔드포인트로 GET 요청을 보냅니다.
- 실제 요청 URL은 https://api.example.com/users가 됩니다.
- await:
- 비동기 요청이 완료될 때까지 기다립니다.
- 요청 성공 시 반환된 데이터를 response.data로 접근합니다.
- try-catch 블록:
- 요청 성공 시 console.log를 사용해 데이터 출력.
- 요청 실패 시 catch 블록에서 에러를 처리하고 콘솔에 에러 메시지 출력.
3. 함수 호출
fetchUsers();
- fetchUsers 함수를 호출하여 실제로 API 요청을 실행합니다.
전체 동작 요약
- axios.create를 사용해 공통 설정을 가진 apiClient를 생성.
- fetchUsers 함수에서 apiClient를 사용해 /users 엔드포인트로 GET 요청을 보냄.
- 요청 성공 시:
- 응답 데이터를 console.log로 출력.
- 요청 실패 시:
- 에러 메시지를 console.error로 출력.
이 코드의 장점
- 재사용성:
- apiClient를 통해 모든 요청에서 기본 URL, 헤더, 타임아웃 등을 반복적으로 설정할 필요가 없습니다.
- 유지보수성:
- 기본 설정 변경이 필요할 경우 apiClient에서 한 번만 수정하면 됩니다.
- 가독성:
- 요청 로직이 간결하고 명확해집니다.
실제 요청 예시
코드 실행 시 가정
- https://api.example.com/users로 GET 요청을 보냄.
- 응답 데이터:
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
콘솔 출력
사용자 목록: [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]
Q4. Tanstack Query의 useQuery와 userMutation
Tanstack Query 의 [useQuery] 와 [useMutation] 을 이용해 GET,POST,DELETE,PUT 기능들을 구현 할 수 있다.
[설명]
Tanstack Query란 무엇인가?
Tanstack Query는 클라이언트 상태와는 별개로 서버 상태를 관리하는 데 초점을 맞춘 라이브러리입니다. 이는 서버와의 통신을 효율적으로 처리하고 데이터 동기화를 유지하며, 간결하고 직관적인 코드를 작성할 수 있도록 도와줍니다.
Tanstack Query의 주요 장점
- 자동 캐싱:
- 데이터가 한 번 가져와지면 캐시로 저장되고, 동일한 요청은 캐시에서 처리됩니다.
- 자동 리페치(refetch):
- 데이터의 변화가 감지되면 자동으로 최신 데이터를 가져옵니다.
- 로딩/에러 상태 관리:
- isLoading, isError 등 상태 관리가 내장되어 있습니다.
- 쿼리 무효화:
- invalidateQueries를 통해 특정 데이터를 업데이트하거나 새로고침할 수 있습니다.
- 중복 요청 방지:
- 동일한 쿼리는 하나의 요청만 보내도록 처리합니다.
useQuery와 useMutation의 역할
- useQuery:
- 데이터를 서버에서 가져오는 데 사용됩니다. 주로 GET 요청에 활용됩니다.
- 데이터의 캐싱과 상태 관리를 자동으로 처리합니다.
- useMutation:
- 데이터를 서버에 전송하거나 업데이트, 삭제하는 데 사용됩니다. 주로 POST, PUT, DELETE 요청에 활용됩니다.
- 서버와의 상호작용이 성공적으로 완료된 후 특정 작업(예: 캐시 무효화)을 실행할 수 있습니다.
1. useQuery로 데이터 가져오기 (GET 요청)
import { useQuery } from 'react-query';
import axios from 'axios';
const fetchPosts = async () => {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
return response.data;
};
const PostsList = () => {
const { data, isLoading, isError } = useQuery('posts', fetchPosts);
if (isLoading) return
로딩 중...
;
if (isError) return
오류 발생!
;
return (
- {data.map((post) => (
- {post.title} ))}
);
};
설명
- useQuery('posts', fetchPosts):
- 첫 번째 인자는 쿼리 키로, 캐싱과 데이터 관리의 기준이 됩니다.
- 두 번째 인자는 데이터를 가져오는 비동기 함수입니다.
- isLoading, isError:
- 데이터 로딩 상태와 에러 상태를 간단히 관리할 수 있습니다.
2. useMutation으로 데이터 추가 (POST 요청)
import { useMutation, useQueryClient } from 'react-query';
import axios from 'axios';
const addPost = async (newPost) => {
const response = await axios.post('https://jsonplaceholder.typicode.com/posts', newPost);
return response.data;
};
const AddPostForm = () => {
const queryClient = useQueryClient();
const mutation = useMutation(addPost, {
onSuccess: () => {
queryClient.invalidateQueries('posts'); // 캐시 무효화
},
});
const handleAddPost = () => {
mutation.mutate({ title: '새 게시글', body: '내용', userId: 1 });
};
return 게시글 추가;
};
설명
- useMutation(addPost, { onSuccess }):
- 성공적으로 데이터를 추가한 후 invalidateQueries를 호출하여 posts 쿼리의 데이터를 새로고침합니다.
- mutation.mutate:
- 새로운 데이터를 서버에 전송합니다.
3. useMutation으로 데이터 수정 (PUT 요청)
const updatePost = async ({ id, updatedData }) => {
const response = await axios.put(`https://jsonplaceholder.typicode.com/posts/${id}`, updatedData);
return response.data;
};
const UpdatePostForm = () => {
const mutation = useMutation(updatePost);
const handleUpdatePost = () => {
mutation.mutate({ id: 1, updatedData: { title: '수정된 게시글 제목' } });
};
return 게시글 수정;
};
설명
- PUT 요청을 통해 기존 데이터를 업데이트.
- 서버에 변경된 데이터를 보내고 성공 여부를 처리합니다.
4. useMutation으로 데이터 삭제 (DELETE 요청)
const deletePost = async (id) => {
await axios.delete(`https://jsonplaceholder.typicode.com/posts/${id}`);
};
const DeletePostButton = ({ postId }) => {
const queryClient = useQueryClient();
const mutation = useMutation(deletePost, {
onSuccess: () => {
queryClient.invalidateQueries('posts');
},
});
return mutation.mutate(postId)}>게시글 삭제;
};
설명
- DELETE 요청을 통해 데이터를 삭제합니다.
- 삭제 후 invalidateQueries로 캐시를 무효화해 데이터 목록을 최신 상태로 유지합니다.
5. 데이터 동기화 및 캐시 무효화
Tanstack Query의 핵심은 캐시 무효화 기능을 활용한 데이터 동기화입니다.
- queryClient.invalidateQueries:
- 특정 쿼리의 캐시를 무효화하고 최신 데이터를 가져옵니다.
- queryClient.refetchQueries:
- 지정된 쿼리를 즉시 새로고침합니다.
결론
useQuery와 useMutation은 데이터의 가져오기, 추가, 수정, 삭제를 쉽게 구현할 수 있는 강력한 도구입니다. 이 두 훅을 적절히 활용하면 API 호출 로직을 간소화하고 애플리케이션의 유지보수를 크게 향상할 수 있습니다.
Tip:
- **useQuery**는 데이터 가져오기(GET)에,
- **useMutation**은 데이터 변경(POST, PUT, DELETE)에 활용하세요.
Q5. JSON Server
JSON server 가 무엇인지 알고 있고, 이를 내 프로젝트에서 띄워서 데이터를 CRUD 할 수 있다.
[설명]
1. 상태 관리
const [posts, setPosts] = useState([]);
- posts: 현재 JSON Server에서 가져온 게시글 데이터를 저장하는 상태 변수.
- setPosts: 상태를 업데이트하는 함수.
2. JSON Server에서 게시글 가져오기 (useEffect와 axios.get)
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await axios.get('http://localhost:3000/posts');
setPosts(response.data); // 가져온 데이터를 상태에 저장
} catch (error) {
console.error(error); // 에러 발생 시 콘솔에 출력
}
};
fetchPosts();
}, []);
작동 방식
- useEffect:
- 컴포넌트가 처음 렌더링될 때 실행됩니다.
- 두 번째 매개변수로 빈 배열([])을 전달하여, 이 함수가 컴포넌트 생명 주기에서 단 한 번만 실행되도록 합니다.
- axios.get:
- JSON Server(http://localhost:3000/posts)에서 데이터를 가져옵니다.
- 상태 업데이트:
- 가져온 데이터를 setPosts를 통해 posts 상태에 저장합니다.
- 에러 처리:
- 데이터를 가져오는 중 문제가 발생하면 console.error를 통해 에러를 콘솔에 출력합니다.
3. 게시글 추가 (axios.post)
const addPost = async () => {
try {
const response = await axios.post('http://localhost:3000/posts', {
title: '새 포스트',
});
setPosts([...posts, response.data]); // 기존 상태에 새로 추가된 데이터 병합
} catch (error) {
console.error(error); // 에러 발생 시 콘솔에 출력
}
};
작동 방식
- axios.post:
- JSON Server의 http://localhost:3000/posts 엔드포인트로 POST 요청을 보내 새로운 게시글 데이터를 추가합니다.
- 여기서는 title이 "새 포스트"인 데이터를 전송합니다.
- 상태 업데이트:
- 기존의 posts 상태 배열에 새로 추가된 데이터를 병합하여 상태를 업데이트합니다.
- 에러 처리:
- 데이터를 추가하는 중 문제가 발생하면 console.error를 통해 에러를 콘솔에 출력합니다.
4. UI 구성
return (
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
<button onClick={addPost}>포스트 추가</button>
</div>
);
작동 방식
- 게시글 리스트 출력:
- posts.map을 사용하여 posts 상태의 각 요소를 <li>로 렌더링합니다.
- key 속성:
- React에서 리스트를 렌더링할 때 각 항목에 고유한 key가 필요합니다. 여기서는 JSON Server에서 생성한 id를 사용합니다.
- post.title:
- 각 게시글의 제목을 출력합니다.
- 포스트 추가 버튼:
- onClick 이벤트로 addPost 함수가 호출됩니다.
- 새로운 포스트가 추가되면 리스트가 업데이트되어 화면에 반영됩니다.
5. 전체 동작 흐름
- 컴포넌트가 렌더링되면 useEffect가 실행되어 JSON Server에서 게시글 데이터를 가져옵니다.
- 가져온 데이터는 posts 상태에 저장되며, <ul> 리스트로 화면에 표시됩니다.
- 사용자가 "포스트 추가" 버튼을 클릭하면:
- addPost 함수가 실행되어 새로운 게시글이 서버에 추가됩니다.
- 추가된 게시글이 posts 상태에 병합되어 리스트가 업데이트됩니다.
6. 예제 결과
초기 상태
- JSON Server에서 데이터를 가져와 <ul> 리스트로 표시합니다.
<ul>
<li>게시글 1</li>
<li>게시글 2</li>
</ul>
<button>포스트 추가</button>
"포스트 추가" 버튼 클릭 후
- 새로운 게시글이 추가되고 화면이 업데이트됩니다.
<ul>
<li>게시글 1</li>
<li>게시글 2</li>
<li>새 포스트</li>
</ul>
<button>포스트 추가</button>
7. 이 코드의 사용 목적
- JSON Server:
- 간단한 로컬 REST API 서버를 사용하여 클라이언트-서버 통신을 연습.
- React:
- 상태 관리(useState)와 컴포넌트 생명 주기(useEffect)를 학습.
- axios:
- API 요청(GET, POST 등)을 구현하는 방법을 학습.
8. 확장 가능성
- 업데이트(PUT):
- 특정 게시글의 내용을 수정하는 기능 추가.
- 삭제(DELETE):
- 게시글을 삭제하는 기능 추가.
- 상태 관리 라이브러리 도입:
- React Query나 Redux를 사용하여 상태 관리 개선.
오늘은 한페이지씩 리뷰 >_<
'DIARY' 카테고리의 다른 글
자습...? (5) | 2024.12.02 |
---|---|
24.11.14 (1) | 2024.11.14 |
2024.11.11 (2) | 2024.11.11 |
2024.11.07 (0) | 2024.11.08 |
2024.11.04 (2) | 2024.11.04 |