1. 콜백 함수란?
1-1)콜백 함수란?
- 콜백 함수는 다른 코드의 인자로 넘겨주는 함수이다. 콜백 함수를 넘겨받은 코드는 이 콜백 함수를 필요에 따라 적절한 시점에 시행할 것이다.
- 콜백 함수는 다른 코드(함수 OR 메서드)에게 인자로 넘겨줌으로서 그 제어권도 함께 위임한 함수이다.
- 콜백 함수를 위임받은 코드는 자체적인 내부 로직에 의해 이 콜백 함수를 적절한 시점에 시행할 것이다.
※일상 생활에서의 예시
- A와 B는 다음 날 아침 8시에 만나기로 하고 잠을 잔다. 늦어도 6시에는 일어나야 약속에 늦지 않는다
- A는 매우 불안한 마음에 수시로 깨어 시계를 확인한다. 계속 잠을 설치다 결국 5시즈음 포기하고 일어난다
- B는 알람시계를 세팅한다. 알람이 잘못될 염려는 없고 평소 알람에 잘 일어나므로 완전 꿀잠을 자고 일어난다
- 여기서 A는 수시로 시간을 구하는 함수를 호출했고, B는 시계의 알람을 설정하는 함수를 호출했고, B가 정해진 시간이 됐을때 비로소 '알람을 울리는' 결과를 반환했다.
- A의 경우는 시계함수 제어권이 A에 있었고, B의 경우는 시계 함수에 요청을 하며 알람을 울리는 명령의 제어권을 시계에게 넘겼다
- 이처럼 콜백 함수는 제어권과 관련이 깊다.
2. 제어권
2-1) 호출 시점
예제를 통해 살펴보자 !
- setInterval엔 함수와(cbFunc), delay(300) 값이 설정되었고, setInterval 코드로는 cbFunc함수를 300delay(0.3초)마다 실행한다.
- 이때, cbFunc의 실행은 setInterval이라는 '다른 코드'에 인자로서, setInterval이 스스로 판단에 따라 적절한 시점(0.3초) 마다 이 cbFunc함수를 실행했다. 위와같이 콜백함수의 제어권을 넘겨받은 코드는 콜백 함수의 제어권을 갖게된다
2-2) 인자
- newArr 변수를 선언하고 우항의 결과를 할당했다. 우항은 배열[10, 20, 30]에 map 메서드를 호출중이고 첫번째 인자로 익명함수를 전달중이다.
- map 메서드는 첫번째 인자로 callback 함수를 받고, 두번째 인자로 콜백 함수 내부에서의 this를 특정한다(생략가능)
- map 메서드는 대상이 되는 배열의 모든 요소들을 처음부터 끝까지 하나씩 꺼내어 콜백함수를 반복호출하고, 콜백함수들의 실행결과를 모아 새로운 배열을 만든다.
- 콜백 함수의 첫번째 인자에는 현재값, 두번째 인자에는 index, 세번째 인자에는 map메서드의 대상 배열 자체가 담김
- 위 코드를 예로 보면, 첫번째에 대한 콜백 함수는 currentValue가 10, index가 0, return값이 15일 것이다.
- 첫번째 인덱스와 마찬가지로 두 번째 index(20, 25 return), 세 번째 index(30, 35return)가 되어, 새로운 배열 [15, 25, 35]이 만들어져 newArr에 담기게 된다(5번줄 코드의 출력값)
2-3) this
- 앞 챕터에서 '콜백 함수도 함수이기 때문에 this를 특정하지 않으면 전역객체가 this가 된다'라고 했다.
- this를 직접 특정하고 사용하는 예제를 통해 이해해보자!
- this에는 thisArg의 값이 있을 경우 그 값, 아닐 경우 전역객체가 할당된다.
- callback 함수의 첫번째 인자로는 메서드의 this가 배열을 가리킬 것이므로 배열의 현재 값, 두번째 인자로는 index, 세번째 인자로는 배열 자체를 지정 해 호출한다. 그 결과가 mappedValue에 담겨 mappedArr[i]에 담기게 된다.
3. 콜백 함수는 함수다
- 콜백 함수로 어떠한 객체 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출된다.
4. 콜백 함수 내부의 this에 다른 값 바인딩하기
- 객체의 메서드를 콜백 함수로 전달하면 해당 객체를 this로 바라볼 수 없게 된다는 것을 우린 알았다.
- 그럼에도 함수 내부에서 this가 객체를 바라보게 하고 싶다면 어떻게 해야하나?
- 문제점이 많고 복잡한 전통적인 방식(변수에 this를 담고 클로저를 이용) 대신 ES5이후부턴 bind를 이용하면된다
5. 콜백 지옥과 비동기 제어
- 콜백 지옥은 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들정도로 깊어지는 현상으로, JS의 흔한 문제이다.
- 주로 이벤트 처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장하곤 하는데, 가독성이 떨어질 뿐더러 코드를 수정하기도 어렵다.
- 비동기는 동기의 반대말로 실행 중인 코드의 완료 여부와 무관하게 즉시 다음코드로 넘어간다.
콜백 지옥 코드와 해결책을 예시로 알아보자 !!
- 커피 리스트를 0.5초마다 출력하는 콜백함수인데, 가독성도 안좋을 뿐더러 실행 순서가 아래에서 위를 향하고 있다.
- 위 처럼 기명함수로 콜백 함수를 바꿔주면 가독성이 좋아졌다.
- 하지만 일회성 함수를 전부 변수에 할당하는 것이 마땅치 않기도 하다.
- JS는 비동기적인 일련의 작업을 동기적으로, 혹은 동기적인 것 처럼 보이게끔 처리해주는 장치를 마련하고자 계속해서 대안을 내놓고 있다. ES6에서는 Promise, Generator, ES2017에서는 async/await 이 도입됐다.
- 아래부터 예시코드를 살펴보자. 아직은 위에 것들이 무엇인지 자세히 모르더라도, 개략적인 흐름을 살펴보는 것에 의의를 두고 살펴보자!
※ Promise
- new 연산자와 함께 호출한 Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만 그 내부에 resolve 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 다음(then) 또는 오류(catch) 구문으로 넘어가지 않는다.
- 따라서 비동기 작업이 완료될 때 비로소 resolve 또는 reject를 호출하는 방법으로 비동기 작업의 동기적 표현이 가능하다.
'자바스크립트 > 코어 자바스크립트' 카테고리의 다른 글
코어자바스크립트 6장<프로토타입> (0) | 2022.08.18 |
---|---|
코어자바스크립트 5장<클로저> (0) | 2022.08.17 |
코어자바스크립트 3장<this> (0) | 2022.08.13 |
코어자바스크립트 2장<실행 컨텍스트> (0) | 2022.08.12 |
코어자바스크립트 1장<데이터 타입> (0) | 2022.08.11 |