TIL

24. 07. 25 TIL

효ㄷi 2024. 7. 25. 21:16

동기, 비동기

1. 동기 -> 요청을 보내면 요청을 받을 때까지 기다리고, 그 후에 다음 작업을 진행함. 순차적으로 처리됨

2. 비동기 -> 요청을 보내고 응답을 기다리지 않고, 바로 다음 작업을 진행함. 요청과 응답이 비순차적으로 일어남


promise

= 자바스크립트에서 비동기 작업의 결과를 처리하기 위해 사용되는 객체

비동기 작업이 완료되거나 실패했을 때, 각각의 결과를 쉽게 다룰 수 있도록 도와줌

 

프로미스 객체는 비동기 작업이 끝난 후 실행될 콜백을 등록할 수 있는 메서드를 제공

 

프로미스 객체는 then, catch, finally 메서드를 통해 이행되거나 거부된 이후의 동작을 정의할 수 있음

 

* 예제

프로미스 객체를 생성하려면 프로미스 생성자를 사용함

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;  // true 또는 false로 변경해 테스트해보세요

    if (success) {
      resolve("작업이 성공적으로 완료되었습니다!");
    } else {
      reject("작업이 실패했습니다.");
    }
  }, 2000);  // 2초 후에 작업이 완료
});

myPromise
  .then((result) => {
    console.log(result);  // "작업이 성공적으로 완료되었습니다!" 출력
  })
  .catch((error) => {
    console.log(error);  // "작업이 실패했습니다." 출력
  });

 

 

리액트에서는 useEffect와 함께 프로미스를 자주 사용함

import React, { useState, useEffect } from "react";

function App() {
  const [post, setPost] = useState(null);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts/1")
      .then((response) => response.json())
      .then((json) => setPost(json))
      .catch((error) => console.error("데이터 펫칭 오류! => ", error));
  }, []);

  return <div>{post ? <div>{post.title}</div> : <div>Loading...</div>}</div>;
}

export default App;

 

 

* promise.all 을 사용하면 여러 비동기 작업을 병렬로 처리할 수 있음

(여러 개의 비동기 작업을 동시에 실행하고, 모든 작업이 완료될 때까지 기다린 후 그 결과를 한번에 처리함)

import React, { useState, useEffect } from "react";

function App() {
  const [data, setData] = useState({ posts: [], users: [] });

  useEffect(() => {
    Promise.all([
      fetch("https://jsonplaceholder.typicode.com/posts").then((response) => response.json()),
      fetch("https://jsonplaceholder.typicode.com/users").then((response) => response.json())
    ])
      .then(([posts, users]) => {
        setData({ posts, users });
      })
      .catch((error) => console.error("데이터 펫칭 오류! => ", error));
  }, []);

  return (
    <div>
      <h1>Posts and Users Data</h1>
      <div>
        <h2>Posts</h2>
        {data.posts.length > 0 ? (
          data.posts.map((post) => <div key={post.id}>{post.title}</div>)
        ) : (
          <div>Loading posts...</div>
        )}
      </div>
      <div>
        <h2>Users</h2>
        {data.users.length > 0 ? (
          data.users.map((user) => <div key={user.id}>{user.name}</div>)
        ) : (
          <div>Loading users...</div>
        )}
      </div>
    </div>
  );
}

export default App;

async, await

= 프로미스 객체를 더욱 간편하게 다룰 수 있도록 도와줌

 

async 키워드로 정의된 함수는 항상 프로미스를 반환함

const testFunc = async () => {
  return 1;
};

const value = testFunc();
console.log("async/await test => ", value);  // Promise {<resolved>: 1}

await 키워드는 프로미스가 이행될 때까지 기다리고, 이행된 프로미스 결과를 반환함

 

async, await를 사용하는 이유는 가독성, 에러처리에 좋고, 코드가 간결해지기 때문임


fetch then & async await

= 모두 비동기 작업을 처리하는 방식

둘 다 비동기 작업을 처리할 때 사용되지만, 코드의 가독성과 작성 방식에 차이가 있음

 

1. fetch, then

프로미스 체이닝을 사용해 비동기 작업을 처리함

