DIARY

2024.12.02

zayn 2024. 12. 4. 20:21

희힁 오늘은 체크리스트 정리 ★ 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를 표시:
    1. 로그인 상태:
      • 환영 메시지와 함께 로그아웃 및 프로필 수정 버튼 제공.
    2. 비로그인 상태:
      • 이메일 및 비밀번호 입력 필드와 로그인/회원가입 버튼 제공.

8. 내보내기

export default AuthApp;
  • AuthApp 컴포넌트를 기본 내보내기(export)로 지정.

전체 기능 요약

  1. 회원가입: 새로운 사용자를 생성.
  2. 로그인: 인증 토큰 및 사용자 정보를 서버에서 가져옴.
  3. 프로필 업데이트: 사용자 정보를 수정.
  4. 로그아웃: 인증 토큰과 사용자 정보를 초기화.
  5. 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:
  • 에러 처리:
    • 요청 중 에러가 발생하면 .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. 전체 동작 요약

  1. 컴포넌트가 처음 렌더링되면 useEffect가 실행되어 axios.get 요청을 보냅니다.
  2. 요청이 성공하면 서버로부터 받은 데이터가 posts 상태에 저장됩니다.
  3. posts 상태가 업데이트되면 컴포넌트가 다시 렌더링되며, 각 포스트의 제목이 <ul> 리스트로 표시됩니다.
  4. 요청 실패 시 콘솔에 에러 메시지가 출력됩니다.

5. axios 요청 결과

[
  { "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를 사용하여 설정이 미리 정의된 새로운 인스턴스를 생성합니다.
    • 이 인스턴스를 통해 여러 요청에 동일한 설정을 재사용할 수 있습니다.

설정 내용

  1. baseURL:
    • 모든 요청에 공통으로 사용되는 기본 URL입니다. 예를 들어, apiClient.get('/users')는 실제 요청 URL을 https://api.example.com/users로 만듭니다.
  2. timeout:
    • 요청 제한 시간입니다. 여기서는 요청이 1초 안에 완료되지 않으면 에러가 발생합니다.
  3. 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); // 요청 실패 시 에러 메시지 출력
  }
};

작동 방식

  1. apiClient.get('/users'):
    • apiClient 인스턴스를 사용해 /users 엔드포인트로 GET 요청을 보냅니다.
    • 실제 요청 URL은 https://api.example.com/users가 됩니다.
  2. await:
    • 비동기 요청이 완료될 때까지 기다립니다.
    • 요청 성공 시 반환된 데이터를 response.data로 접근합니다.
  3. try-catch 블록:
    • 요청 성공 시 console.log를 사용해 데이터 출력.
    • 요청 실패 시 catch 블록에서 에러를 처리하고 콘솔에 에러 메시지 출력.

3. 함수 호출

fetchUsers();
  • fetchUsers 함수를 호출하여 실제로 API 요청을 실행합니다.

전체 동작 요약

  1. axios.create를 사용해 공통 설정을 가진 apiClient를 생성.
  2. fetchUsers 함수에서 apiClient를 사용해 /users 엔드포인트로 GET 요청을 보냄.
  3. 요청 성공 시:
    • 응답 데이터를 console.log로 출력.
  4. 요청 실패 시:
    • 에러 메시지를 console.error로 출력.

이 코드의 장점

  1. 재사용성:
    • apiClient를 통해 모든 요청에서 기본 URL, 헤더, 타임아웃 등을 반복적으로 설정할 필요가 없습니다.
  2. 유지보수성:
    • 기본 설정 변경이 필요할 경우 apiClient에서 한 번만 수정하면 됩니다.
  3. 가독성:
    • 요청 로직이 간결하고 명확해집니다.

실제 요청 예시

코드 실행 시 가정

[
  { "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의 주요 장점

  1. 자동 캐싱:
    • 데이터가 한 번 가져와지면 캐시로 저장되고, 동일한 요청은 캐시에서 처리됩니다.
  2. 자동 리페치(refetch):
    • 데이터의 변화가 감지되면 자동으로 최신 데이터를 가져옵니다.
  3. 로딩/에러 상태 관리:
    • isLoading, isError 등 상태 관리가 내장되어 있습니다.
  4. 쿼리 무효화:
    • invalidateQueries를 통해 특정 데이터를 업데이트하거나 새로고침할 수 있습니다.
  5. 중복 요청 방지:
    • 동일한 쿼리는 하나의 요청만 보내도록 처리합니다.

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();
}, []);

작동 방식

  1. useEffect:
    • 컴포넌트가 처음 렌더링될 때 실행됩니다.
    • 두 번째 매개변수로 빈 배열([])을 전달하여, 이 함수가 컴포넌트 생명 주기에서 단 한 번만 실행되도록 합니다.
  2. axios.get:
    • JSON Server(http://localhost:3000/posts)에서 데이터를 가져옵니다.
  3. 상태 업데이트:
    • 가져온 데이터를 setPosts를 통해 posts 상태에 저장합니다.
  4. 에러 처리:
    • 데이터를 가져오는 중 문제가 발생하면 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); // 에러 발생 시 콘솔에 출력
  }
};

작동 방식

  1. axios.post:
    • JSON Server의 http://localhost:3000/posts 엔드포인트로 POST 요청을 보내 새로운 게시글 데이터를 추가합니다.
    • 여기서는 title이 "새 포스트"인 데이터를 전송합니다.
  2. 상태 업데이트:
    • 기존의 posts 상태 배열에 새로 추가된 데이터를 병합하여 상태를 업데이트합니다.
  3. 에러 처리:
    • 데이터를 추가하는 중 문제가 발생하면 console.error를 통해 에러를 콘솔에 출력합니다.

4. UI 구성

return (
  <div>
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
    <button onClick={addPost}>포스트 추가</button>
  </div>
);

작동 방식

  1. 게시글 리스트 출력:
    • posts.map을 사용하여 posts 상태의 각 요소를 <li>로 렌더링합니다.
    • key 속성:
      • React에서 리스트를 렌더링할 때 각 항목에 고유한 key가 필요합니다. 여기서는 JSON Server에서 생성한 id를 사용합니다.
    • post.title:
      • 각 게시글의 제목을 출력합니다.
  2. 포스트 추가 버튼:
    • onClick 이벤트로 addPost 함수가 호출됩니다.
    • 새로운 포스트가 추가되면 리스트가 업데이트되어 화면에 반영됩니다.

5. 전체 동작 흐름

  1. 컴포넌트가 렌더링되면 useEffect가 실행되어 JSON Server에서 게시글 데이터를 가져옵니다.
  2. 가져온 데이터는 posts 상태에 저장되며, <ul> 리스트로 화면에 표시됩니다.
  3. 사용자가 "포스트 추가" 버튼을 클릭하면:
    • 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