비동기 처리방법 - (1)

SCYu·2022년 11월 11일
0
post-thumbnail

시작하며...

혹시 여러분은 비동기 처리,에 대해 들어본 적이 있는가? 앞선 비동기, 동기 처리 글에서도 살펴봤지만 비동기 처리는 JavaScript의 특성으로써(물론 다른 언어가 안된다는 것은 아니다) 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 실행하는 것이다. 이런 비동기 처리의 대표적인 예시로 JavaScript와 XML을 이용한 비동기적 정보 교환 기법인 AJAX가 있다. 비동기 처리는 앞선 코드를 기다리지 않기 때문에 분명 성능 면에서 향상되지만, 의도치 않은 문제점들이 발생하기도 한다. 오늘은 이런 문제점과 이를 해결하는 방법들에 대해 알아보고자 한다.

<비동기 처리의 대표적 예시인 AJAX! 하지만 문제도 있다..>

비동기 처리의 문제

비동기 처리의 문제는 바로 의도치 않은 상황에서 밑의 코드가 위의 코드가 실행되는 것을 기다리지 않고 실행되는 것이다. 다음 예시 코드를 보자:

여기 코드에서 우리가 의도하고자 하는건 getData() 함수로 URL에 대한 정보를 받아온 뒤에 이걸 console에 출력하는 것이다. 하지만 이 상황에서 getData() 함수가 response를 받아오는 시간이 오래 걸린다면, 비동기 처리에 의해 console에 출력이 먼저 되어 결국은 undefined가 출력될 것이다. 우리는 이런 상황을 원치 않기 때문에 해결방법을 생각하게 되고, 그래서 나온 것이 바로 콜백 함수(Callback Function)이다.

해결책 첫번째: 콜백 함수

다음은 위의 문제를 해결하기 위한 첫번째 방법인 콜백 함수를 이용해 문제를 해결한 코드이다:

위의 코드를 보면, callbackFunc() 함수를 써서 getData() 함수가 response를 받아올 때까지 기다리고, 이후에 이 responseconsole에 출력했다! 이렇게 하면 response를 받아오는 데에 오랜 시간이 걸리더라도, callbackFunc() 함수 때문에 console에 비동기적으로 출력되지 않는다.

콜백 함수의 문제점

그렇다면, 모든 문제는 해결됐고 이제 더이상 고민할 필요가 없는 것일까? 아니다. 이 콜백 함수는 콜백 함수대로 또 다른 문제를 품고 있었다. 바로 콜백 헬(Callback Hell) 이란 문제인데, 코드로 설명하면 다음과 같다:

코드만 봐도 어저럽지 않은가? 전 callback 함수의 결과를 토대로 계속 callback 함수를 불러와 무언가를 해야 하는 상황을 나타낸건데, 저런 코드가 있으면 가독성이 매우 떨어질 뿐더러 로직변경이 어려워진다. 그렇다면 이를 하나하나 정의해서 띄워놓음 되지 않을까? 란 생각을 할 수 있지만 그래도 어지러운건 매한가지이다...

그래서 사람들은 다른 해결책을 찾기 시작했고, 이때 나온 것이 바로 프로미스(Promise)이다

해결책 두번째: 프로미스

프로미스라니, 이름만 들어서는 어떤 건지 감이 잘 오지 않는다. 설명하자면, 프로미스(Promise)는 JavaScript에서 비동기 처리를 위한 객체이다. 프로미스 객체는 3가지 상태를 가지는데, 이를 코드로 표현해보면 다음과 같다:

위 식에서 new Promise()로 만들어진 프로미스 객체가 보이는가? 프로미스 객체는 생성되면 첫번째로 대기(Pending) 이라는 상태를 가진다. 이후로 이 객체는 어떤 함수가 내부에서 호출되느냐에 따라 바뀌는 상태가 나뉘는데,

  • resolve() 함수가 호출될 때
    프로미스 객체가 정상적으로 할 일을 한 상황으로 실행(Fulfilled) 상태로 바뀌게 된다. 이 상태에서는 then() 함수를 이용해 처리 결과값을 받을 수 있다.

  • reject() 함수가 호출될 때
    프로미스 객체가 원하는 일을 할수 없어 에러가 발생한 상황으로 실패(Rejected) 상태로 바뀌게 된다. 이 상태에서는 catch() 함수를 이용해 발생한 에러를 가져와 뒤의 작업들을 할 수 있다.
    이렇게 세가지 상태를 가지고 있는 프로미스를 가지고 우리는 콜백함수를 대체하여 비동기 처리의 문제를 해결할 수 있었다.

프로미스의 특성

그렇다면 앞서 말했던, 콜백 함수의 문제를 어떻게 해결할 수 있을까? 그건 바로 프로미스의 특성인, 프로미스 체이닝(Promise Chaining) 을 사용하는 것이다. 프로미스 체이닝은 여러 개의 프로미스를 연결하여 사용하는 것으로, 앞선 then() 함수를 사용하면 새로운 프로미스 객체가 생성된다는 것을 활용한다.

이렇게 then() 함수를 여러 개 사용하여 콜백 헬에 빠지지 않으면서 비동기 처리를 할 수 있다.

마치며...

사실 프로미스 체이닝도(위 사진을 보면 알겠지만) then() 함수가 많이 늘어나게 되면 콜백 헬마냥 복잡해지게 된다. 이 또한 결국은 완벽한 해결책이 아닌 것이다. 사람들은 이를 해결하기 위해 또 고민했고, 결과적으로 제너레이터(generator)async/await가 나오게 된다. 하지만 여기까지 다루면 글이 너무 길어질 것 같아 한번 끊고, 이 주제들은 다음 글에서 다루도록 하자.

<오늘으 마지막 사진은 내가 제일 좋아하는 시계인 '오데마피게'의 로얄 오크 모델이다. 저 베젤이 너무 아름답지 않은가??>

profile
Front+Back=Full

0개의 댓글