ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] 항해 99 5주차 주특기 심화 회고록_21일차
    항해[TIL] 2021. 12. 4. 16:42

    Today I Learnd 

     

    (2021. 12. 2. 목)

     

     

     

     

    목차

    1. Javascript 동기와 비동기
    2. 주특기 심화 4일차 소감 및 부족한 점

     

     

     

     

    1. Javascript 동기와 비동기

    1. 동기와 비동기

    동기 (Syncronous)

    • 요청 후 응답을 받아야 다음 동작을 실행하는 방식

    비동기 (Asynchronous)

    • 요청을 보낸 후 응답과 관계없이 다음 동작을 실행하는 방식

    자바스크립트는 단일 스레드 프로그래밍 언어로 단일 호출 스택이 있어 한번에 하나의 일을 처리할 수 있다. 이러한 이유로 Javascript는 동기 방식으로 진행이 된다. 하나의 호출 스택만 있기 떄문에 하나의 함수를 처리하는데 시간이 오래 걸린다면 다음 실행할 함수에 지장을 줄 수 있는 문제가 생긴다.

     

    위와 같은 문제로 비동기의 필요성이다. 이러한 문제를 해결할 수 있는 방법은 아래와 같은 방법들이 있다.

    • 비동기적 callBack 함수 사용
    • ES6 Promise
    • ES8 async await

    2. CallBack

    CallBack함수는 다른 함수의 인자로 이용이 되는 함수이며 어떤 이벤트에 의해서 호출이 되는 함수이다. CallBack함수는 아래 코드와 같이 동기적으로 사용이 될 수 있다.

    /example 이라는 이벤트 함수가 인자로 받는 코드
    
    function expmple(callBackFunction) {
    	callBackfunction()
    }
    example() => console.log('synchronous callBack')

    단순하게 인자로서 함수를 받아 그 함수를 실행한다. 일반적인 Javascript 코드이기에 당연하게 함수 호출 스택에 따라서 동기적으로 실행이 된다. 구현하고자 하는 비동기적 과정은 위 코드처럼 일어나지 않지만, 비동기적 과정을 일으키리면 비동기적 callback함수를 사용해야 한다.

    /비동기적 콜백 함수 Asynchronous callBack 예시
    
    function expmple(callback, sec) {
    	setTimeOut(callback, sec*1000)
    }
    example() => console.log(('async callBack'), 2)
    console.log ("hello")

    동기적인 방식을 따르면 example() 가 모두 실행을 완료한 후 "hello"를 출력해야한다. 하지만 setTimeOut을 사용해서 2초 후에 "async callback"이 비동기적으로 출력이 된다. 따라서 "hello"가 먼저 출력이 되고나서 2초 후에 "async callback"이 출력된다.

     

    예를 들면 사용자가 어떤 버튼을 클릭을 했을 때 실행할 함수도 비동기 콜백 함수다. 그 이전까지는 실행하지 않다가 클릭이라는 이벤트가 발생했을 때 콜백함수를 실행하는 것이다.

     

    3. 비동기 작동 원리

    Javascript 엔진만으로 비동기적으로 구현할 수 없으므로 Javascript 실행 환경(RunTime)은 브라우저에서 제공하는 wep API를 사용해서 비동기를 구현하게 된다. DOM 이벤트, setTimeOut과 같은 비동기함수는 wep API를 호출해서 콜백 함수를 콜백 큐에 넣는다. 콜백 함수들이 담긴 큐는 특정 시점에서 콜백을 실행시키는 방식이다. 

     

    또한 비동기 구현을 위한 첫번째 방법인만큼 큰 문제가 있는데 콜백 함수가 콜백 함수를 부르고, 그 콜백 함수가 또 다른 콜백 함수를 부르는 콜백 지옥이 발생한다. 많은 중첩 함수가 생겨 가독성과 유지보수면에서 끔찍한 코드가 발생하는데 이를 해결하기 위해서 Promise가  나오게 됐다.

     

    4. Promise

    콜백 함수를 사용하지 않고 Promise object를 통해 콜백 지옥에 빠지지 않고 어떻게 깔끔하게 비동기 함수를 처리할 수 있는지 예시 코드를 만들었다. 

    const myPromise = new Promise((resolve, reject)=>{
      console.log("doning some heavy work: network, read files")
      setTimeout(()=>{
        // resolve('hi');
        reject(new Error('this is error msg'));
      }, 2000);
    })
    
    myPromise.then(value=>{
      console.log(value) // resolve 가 있다면 'hi' 출력 
    })
    .catch(error=>{
      console.log(error) // reject에 있는 'this is error msg' 출력
    })
    .finally(()=>{
      console.log('finally!!')
    })

    위 코드의 경우 2초 뒤에 'this is error msg'와 'finally!'가 출력이 된다. 민약 resolve('hi')가 주석처리 되지 않았다면 .then()에서 'hi'가 출력됐을 것이다.

     

    콜백 함수의 중첩과 같이 여러 Promise 객체를 만들어 중첩시킬 수 있다. 

    const initialPokemon = () =>
      new Promise((resolve, reject)=>{
        setTimeout(()=>resolve('파이리'), 1000)
      });
    
    const nextPokemon = prevPokemon =>
      new Promise((resolve, reject)=>{
        setTimeout(()=>resolve(`${prevPokemon} => 리자드`), 1000)
      });
    
    const finalPokemon = prevPokemon =>
      new Promise((resolve, reject)=>{
        setTimeout(()=>resolve(`${prevPokemon} => 리자몽`), 1000)
      });
    
    initialPokemon() // 1초 소요
      .then(prev=>{
        console.log(prev) // 파이리
        return nextPokemon(prev) // 1초 소요
      })
      .then(prev=>{
        console.log(prev) // 파이리 => 리자드
        return finalPokemon(prev) // 1초 소요
      })
      .then(console.log) // 파이리 => 리자드 => 리자몽

    확실히 콜백 지옥보다 훨씬 로직이 깔끔하고 가독성도 뛰어나다는 것을 알 수 있다. 위 코드들을 사용하는 방법의 경우 Promise chaining으로 then, catch 메소드를 사용하여 비동기를 관리하고 있다.

     

    5. async await

    asynce await 는 비동기처리의 최신문법이다. 기존의 promise와 다른 것은 아니고, syntatic sugar일 뿐이다. promise를 사용할 경우에 callback처럼 chaining이 일어나는 것은 마찬가지이다. 따라서 콜백 지옥의 문제가 어느정도 나타날 수 있다는 것이다.

    하지만 async await을 사용하면 promise를 '깔끔한 스타일'로 작성할 수 있다. 그러나 무조건 async await이 절대적으로 깔끔한 방법은 아니고 상황에 따라 적절한 것을 선택하면 된다. async await를 사용한 예시 코드를 살펴보자.

    const getTodo = async (id) => {
      const todoResponse = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
      const todo = await todoResponse.json()
      return todo;
    }
    
    getTodo(172).then(console.log)

    fetch 함수에서 사용한 API는 무료 가짜 데이터 REST API를 제공하는 API 주소이다. 간단한게 데이터를 가져오는 과정을 async await 문법을 사용한 코드이다. async 키워드는 함수 앞에 붙이는 키워드이며 await 키워드는 async 키워드가 붙어 있는 함수 내부에서만 사용할 수 있다. await 라는 코드로 의도한 순서대로 코드의 흐름을 제어하고 있다. 일반적인 동기 코드 처리와 동일한 흐름으로 코드를 작성할 수 있기에 코드 읽기가 수월해진다.

    한 가지 주의할 것은 async 함수를 호출할 때 명시적으로 promise 객체를 생성하여 리턴하지 않아도 promise 객체가 리턴된다. 따라서 호출하는 코드를 보면 then() 매서드를 사용하여 결과값을 출력하고 있다.

    async await의 또다른 장점은 동기와 비동기 구분없이 try catch 로 일관된 예외 처리를 할 수 있다는 점이다!

    const myFunction = async (postId) => {
      const postResponse = await fetch(
        `https://jsonplaceholder.typicode.com/posts/${postId}`
      )
      const post = await postResponse.json()
      const userId = post.userId
    
      try {
        const userResponse = await fetch(
          // 1번 주소: `https://jsonplaceholder.typico`
          // 2번 주소: `https://jsonplaceholder.typicode.com/users/${userId}`
        )
        const user = await userResponse.json()
        return user.name || "no data"
      } catch (err) {
        console.log(err)
        return "Unknown"
      }
    }
    
    myFunction(15).then(console.log)

    위 코드에서 2번 주소가 정상적으로 작동하는 코드이다. postId 를 주면 해당 포스트의 userId 로부터 다시 user 의 이름을 얻어오는 코드이다. 2번 주소일 때, postId 혹은 userId 가 DB에 없을 경우 빈 객체가 반환되는데 그 때는 "no data" 를 반환하도록하였다. 데이터가 존재할 경우 user.name 을 정상적으로 반환한다.

    그리고 1번 주소의 경우 에러 상황으로 err를 출력하고 (위 코드에서는 Error: 'Failed to fetch' 라는 에러 발생) "Unknown"을 반환하게 된다.

     

    이 글의 출처: https://velog.io/@open_h/javascriptasync

     

     

     

     

    2. 주특기 심화 4일차 소감 및 부족한 점

    소감

    5주차 주특기 숙련 4일차가 지났다. 기초를 배우는데 이렇게 양이 많은지 몰랐다. 잠을 엄청 적게 자면서 열심히 듣고 있다만 벌써 목요일이라서 내일에는 무조건 과제를 끝내야 겠다고 생각을해서 쭉 듣지 말고 지금 당장 필요한 것을 듣기로 마음을 먹었다.

     

    이렇게 기초도 공부를 할게 많은데 점점 난이도를 높여가면서 공부를 하면 얼마나 배울게 많을까 라는 생각이든다. 이번 주말에는 다음주 미니 프로젝트 부터 시작해서 마지막으로 실전 프로젝트가 있기 때문에 node.js도 공부해야할 것 같다.

     

    부족한 점

    계속해서 기초를 닦는 중이라 부족한 점에 대해서 명확히 얘기하기는 힘들지만 기초를 배우는 과정에서 집중을 할 수 있도록 자세를 고쳐 앉고 집중 하려고 노력을 해봐야겠다.

Designed by Tistory.