JS DeepDive

모던 자바스크립트 DeepDive 공부 내용 16차

맨땅헤딩! 2023. 5. 8. 13:01

이번 정리 목차는 44 ~ 47장이다.

44REST API

-       RESTHTTP를 기반으로 클라이언트가 서버의 리소스에 접근하는 방식을 규정한 아키텍처

-       REST APIREST를 기반으로 서비스 API 구현한 것 의미

 

REST API 구성

-       자원, 행위, 표현 3가지 요소로 구성, 자체 표현 구조로 구성되어 REST API만으로 HTTP 요청의 내용 이해 가능

구성 요소 내용 표현 방법
자원 자원 URI(엔드포인트)
행위 자원에 대한 행위 HTTP 요청 메서드
표현 자원에 대한 행위의 구체적 내용 페이로드

REST API 설계 원칙

-       URI는 리소스를 표현하는데 집중해야 한다.

-       리소스에 대한 행위는 HTTP 요청 메서드로 표현한다.

 

45장 프로미스

-       비동기 처리를 위해 콜백함수를 사용하는데 이 콜백 패턴은 콜백 헬로 인해 가독성 나쁘고 에러의 처리가 곤란하며 여러 개의 비동기 처리를 한 번에 처리하는데 한계가 있다.

-       비동기 처리를 위한 또 다른 패턴으로 프로미스 도입, 콜백 패턴이 가진 단점을 보완하며 비동기 처리 시점을 명확하게 표현할 수 있는 장점이 있다.

 

비동기 처리를 위한 콜백 패턴의 단점

[콜백 헬]

-       비동기 함수를 호출하면 함수 내부의 비동기로 동작하는 코드가 완료되지 않아도 즉시 종료된다. 비동기로 동작하는 코드는 비동기 함수가 종료된 이후에 완료된다. 따라서 비동기 처리 결과를 외부에 반환할 수 없고, 상위 스코프의 변수에 할당할 수도 없다.

-       비동기 함수의 처리 결과에 대한 후속처리는 비동기 함수 내부에서 수행해야 하고 이 방법으로 콜백 함수를 전달하는 것이 일반 적인데 콜백 함수 중첩으로 인하여 복잡도가 높아지는 현상이 콜백 헬이다.

 

[에러 처리의 한계]

-       콜백 패턴의 가장 심각한 문제는 에러 처리가 곤란이다.

-       콜백 함수를 호출한 것은 비동기 함수가 아니기 때문에 에러를 캐치할 수 없다.

-       에러는 호출자 방향으로 전파된다.

-       이를 극복하고자 ES6 프로미스가 도입

 

프로미스의 생성

-       new 연산자와 함께 Promise생성자 함수를 호출하면 Promise객체 생성

-       생성자 함수는 비동기 처리를 수행할 콜백함수를 인수로 받는다. (resolve, reject)

-       비동기 처리 성공하면 resolve 함수 호출, 실패하면 reject함수 호출

-       프로미스는 현재 비동기 처리가 어떻게 진행되고 있는지 상태 정보를 갖는다.

프로미스 상태 정보 의미 상태 변경 조건
pending 비동기 처리 아직 수행 X 프로미스 생성된 직후 상태
fulfilled 비동기 처리 수행 성공 resolve 함수 호출
rejected 비동기 처리 수행 실패 reject 함수 호출

-       프로미스의 상태는 resolve 또는 reject 함수 호출하는 것으로 결정

-       fulfilled 또는 rejected 상태를 settled 상태라고 한다.

-       프로미스는 비동기 처리 상태와 더불어 비동기 처리 결과도 상태로 갖는다.

-       비동기 처리 성공 시 처리 결과값, 실패 시 처리 결과값은 에러 객체를 갖는다.

-       , 프로미스는 비동기 처리 상태와 처리 결과를 관리하는 객체이다.

 

프로미스의 후속 처리 메서드

-       비동기 처리 상태 변화에 따라 후속 처리를 해야 하는데 프로미스는 후속처리 메서드를 제공한다(then, catch, finally 메서드)

-       비동기 처리 상태가 변화하면 후속 처리 메서드에 인수로 전달한 콜백함수가 선택적으로 호출된다. 이때 후속 처리 메서드의 콜백 함수에 프로미스의 처리 결과가 인수로 전달

-       모든 후속 처리 메서드는 프로미스를 반환하고 비동기로 동작

 

[Promise.prototype.then]

-       두 개의 콜백 함수를 인수로 전달받는다.

-       첫번째 콜백 함수는 fulfilled 상태일때 호출, 두번째 콜백 함수는 rejected 상태일때 호출