// JSONPlaceholder API에서 id가 1인 포스트를 가져옵니다.
fetch("https://posts/1")
  // fetch 함수는 네트워크 요청을 수행하고, 이를 비동기적으로 처리하기 위해 Promise를 반환합니다.
  
  .then((response) => {
    // 첫 번째 then 블록: 서버로부터의 응답(response) 객체를 받습니다.
    // response.json()을 호출하여 응답 본문을 JSON 형식으로 파싱합니다.
    // response.json()도 Promise를 반환합니다.
    return response.json();
  })
  
  .then((data) => {
    // 두 번째 then 블록: JSON으로 파싱된 데이터를 받습니다.
    // 이 데이터를 사용하여 필요한 작업을 수행합니다.
    console.log(data); // JSON 데이터를 콘솔에 출력합니다.
  })
  
  .catch((error) => {
    // catch 블록: 요청이나 응답 처리 중에 발생한 오류를 처리합니다.
    console.error("Error fetching data:", error); // 오류 메시지를 콘솔에 출력합니다.
  });

 

* 기억! =

프로미스 객체를 반환한다는 것은 비동기 작업이 완료됐을 때 (성공 & 실패) 결과 값을 나중에 사용할 수 있게 해주는 자바스크립트 객체를 반환한다는 것

 

파싱은 문자열 데이터를 특정 형식으로 변환하는 과정인데, 일반적으로 서버에서 응답 받은 데이터는 문자열 형식이고 이 문자열 데이터를 우리가 사용할 수 있는 객체나 배열 형태로 변환하는 과정임

 

2. async await 

최신 자바스크립트 환경에서 비동기 작업을 더 직관적으로 처리할 수 있는 방법

// async 키워드로 비동기 함수를 정의합니다.
// fetchData 함수는 항상 Promise를 반환합니다.
async function fetchData() {
  try {
    // await 키워드를 사용하여 fetch 함수가 반환하는 Promise가 이행될 때까지 기다립니다.
    // 이 때 response 변수는 서버로부터의 응답 객체를 받습니다.
    const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");

    // response.json()도 Promise를 반환하며, 이 Promise가 이행될 때까지 기다립니다.
    // 이 때 data 변수는 파싱된 JSON 데이터를 받습니다.
    const data = await response.json();

    // 파싱된 JSON 데이터를 콘솔에 출력합니다.
    console.log(data);
  } catch (error) {
    // try 블록 내에서 발생한 오류를 catch 블록에서 처리합니다.
    // 네트워크 요청 실패 또는 JSON 파싱 실패 시 오류가 발생할 수 있습니다.
    console.error("Error fetching data:", error);
  }
}

// fetchData 함수를 호출하여 데이터를 가져옵니다.
fetchData();

http

= 웹 상에서 데이터를 주고 받기 위한 프로토콜

클라이언트와 서버 간의 요청과 응답을 정의하며, 상태 코드와 헤더를 포함한 다양한 요소를 가지고 있음

 

프로토콜

= 컴퓨터 네트워크에서 데이터 통신을 하기 위한 규칙과 절차의 집합

 

http의 개념

= 클라이언트-서버 모델을 기반으로 동작함

클라이언트가 요청을 보내면 서버가 응답을 반환하는 방식임

이러한 요청과 응답은 텍스트 기반의 메세지로 이루어져 있음

 

http의 특정

1. 무상태성 -> 상태를 유지 않음, 각 요청은 독립적, 이전 요청 정보 기억하지 않음

2. 확장성 -> 다양한 확장 헤더를 추가하여 기능 확장 가능

3. 유연성 -> 다양한 데이터 형식을 전송할 수 있음. 텍스트, 이미지, 비디오 등 여러 형식 지원

 

http 메세지 구조

= 요청, 응답으로 나뉨

(요청)

1. 요청 라인 -> 메서드(GET, POST 등), URL, HTTP 버전

2. 헤더 -> 요청의 추가 정보(메타 데이터)를 담고 있음

3. 본문 -> 선택적, 주로 POST 메서드에서 사용

ex.

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html

 

(응답)

