☁️ goormTIL | Web #41

매루·2025년 11월 6일

goormTIL

목록 보기
39/67
post-thumbnail

📅 2025-11-06

➡️ 웹 비동기 프로그래밍에 대해 새롭게 알게 된 것 또는 헷갈리는 부분 정리


🔎 학습 리마인드

📌 비동기 프로그래밍 복습

💡 Promise

  • 생성 방법
    // 비동기 작업 수행
    const myPromise = new Promise((resolve, reject) => {
      if (/* 작업이 성공하면*/) {
        resolve("성공 메시지");
      } else {
        reject("실패 메시지");
      }
    });
  • 예시 코드
    const myPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        // 성공 여부를 나타내는 플래그
        const success = true;
    
        if (success) {
          // resolve()가 호출되면 Promise는 '성공(fulfilled)' 상태가 됨
          // 인자로 전달한 값은 .then()의 콜백 함수로 넘어감
          resolve("작업이 성공적으로 완료되었습니다!");
        } else {
          // reject()가 호출되면 Promise는 '실패(rejected)' 상태가 됨
          // 인자로 전달한 값은 .catch()의 콜백 함수로 넘어감
          reject("작업이 실패했습니다.");
        }
      }, 2000); // 2초 후에 결과 반환
    });
    
    myPromise
      .then((result) => {
        console.log(result); // 성공 시 메시지 출력
      })
      .catch((error) => {
        console.log(error); // 실패 시 에러 메시지 출력
      });
  • 리액트에서 활용
    import React, { useState, useEffect } from "react";
    
    function App() {
      const [message, setMessage] = useState("타이머 시작");
    
      // useEffect 훅을 사용하여 컴포넌트가 마운트되었을 때 실행될 효과를 정의
      // 빈 배열 []을 두 번째 인자로 넘겨주어, 이 효과가 컴포넌트가 처음 렌더링 된 후 한 번만 실행
      useEffect(() => {
        // delay 함수 정의
        // (1) delay 함수는 Promise 객체를 새로(new) 만들어 반환
        // 여기서 Promise는 객체를 생성하기 위한 생성자
        // (2) 만들어진 promise 객체는 주어진 밀리초(ms)만큼 동작을 지연시킴
    
        // (1) delay함수는 주어진 밀리초(ms)만큼 지연시키는 Promise를 반환
        // (2) setTimeout을 사용하여 지정된 시간(ms) 후에 resolve를 호출
        // (3) 따라서, 지정된 시간(ms) 후에 pending -> fulfilled로 상태가 바뀜
        const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
        // (1) delay 함수를 호출하여 2000밀리초(2초) 동안 지연시킴
        // (2) delay 함수가 반환하는 Promise가 완료되면 then 메서드가 호출되고, 이 메서드 안의 콜백 함수가 실행됨
        // (3) 이 콜백 함수는 setMessage를 호출하여 message 상태를 "2초 후 메시지 변경"으로 업데이트
        delay(2000).then(() => setMessage("2초 후 메시지 변경"));
      }, []);
    
      // 초기 상태는 "타이머 시작"이며, 2초 후에는 "2초 후 메시지 변경"으로 업데이트
      return (
        <div>
          <h1>{message}</h1>
        </div>
      );
    }
    
    export default App;
  • 데이터 가져올 때

    import React, { useState, useEffect } from "react";
    
    function App() {
      const [post, setPost] = useState(null);
    
      useEffect(() => {
      // 1. 컴포넌트가 마운트될 때 fetch를 사용해서 데이터를 비동기적으로 가져옴
        fetch("https://jsonplaceholder.typicode.com/posts/1")
    	// 2. Promise의 then 메서드를 사용해서 데이터 설정
          .then((response) => response.json())
          .then((json) => setPost(json))
      // 3. 에러가 발생하면 catch 메서드를 통해 에러 처리 
    	    .catch((err) => console.error("데이터 요청 실패:", err));
      }, []);
    
      return <div>{post ? <div>{post.title}</div> : <div>Loading...</div>}</div>;
    }
    
    export default App;
    • fetch()함수는 Promise를 반환함
    • .then()은 성공 시 실행, .catch()는 실패 시 실행
    • .finally()로 성공/실패 상관없이 마지막 정리 작업도 가능
  • Promise.all()

    import React, { useEffect, useState } from "react";
    
    export default function App() {
      const [data, setData] = useState({ posts: [], users: [] });
    
      useEffect(() => {
        Promise.all([
          fetch("https://jsonplaceholder.typicode.com/posts").then((r) => r.json()),
          fetch("https://jsonplaceholder.typicode.com/users").then((r) => r.json()),
        ])
          .then(([posts, users]) => setData({ posts, users }))
          .catch((e) => console.error("데이터 로드 실패:", e));
      }, []);
    
      return (
        <div>
          <h1>Posts & Users</h1>
          <section>
            <h2>Posts</h2>
            {data.posts.length ? (
              data.posts.map((p) => <div key={p.id}>{p.title}</div>)
            ) : (
              <p>Loading...</p>
            )}
          </section>
          <section>
            <h2>Users</h2>
            {data.users.length ? (
              data.users.map((u) => <div key={u.id}>{u.name}</div>)
            ) : (
              <p>Loading...</p>
            )}
          </section>
        </div>
      );
    }
    • Promise.all()여러 개의 비동기 요청을 한 번에 실행하고, 모든 요청이 끝나면 결과를 한 번에 받아볼 수 있음

💡 async/await

  • async 함수는 항상 Promise를 반환
  • await 키워드는 Promise가 완료될 때까지 기다린 뒤 결과를 반환
  • 예시
    import React, { useState, useEffect } from "react";
    
    export default function App() {
      const [post, setPost] = useState(null);
    
      useEffect(() => {
        const load = async () => {
          try {
            const res = await fetch("https://jsonplaceholder.typicode.com/posts/1");
            const data = await res.json();
            setPost(data);
          } catch (err) {
            console.error("에러 발생:", err);
          }
        };
    
        load();
      }, []);
    
      return post ? <h3>{post.title}</h3> : <p>Loading...</p>;
    }
    • async/awaittry-catch로 에러를 한 곳에서 처리할 수 있고, .then().catch()보다 코드 흐름이 자연스럽게 이어짐

📌 HTTP 복습

💡 HTTP의 주요 특징

  • 무상태성
    • HTTP는 상태를 유지하지 않음. 각 요청은 독립적이며, 이전 요청의 정보를 기억하지 않음
  • 확장성
    • HTTP는 다양한 확장 헤더를 추가하여 기능을 확장할 수 있음
  • 유연성
    • HTTP는 다양한 데이터 형식을 전송할 수 있음 (텍스트, 이미지, 비디오 등)

💡 HTTP 메서드와 REST API

  • HTTP 메서드는 클라이언트가 서버에 요청의 의도를 전달하는 수단
  • REST API는 이 메서드를 이용해 CRUD(Create, Read, Update, Delete) 동작을 표현
메서드역할설명
GET조회(Read)서버로부터 데이터를 요청. 요청 데이터가 URL에 포함됨
POST생성(Create)서버에 데이터를 제출하여 새로운 리소스를 생성. 데이터는 요청 본문에 포함됨
PUT / PATCH수정(Update)서버의 기존 리소스를 수정. 요청 본문에 수정할 데이터 포함
DELETE삭제(Delete)서버의 특정 리소스를 삭제
  • REST API

    특정 자원(Resource)을 URL로 표현하고, HTTP 메서드를 조합하여 자원의 행위를 나타내는 방식

    즉, 메서드 + URL 조합으로 API의 의미를 표현한다고 보면 됨


0개의 댓글