-       프로미스가 아닌 값을 반환하면 그 값을 암묵적으로 resolve, reject하여 프로미스 생성해 반환

 

[Promise.prototype.catch]

-       한 개의 콜백 함수를 인수로 전달받는다.

-       reject 상태일 때만 콜백 함수 호출

 

[Promise.prototype.finally]

-       한 개의 콜백 함수를 인수로 전달받는다.

-       fulfilled 또는 rejected 상관없이 무조건 한 번 호출

-       공통적 수행할 처리 내용 있을 시 유용

 

프로미스의 에러 처리

-       비동기 처리에서 발생한 에러는 후속처리 메서드 thencatch로 처리 가능

-       then 메서드에 두번째 콜백 함수 전달 보다 catch메서드 사용하는 것이 가독성 좋고 명확하므로 catch메서드 권장

 

프로미스 체이닝

-       후속처리 메서드는 언제나 프로미스를 반환하므로 연속적 호출이 가능, 이것이 프로미스 체이닝

-       프로미스 체이닝을 통해 비동기 처리 결과를 전달 받아 후속 처리를 하므로 콜백 헬이 발생하지는 않지만 프로미스도 콜백 패턴을 사용하므로 콜백 함수를 사용하지 않는 것은 아니다.

-       ES8에 도입된 async/await통해 후속 처리 메서드 없이 마치 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현 가능(콜백 패턴 해결)

 

프로미스의 정적 메서드

[Promise.resolve / Promise.reject]

-       인수로 전달 받은 값을 resolve / reject 하는 프로미스 생성

 

[Promise.all]

-       여러 개의 비동기 처리를 모두 병렬 처리할 때 사용

-       프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받는다.

-       전달받은 모든 프로미스가 모두 fulfilled상태가 되면 모든 처리 결과를 배열에 저장해 새로운 프로미스 반환하고 처리 순서 보장

-       전달받은 프로미스 중 하나라도 rejected상태가 되면 즉시 종료 반환

-       인수로 전달받은 이터러블 요소가 프로미스가 아니면 resolve메서드로 프로미스 래핑

 

[Promise.race]

-       프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받는다.

-       가장 먼저 fulfilled상태가 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스 반환

-       하나라도 rejected상태가 되면 즉시 종료 반환

 

[Promise.allSettled]

-       프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받는다.

-       전달 받은 프로미스가 모두 settled상태가 되면 처리 결과를 배열로 반환

-       프로미스가 fulfilled상태이면 status, value 프로퍼티 갖음

-       프로미스가 rejected상태이면 status, reason 프로퍼티 갖음

 

마이크로태스크 큐

-       프로미스의 후속 처리 메서드의 콜백 함수가 임시 저장되는 곳

-       태스크 큐보다 우선순위가 높다.

 

fetch

-       XMLHttpRequest객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 Web API이다.

-       XMLHttpRequest객체보다 사용법 간단하고 프로미스를 지원하기 때문에 비동기 처리를 위한 콜백 패턴의 단점에서 자유롭다.

-       fetch함수에는 HTTP요청을 전송할 URLHTTP요청 메서드, HTTP요청 헤더, 페이로드 등을 설정한 객체를 전달한다.

-       fetch함수는 HTTP응답을 나타내는 Response객체를 래핑한 Promise객체를 반환한다.

-       fetch함수가 반환하는 프로미스는 오프라인 등의 네트워크 장애나 CORS 에러에 의해 요청이 완료되지 못한 경우에만 프로미스를 reject 하기에 에러처리에 주의가 필요하다.

-       axios는 모든 HTTP 에러를 reject하는 프로미스를 반환하므로 catch에서 처리 가능하고 fetch보다 다양한 기능 지원

 

46장 제너레이터와 async/await

제너레이터란?

-       코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수

-       제너레이터 함수는 함수 호출자에게 함수 실행의 제어권을 양도할 수 있다.

-       제너레이터 함수는 함수 호출자와 함수의 상태를 주고받을 수 있다.

-       제너레이터 함수를 호출하면 함수 코드를 실행하는 것이 아니라 이터러블이면서 동시에 이터레이터인 제너레이터 객체를 반환한다.

 

제너레이터 함수 정의

-       function* 키워드로 선언하고 하나 이상의 yield 표현식을 포함한다.

-       화살표 함수로 정의 X, 생성자 함수로 호출 X

 

제너레이터 객체

-       제너레이터 함수를 호출하면 함수 코드를 실행하는 것이 아닌 이터러블이면서 동시에 이터레이터인 제너레이터 객체를 생성해 반환한다.