1. 상태 라인 -> http 버전, 상태 코드, 상태 메세지

2. 헤더 -> 응답의 추가 정보

3. 본문 -> 선택적, 주로 응답 데이터

ex.

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1354

<!DOCTYPE html>
<html>
<head>
    <title>Example</title>
</head>
<body>
    <h1>Hello, World!</h1>
</body>
</html>

 

http 상태 코드

* 1xx -> 정보 

* 2xx -> 성공

* 3xx -> 리다이렉션

* 4xx -> 클라이언트 오류

* 5xx -> 서버 오류

 

http 메서드 및 rest API

 = http 메서드는 클라이언트가 서버에게 요청의 성격을 알리는 데 사용됨

rest API 는 이러한 http 메서드를 사용해 CRUD 작업을 수행함

 

GET -> 데이터 요청

POST -> 데이터 제출

PUT/PATCH -> 데이터 업데이트

DELETE -> 데이터 삭제

 

CRUD

1. Create = 새로운 데이터 생성

2. Read = 데이터 조회

3. Update = 기존 데이터 수정

4. Delete = 데이터 삭제

 

엔드포인트

= 서버와 클라이언트가 서로 데이터를 주고 받기 위해 사용하는 URL 주소

이 URL은 특정한 작업을 수행할 수 있는 경로를 나타냄

 

REST API에서는 특정 리소스에 접근할 수 있는 경로를 말함

각 엔드포인트는 특정 작업을 수행하는 데 사용됨

엔드포인트와 URL
POST /posts: 새로운 게시물을 생성하는 엔드포인트
URL: https://api.example.com/posts
사용 예: 클라이언트가 새로운 게시물을 작성하고 서버로 보내기 위해 이 URL로 요청을 보냅니다.

GET /posts: 모든 게시물을 조회하는 엔드포인트
URL: https://api.example.com/posts
사용 예: 클라이언트가 모든 게시물을 확인하기 위해 이 URL로 요청을 보냅니다.

GET /posts/
: 특정 게시물을 조회하는 엔드포인트
URL: https://api.example.com/posts/1 (1번 게시물을 조회)
사용 예: 클라이언트가 특정 ID를 가진 게시물을 확인하기 위해 이 URL로 요청을 보냅니다.

PUT /posts/
: 특정 게시물을 전체 수정하는 엔드포인트
URL: https://api.example.com/posts/1 (1번 게시물을 전체 수정)
사용 예: 클라이언트가 특정 ID를 가진 게시물의 내용을 전체적으로 수정하기 위해 이 URL로 요청을 보냅니다.

PATCH /posts/
: 특정 게시물을 부분 수정하는 엔드포인트
URL: https://api.example.com/posts/1 (1번 게시물을 부분 수정)
사용 예: 클라이언트가 특정 ID를 가진 게시물의 내용을 일부 수정하기 위해 이 URL로 요청을 보냅니다.

DELETE /posts/
: 특정 게시물을 삭제하는 엔드포인트
URL: https://api.example.com/posts/1 (1번 게시물을 삭제)
사용 예: 클라이언트가 특정 ID를 가진 게시물을 삭제하기 위해 이 URL로 요청을 보냅니다.

 

REST API

= HTTP를 기반으로 클라이언트와 서버 간에 데이터를 주고 받기 위한 아키텍처 스타일

RESTful API는 이러한 REST 원칙을 준수해 설계된 API임

* 자원(데이터나 기능)을 URL로 식별하고, HTTP 메서드(GET, POST 등)를 사용해 자원을 다룸

 

정리

1. REST API = 데이터를 주고 받기 위한 규칙과 프로토콜의 집합으로 웹 서비스 전체를 나타냄

예: https://api.example.com

 

2. 엔드포인트 = REST API의 일부로, 특정 자원에 접근하거나 특정 기능을 수행하기 위한 구체적인 URL

예:

모든 게시물을 조회하는 엔드포인트: https://api.example.com/posts

특정 게시물을 조회하는 엔드포인트: https://api.example.com/posts/1

새로운 게시물을 생성하는 엔드포인트: https://api.example.com/posts