백엔드 부트캠프[사전캠프]/TIL

[내일배움캠프-사전캠프 15일차] 동기, 비동기 작업

sintory-04 2025. 2. 12. 16:18

    - Web 프로젝트를 하나 만들고 보니 동기, 비동기를 알아야 겠다는 생각이 들었다.

    - 백엔드 작업자들도 동기, 비동기 작업을 필수로 알아야한다.

    - 백엔드는 클라이언트 요청을 받아 응답을 줘야한다. 동기 방식으로 처리하면 요청이 끝날 때 까지 다음 요청을 받지 못해 성능이 낮아질 수 있다. 그러나 비동기 방식을 이용하여 여러 요청을 동시에 처리하면 처리 속도가 훨씬 빨라질 것이다.

    - DB 작업을 예시로 생각하면 쉽다. 데이터를 저장하고 조회할 때, 다른 요청을 처리할 수 있어야한다. 동기 작업이라면 병목현상이 생길 수 있지만, 비동기 작업이라면 여러 개의 DB 요청을 동시에 처리할 수 있을 것이다.

    ✅ 사전 지식

    1️⃣ 메모리힙

    - 동적으로 할당된 메모리(객체, 함수, 변수 등)가 저장되는 영역이다. 힙은 구조화되지 않은 넓은 메모리 공간으로, 객체나 복잡한 데이터 구조를 저장하는 데 사용된다.

    • 동적 메모리 할당: 객체, 배열, 함수 등은 런타임에 힙에 할당된다.
    • 가비지 컬렉션: 더 이상 사용되지 않는 메모리는 가비지 컬렉터가 자동으로 해제한다.
    • 메모리 누수: 잘못된 참조로 인해 사용되지 않는 메모리가 해제되지 않으면 메모리 누수가 발생할 수 있다.

    2️⃣ 콜스택

    - 자바스크립트에서 현재 실행 중인 함수들을 추적하는 공간이다. 함수가 호출되면 그 함수는 콜 스택에 쌓이게 되고, 실행이 끝나면 스택에서 제거된다(LIFO-나중에 들어온게 먼저 나감)

    • 함수 실행 순서 관리: 함수가 호출되면 콜스택에 쌓이고, 실행이 끝나면 제거됨.
    • 싱글 스레드: JS 는 단일 콜스택을 사용하므로 한 번에 하나의 작업만 처리할 수 있다.
    • 스택 오버플로우: 재귀 함수나 너무 많은 함수 호출로 콜스택이 함수를 초과하면 "Maximum call stack size exceeded" 오류가 발생한다.
    function foo() {
        console.log("foo");
        bar();
    }
    
    function bar() {
        console.log("bar");
    }
    
    foo();

    - 이런식의 함수가 있다면 출력문은 아래와 같다.

    foo
    bar

    - 해당 출력문을 토대로 함수 호출 순서를 그림으로 표현하자면 아래와 같다.

    3️⃣콜스택과 메모리 힙의 차이

    - 메모리 힙: 객체, 배열, 함수 등 참조 타입 데이터는 힙에 저장된다.

    - 콜스택: 메모리 힙의 참조(포인터)가 저장된다. 함수 호출과 실행 순서를 관리. 기본 데이터 타입(숫자, 문자열 등)은 콜스택에 저장된다.

    ✅ 동기작업

    - 한 작업이 끝나야 다음 작업이 실행되는 방식을 뜻한다. (순차적 작업: 작업이 하나씩 차례대로 실행된다. )

    - 이전 작업이 완료될 때까지 다음 작업이 대기하고 있는다. ( 블로킹: 이전 작업이 끝나기 전까지는 다음 작업이 시작되지 않음 )

    3

    - 동기작업의 장점은 작업이 하나씩 차례대로 실행된다는 것이다. (순서가 중요한 작업이라면 적절함 / 결제방식)

    ww

    - 단점으로는 하나의 작업이 오래 걸리면 다음 작업이 지연된다는 것이다.

    따라서, 순서가 중요한 작업이나 작업이 짧고 빠르게 끝나는 경우에 사용하는 것이다.

    동기 작업

    한 작업이 끝나야 다음 작업이 시작되는 방식

    ✅ 비동기 작업

    - 작업이 끝날 때 까지 기다리지 않고, 다음 작업을 먼저 실행하는 방식이다. 작업이 동시에 가능하다 !

    - 비동기 작업의 특징으로는 아래와 같다.

    • 논 블로킹 (Non-blocking) : 한 작업이 끝날때까지 기다리지 않고, 다음 작업 실행
    • 동시에 여러 작업 수행 가능
    • 빠른 응답 처리

    비동기 작업

    기다리지 않고 다음 작업 실행, 결과가 나중에 도착하는 방식

    1️⃣ Callback 함수

    - 다른 함수에 인자로 전달되어 실행되는 함수이다.

    function someFunction(callback) {
        // 작업을 진행
        callback();  // 작업이 끝난 후 콜백 실행
    }
    
    function myCallback() {
        console.log("작업 완료!");
    }
    
    someFunction(myCallback);  // myCallback이 콜백으로 전달됨

    - someFunctioncallback이 콜백함수이다. someFunction 내부에서 특정 작업이 끝나면 callback()을 호출하여 콜백을 실행한다.

    - 함수의 실행이 끝난 후 호출되는 함수이다.

    - 어떤 함수가 콜백 함수로 사용될지는 그 함수가 다른 함수에 인자로 전달되어 실행되는지에 달려 있다.

    - 콜백이 중첩되면 코드가 지저분해지고 가동성이 떨어지는 문제가 생길 수 있다.

    - 콜백 함수의 특징

    • 다른 함수의 인자로 전달된다.
    • 특정 작업이 끝난 후 실행된다.
    • 비동기 작업에서 결과를 처리하는 데 주로 사용된다.
    • 콜백 함수 내부에서 다른 함수를 호출할 수 있다.
    • 체이닝이 불가하다.(then() catch())

    - 콜백함수 장점

    • 비동기 작업처리: 서버가 멈추지 않도록 처리 가능하다.
    • 유연성: 함수의 동작을 외부에서 정의할 수 있어, 다양한 작업을 처리 가능하다.

    - 콜백 지옥: 콜백함수가 중첩되어 코드가 매우 복잡하고 읽기 어려운 상태를 말한다.

    fs.readFile('file1.txt', 'utf8', (err1, data1) => {
        if (err1) throw err1;
        fs.readFile('file2.txt', 'utf8', (err2, data2) => {
            if (err2) throw err2;
            fs.readFile('file3.txt', 'utf8', (err3, data3) => {
                if (err3) throw err3;
                console.log('모든 파일 읽기 완료!');
            });
        });
    });

    2️⃣ Promise

    - Promise는 비동기 작업의 결과를 나중에 받아올 것을 약속하는 객체로, 비동기 작업이 성공(resolve) 또는 실패(reject)했을 때 실행되는 객체이다.

    promise
      .then((result) => {
        console.log(result);  // 작업 성공 시 실행
      })
      .catch((error) => {
        console.log(error);  // 작업 실패 시 실행
      });

    - .then(), catch() 으로 체이닝이 가능하다. 연속된 비동기 작업을 처리하기 쉽다.

    +) fetchData()Promise를 반환하기 때문에 .then()을 사용해서 결과를 받아옴.

    3️⃣ async/await

    - Promise의 문법적 개선판이다. asyncawait을 사용하면 비동기 작업을 동기처럼 처리할 수 있다.

    - 동기 코드처럼 읽기 쉽고, 내부적으로 비동기적으로 실행됨. > 더 직관적인 방식으로 비동기 작업을 처리할 수 있음.

    - async 함수는 항상 Promise를 반환하며

    - awaitpromise가 처리될 때까지 기다리고, promise가 해결되면 값을 반환한다.

    async function fetchData() {
      const result = await new Promise((resolve) => {
        setTimeout(() => {
          resolve("데이터를 가져왔습니다!");
        }, 1000);
      });
      console.log(result);  // "데이터를 가져왔습니다!" 출력
    }
    
    fetchData();

    ✅ 오늘의 회고

    - 오늘은 동기작업과 비동기 작업에 대해 다시 공부해보았다. 이거 저거 하다보니 오늘은 해당 부분만 공부했다.. 

    - 블로그 수정 할 부분도 있어서 수정하다 보니,, 실수로 작성하던 중인 블로그 글을 삭제해버렸다 😭😭 그래서 백준 자바 풀기는 물 건너갔다...

    - 한 가지 이슈가 있는데, 우리 사전캠프 조에 새로운 팀원이 한 분 더 오셨다! 이제 정말로 각 조 당 평균 5명은 있는 거 같다.

    - 본캠 때 이정도 규모로 수업 받을 생각이 하니 조금 걱정이 된다. 집중을 잘 할 수 있을까.. 😫