-       next메서드 뿐만 아니라 return, throw 메서드를 갖는다.

-       next메서드 호출하면 yield표현식까지 코드 블럭 실행하고 yield된 값을 value 프로퍼티 값으로 falsedone 프로퍼티 값으로 갖는 이터레이터 리절트 객체 반환

-       return메서드 호출하면 인수로 전달받은 값을 value 프로퍼티 값으로 truedone프로퍼티 값으로 갖는 이터레이터 리절트 객체 반환

-       throw메서드 호출하면 인수로 전달받은 에러를 발생시키고 undefinedvalue프로퍼티 값으로 truedone프로퍼티 값으로 갖는 이터레이터 리절트 객체 반환

제너레이터의 일시 중지와 재게

-       yield키워드와 next 메서드를 통해 실행을 일시 중지했다가 필요한 시점에 다시 재게 가능

-       next메서드를 호출하면 yield 표현식 까지만 실행, yield키워드는 제너레이터 함수의 실행을 일시 중지시키거나 yield 키워드 뒤에 오는 표현식의 평가 결과를 제너레이터 함수 호출자에게 반환

-       next메서드에 전달한 인수는 제너레이터 함수의 yield표현식을 할당 받는 변수에 할당된다.

 

제너레이터의 활용

-       이터러블의 구현, 비동기 처리

 

async/await

-       제너레이터보다 간단하고 가독성 좋게 비동기 처리를 동기 처리처럼 동작하도록 async/await 도입

-       프로미스 기반으로 동작, 후속 처리 메서드 없이 마치 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현할 수 있다.

 

[async 함수]

-       async 키워드를 사용해 정의하고 언제나 프로미스 반환

 

[await 키워드]

-       프로미스가 settled상태가 될 때까지 대기하다가 settled상태가 되면 프로미스가 resolve한 처리 결과를 반환한다. 반드시 await키워드는 프로미스 앞에서 사용해야 한다.

-       await 키워드는 다음 실행을 일시 중지시켰다가 프로미스가 settled상태가 되면 다시 재개

 

[에러 처리]

-       try … catch문으로 에러 처리 가능

-       async 함수 내에서 catch문 사용해서 에러 처리하지 않으면 async 함수는 에러를 reject하는 프로미스를 반환하므로 프로미스 후속처리 메서드 사용해서 에러 캐치도 가능하다.

 

47장 에러 처리

에러처리의 필요성

-       에러나 예외적인 상황에 대응하지 않으면 프로그램이 강제 종료되므로 언제나 에러나 예외적인 상황이 발생할 수 있다는 것을 전제로 대응하는 코드를 작성하는 것이 중요하다.

 

try … catch … finally

-       에러처리 구현 방법은 예외적 상황이 발생하면 반환하는 값(null 또는 -1)if문이나 단축평가 또는 옵셔널 체이닝 연산자로 확인해서 처리하는 방법과 에러 처리 코드를 미리 등록해 두고 에러가 발생하면 에러 처리 코드로 점프하도록 하는 방법이 있다.

-       try … catch … finally문은 두번째 방법이다.

-       try 코드 블록이 먼저 실행되고 이 과정에서 에러가 발생하면 catch문의 매개 변수에 전달되고 catch가 실행된다. finally 코드 블록은 에러 발생과 상관없이 반드시 단 한 번 실행된다.

-       try … catch … finally문을 사용하면 강제 종료되지 않는다.

 

에러 객체

-       Error 생성자 함수는 에러 객체를 생성

-       에러 객체는 message 프로퍼티와 stack 프로퍼티를 갖는다.

-       message 프로퍼티 값은 Error 생성자 함수에 인수로 전달한 에러 메시지

-       stack 프로퍼티 값은 에러를 발생시킨 콜 스택의 호출 정보를 나타내는 문자열

-       JS7가지 에러 생성자 함수 제공(Error, SyntaxError, ReferenceError, TypeError, RangeError, URIError, EvalError)

 

throw

-       에러를 발생시키려면 try 코드 블록에서 throw문으로 에러 객체를 던져야 한다.

 

에러 전파

-       에러는 호출자 방향으로 전파된다. (콜 스택의 아래 방향)

-       throw된 에러를 캐치하지 않으면 호출자 방향으로 전파된다. 어디에서도 캐치하지 않으면 프로그램은 강제 종료된다.

-       비동기 함수인 setTimeout이나 프로미스 후속처리 메서드의 콜백함수는 호출자가 없다. 콜 스택의 가장 하부에 존재하므로 에러를 전파할 호출자가 존재하지 않는다.