[TIL] 자바스크립트 웹 개발 기본기

Jeris·2023년 4월 13일
0

코드잇 부트캠프 0기

목록 보기
25/107

Topic

웹 기초 지식, Web API, 자바스크립트의 비동기 실행



What I Learned

웹 기초

  1. fetch 함수 살펴보기
    fetch('https://www.google.com')
      .then((response) => response.text())
      .then((result) => { console.log(result); });
    • fetch() 서버에 리퀘스트를 보내고 리스폰스를 받는 보편적인 방법
    • Callback 어떤 조건이 만족되었을 때 실행되는 함수
    • then() 콜백을 등록해주는 메소드
      • fetch 함수가 리턴하는 프로미스 객체의 메소드이다
    • text() 리스폰스의 실제 내용을 갖고 있는 프로미스 객체를 리턴하는 리스폰스 객체의 메소드
    • 파라미터로 넘어온 URL로 리퀘스트를 보낸다
    • 리스폰스는 하나의 객체가 되어 then으로 등록된 첫 콜백의 파라미터로 전달된다
    • then 메소드로 등록한 콜백은 서버의 리스폰스가 왔을 때 실행된다
    • 콜백이 실행되면 리턴값을 다음 콜백의 파라미터로 전달하고 다음 콜백을 실행한다
  2. 웹이란?
    • Web(World Wide Web): 인터넷에 연결된 컴퓨터를 통해 사람들이 정보를 공유할 수 있는 전 세계적인 정보 공간
  3. URL이란?
    • URI(Uniform Resource Identifier): 웹 기술에 사용되는 논리적 또는 물리적 리소스를 식별하는 고유한 문자 시퀀스
    • URL(Uniform Resource Locator): 웹 페이지를 찾기 위한 주소
    • URI는 URL과 URN(Uniform Resource Name)에서 추천되는 방식을 고려하여 설계된 상위 개념이다
    • URI의 표현방법
      URI = scheme ":" ["//" authority] path [ "?" query ] [ "#" fragment ]
      • URL은 URI와는 달리, # <fragment>를 포함하지 않으며, ? <query>까지만 포함한다
      • scheme 리소스에 접근할 방법을 정의해 둔 프로토콜 이름
        • http, https, mailto, tel
      • authority 서버의 사용자 이름, 비밀번호, 호스트, 포트번호 등
        • 일반적인 웹 페이지에서는 호스트인 도메인/IP 주소만 쓰인다
      • path 리소스 경로
      • query key=value 형태로 서버에 문자열로 전달하는 파라미터
        • '&'을 써서 여러 key-value 쌍을 전달할 수 있다
      • fragment html 내부 북마크 등에 사용되며 서버에 전송되지 않는 정보
  4. https란?
    • https(HyperText Transfer Protocol Secure): 웹 상에서 정보를 주고받을 수 있는 통신 규약인 HTTP의 보안이 강화된 버전

Web API

  1. JSON이란?

    • JSON(JavaScript Object Notation) 자바스크립트 언어로부터 파생된 가벼운 데이터 포맷
    • JSON의 기본 자료형: Number, String, Boolean, Array, Object, null
    • JSON 포맷 참조
  2. 자바스크립트 객체 표기법과 JSON 문법의 차이

    • JSON에는 프로퍼티 네임과 밸류를 표현하는 방식에 제한이 있다
      • JSON에서는 각 프로퍼티의 이름을 반드시 큰따옴표(")로 감싸줘야 한다
      • JSON에서는 밸류가 문자열인 경우 큰따옴표(")를 사용해야 한다
    • JSON에서는 표현할 수 없는 값들이 있다
      • undefined, NaN, Infinity
    • JSON에는 주석을 추가할 수 없다
    • 자바스크립트 문법과 JSON 문법 간의 차이 참조
  3. JSON 데이터를 객체로 변환하기

    • 서버는 JSON 파일을 string 타입으로 전달한다
    • JSON.parse() 메소드로 string 타입의 JSON 데이터를 자바스크립트 배열로 변환할 수 있다
      • JSON JSON 데이터를 다루기 위해 사용되는 자바스크립트의 기본 객체
  4. Request의 종류를 결정하는 메소드

    • GET Read(데이터 조회)
    • POST Create(데이터 생성)
    • PUT Update(데이터 수정)
    • DELETE Delete(데이터 삭제)
  5. Request의 Head와 Body

    • Request는 Head와 Body로 이루어져 있다
      • Head 리퀘스트에 관한 여러 가지 부가 정보들이 들어있는 부분
      • Body 실제 데이터를 담는 부분
    • POST, PUT request는 보통 body에 data를 담아서 보내줘야 한다
    • GET, DELETE request는 보통 body가 필요하지 않다
    • Request Header request head 안에 존재하는 하나하나의 key-value 쌍
    • Header Head의 내용
      • :authority URL의 authority
      • :method Request method
      • :path URL의 path
      • :scheme URL의 scheme
      • accept 클라이언트가 이해 가능한 컨텐츠 MIME 타입의 종류 (*/*: 모든 MIME 타입)
      • accept-encoding 클라이언트가 이해 가능한 인코딩 종류(주로 압축 알고리즘)
      • accept-language 클라이언트가 선호하는 언어(한국어, 영어 등)
      • origin fetch가 시작된 서버 이름
      • referer request를 보낸 페이지의 주소
      • sec-ch-ua 브라우저의 버전
      • sec-ch-ua-mobile 모바일 디바이스의 브라우저인지 아닌지
      • sec-ch-ua-platform 유저가 실행하고 있는 플랫폼/운영체제
      • sec-fetch-dest 리퀘스트의 목적지
      • sec-fetch-mode 리퀘스트 모드 (CORS, navigate, no-cors, same-origin, websocket)
      • sec-fetch-site fetch가 시작된 서버와 요청된 리소스의 서버의 관계
      • user-agent 리퀘스트를 보낸 브라우저와 그것이 설치된 운영 체제의 정보
      • HTTP headers 참조
    • http/2에서는 http/1.1에서 사용하던 GET /men/shirts HTTP/1.1과 같은 start-line을 사용하지 않는 대신에, method와 path를 일종의 pseudo-header로 표현한다
    • Pseudo-header 앞에는 콜론이 붙어있다
  6. POST request 보내기

    • GET request 보내기

      // 3번 직원의 정보 조회
      fetch('https://learn.codeit.kr/api/members/3')
        .then((response) => response.text())
        .then((result) => { console.log(result); });
    • POST request 보내기

      // 새로운 직원 정보 추가
      const newMember = {
        name: 'jeris',
        email: 'jeris@email.kr',
        department: 'engineering',
      };
      
      fetch('https://learn.codeit.kr/api/members', {
        method: 'POST',
        body: JSON.stringify(newMember),
      })
        .then((response) => response.text())
        .then((result) => { console.log(result)});
      • POST request body에 특정 값을 보냈을 때, 그 값을 서버에 저장하고 그 결과를 response로 전달하는 로직이 구현된 사이트를 이용했다
      • POST request를 보냈을 때의 response는 서버 설정에 따라 다르다
    • Option object request options들을 요소로 하는 객체로 fetch() 함수의 두 번째 argument로 전달한다

      • method: 'GET'이 default value이다
    • JSON.stringify() 객체를 JSON string으로 변환하는 메소드

  7. PUT request, DELETE request 보내기

    • PUT requst 보내기

      // id=6인 직원 정보 수정
      const member = {
        name: 'jeris',
        email: 'jeris@email.kr',
        department: 'marketing',
      };
      
      fetch('https://learn.codeit.kr/api/members/6', {
        method: 'PUT',
        body: JSON.stringify(member),
      })
        .then((response) => response.text())
        .then((result) => { console.log(result)});
    • DELETE request 보내기

      // id=6인 직원 정보 삭제
      fetch('https://learn.codeit.kr/api/members/6', {
        method: 'DELETE',
      })
        .then((response) => response.text())
        .then((result) => { console.log(result)});
  8. 모범적인 Web API, REST API

    • Web API(Application Programming Interface): 어느 URL로 어떤 리퀘스트를 보냈을 때, 무슨 처리가 수행되고 어떤 리스폰스가 오는지에 관해 미리 정해진 규격
    • REST API: REST architecture에 부합하는 Web API 설계를 위한 가이드라인
    • REST(Representational State Transfer) architecture: 미국의 컴퓨터 과학자인 Roy Fielding이 제시한, 웹이 갖추어야 할 이상적인 architecture
    • REST architecture가 되기 위한 조건
      • Client-Server Client-Server 구조를 통해 양측의 관심사를 분리해야 한다
      • Stateless Client가 보낸 각 리퀘스트에 관해서 Server는 그 어떤 context도 저장하지 않는다. 즉, 매 리퀘스트는 각각 독립적인 것으로 취급된다는 뜻이다
      • Cache Cache를 활용해서 네트워크 비용을 절감해야 한다. Server는 response에, Client가 response를 재활용해도 되는지 여부(Cacheable)를 담아서 보내야 한다
      • Uniform Interface Client가 Server와 통신하는 인터페이스는 다음과 같은 하위 4가지를 준수해야 한다
        • identification of resources resource를 URI로 식별할 수 있어야 한다
        • manipulation of resources through representations Client와 Server는 둘 다 resource를 직접적으로 다루는 게 아니라 resource의 representations를 다뤄야 한다
        • self-descriptive messages request와 response 모두 그 자체에 있는 정보만으로 모든 것을 해석할 수 있어야 한다
        • hypermedia as the engine of application state response에는 현재 상태에서 다른 상태로 이전할 수 있는 링크를 포함하고 있어야 한다
      • Layered System Cline와 Server 사이에는 proxy, gateway와 같은 중간 매개 요소를 두고, 보안, 로드 밸런싱 등을 수행할 수 있어야 한다. 이를 통해 Client와 Server 사이에는 hierarchical layers가 형성된다
      • Code on Demand Client는 받아서 바로 실행할 수 있는 applet이나 script 파일을 Server로부터 받을 수 있어야 한다. 이 조건은 Optional이므로 REST architecture가 되기 위해 반드시 만족될 필요는 없다
    • RESTful service 이런 REST API를 사용하는 웹 서비스
    • identification of resources에 관해서 특히 중요한 규칙 2가지
      • URL은 resource를 나타내기 위해서만 사용하고, resource handling은 method로 해야 한다
      • Document는 단수 명사로, Collection은 복수 명사로 표시한다
        • document 하나의 객체로 표현할 수 있는 resource (file)
        • collection Documents를 담을 수 있는 resource (directory)
  9. JSON 데이터 다루기 종합

    • Serialization 자바스크립트 객체를 JSON string으로 변환하는 작업 (stringify)
    • Deserialization JSON string을 자바스크립트 객체로 변환하는 작업 (parse)
    • response.json() JSON string을 parsing한 결과를 담은 promise 객체를 리턴하는 메소드
  10. Status Code

    • Response도 Head와 Body로 이루어져 있다
    • Status Code Request를 받은 server가 그 작업 결과를 나타내기 위해서 Response head에 넣는 숫자
      • 100번대: server가 client에게 정보성 응답(Informational response)를 줄 때 사용된다
        • 100 Continue Client가 server에게 계속 request를 보내도 괜찮은지 물어봤을 때, 계속 request를 보내도 괜찮다고 알려주는 상태 코드
        • 101 Switching Protocols Client가 protocol을 바꾸자는 request를 허락한다고 알려주는 코드
      • 200번대: request가 성공 처리되었음을 의미한다
        • 200 OK request가 성공적으로 처리되었음을 포괄적으로 의미하는 상태 코드
        • 201 Created request의 내용대로 resource가 잘 생성되었음을 의미하는 상태 코드
        • 202 Accepted request의 내용이 일단은 잘 접수되었음을 의미하는 상태 코드
      • 300번대: client의 request가 아직 처리되지 않았고, request 처리를 원하면 client 측의 추가적인 작업이 필요함을 의미한다
        • 301 Moved Permanently resource의 위치가 바뀌었음을 나타내는 상태 코드
        • 302 Found resource의 위치가 일시적으로 바뀌었음을 나타내는 상태 코드
          • 301, 302같은 상태 코드가 있는 response의 head에는 Location이라는 헤더도 일반적으로 포함되어 있다
          • 대부분의 브라우저는 GET request의 response로 이런 상태 코드를 받았을 때, 헤드에 포함된 Location 값으로 redirection 동작을 수행합니다
        • 304 Not Modified response로 받았던 resource가 변경되지 않았으므로 client에게 caching된 resource를 사용하도록 권하는 상태 코드
      • 400번대: request를 보내는 client 쪽에 문제가 있음을 의미한다
        • 400 Bad Request request에 문제가 있을 때 나타내는 상태 코드
        • 401 Unauthorized 아직 신원이 확인되지 않은(unauthenticated) user로부터 온 request를 처리할 수 없다는 뜻을 의미하는 상태 코드
        • 403 Forbidden user의 신원은 확인되었지만 해당 resource에 접근 권한이 없어서 처리할 수 없다는 뜻을 의미하는 상태 코드
        • 404 Not Found 해당 URL이 나타내는 resource를 찾을 수 없다는 뜻을 의미하는 상태 코드
        • 405 Method Not Allowed 해당 resource에 대해서 요구한 처리는 허용되지 않는다는 뜻을 의미하는 상태 코드
        • 413 Payload Too Large 현재 request의 body에 들어있는 data의 size가 지나치게 커서 server가 거부한다는 뜻을 의미하는 상태 코드
        • 429 Too Many Requests 일정 시간동안 client가 지나치게 많은 request를 보냈다는 뜻을 의미하는 상태 코드
      • 500번대: Server 쪽의 문제로 인해 request를 정상적으로 처리할 수 없음을 의미한다
        • 500 Internal Server Error 현재 알 수 없는 server 내의 error로 인해 request를 처리할 수 없다는 뜻을 의미하는 상태 코드
        • 503 Service Unavailable 현재 server 점검 중이거나, traffic 폭주 등으로 인해 service를 제공할 수 없다는 뜻을 의미하는 상태 코드
    • HTTP response status codes 참조
    • Web API 설계 시에 상태 코드들도 각각의 상황에 알맞은 것들이 설정되도록 설계해야 한다
  11. Content-type이란?

    • Content-Type header body에 들어 있는 data가 어떤 타입인지를 나타낸다
      • Content-Type header는 'main type/sub type'의 형식으로 나타난다
      • 일반 텍스트: text/plain
      • CSS code: text/css
      • HTML code: text/html
      • JavaScript code: text/javascript
      • image: image/bmp,gif,png, ...
      • audio: audio/mp4,ogg, ...
      • video: video/mp4,H264, ...
      • JSON data: application/json
      • 확인되지 않은 binary file: application/octet-stream
        • binary file 텍스트 파일 이외의 파일들을 보통 binary file이라고 한다
      • Content-Type header 참조
  12. 알아두면 좋은 Content-type들

    • XML(Extensible Markup Language) tag를 사용하는 data type
      • 예시
      <?xml version="1.0" encoding="UTF-8 ?>
      <person>
          <name>Michael Kim</name>
          <height>180</height>
          <weight>70</weight>
          <hobbies>
              <value>Basketball</value>
              <value>Listening to music</value>
          </hobbies>
      </person>
      • JSON이 2013년에 표준화되고 그 뒤로 활성화되기 전까지만 해도 정말 많이 사용되던 data type
      • 보통 Schema라는 별도의 문서를 함께 사용한다
        • Schema 태그 정보에 대한 문서
      • data에 대한 엄격한 validty 검증에 특화된 data format
      • JSON에 비해 용량이 크고 가독성이 떨어진다
      • XML을 나타내는 Content-Type header는 application/xml이다
      • XML의 문법을 기반으로 특수한 규칙을 더해 만든 data type들은 그 이름 끝에 +xml을 붙여서 사용한다
    • form tag에 사용되는 Content-Type headers
      • application/x-www-form-urlencoded
        • form tag는 기본적으로 이 type의 data를 body에 담아서 보낸다
        • data 표현 방식이 URL의 query 표현 방식과 똑같다
        • URL encoding 작업을 수행해 특정 특수 문자들 그리고 영어와 숫자를 제외한 다른 나라의 문자들을 percent encoding한다
        • CORS(Cross-Origin Resource Sharing) 문제를 해결할 때, 다른 Content-Type 값들에 비해 주고받아야하는 request와 response 수가 더 적다는 약간의 장점이 있다
        • URLSearchParams라는 객체를 request body로 전달하면 자동으로 값에 URL encoding을 적용해주기 때문에, application/x-www-form-urlencoded type의 data를 fetch 함수로도 보낼 수 있다
      • multipart/form-data 여러 종류의 data를 하나로 합친 Content-Type
        • form tag/JavaScript code만으로 request body에 담아 전송할 수 있다
        • boundary 기준으로 여러 종류의 데이터들을 각각 나눈다
  13. 그 밖에 알아야 할 내용들

    • AJAX 참조
    • GET, POST, PUT, DELETE 이외의 메소드들
      • PATCH 새로운 data로 기존 data의 일부를 수정
        • PUT request는 기존 데이터를 아예 덮어쓰기 때문에 PATCH request가 유용할 때가 있다
      • HEAD GET 메소드와 동일하지만 reponse body 부분은 제외하고, reponse head 부분만 받는다
        • body의 파일 용량이 너무 크다던지 할 때 data에 관한 정보만 head를 통해 얻으려는 상황에서 활용된다
      • Request Methods
    • 웹 통신말고 다른 통신도 있어요.
      • TCP(Transmission Control Protocol) 두 개의 호스트를 연결하고 데이터 스트림을 교환하게 해주는 중요한 네트워크 프로토콜
      • IP(Internet Protocol) 송신 호스트와 수신 호스트의 Packet Switchng Netwrok에서 정보를 주고받는데 사용하는 정보 위주의 프로토콜
      • Ethernet 로컬 환경의 컴퓨터 및 기타 장치를 네트워크에 연결하기 위해 개발된 프로토콜
      • UDP(User Datagram Protocol) 전송 속도와 효율성이 보안과 신뢰성보다 중요할 때 데이터를 전송하기 위해 IP와 함께 사용되는 오래된 프로토콜
      • FTP(File Transfer Protocol) 인터넷을 통해 한 호스트에서 다른 호스트로 파일을 전송하기 위해 사용했던 과거의 표준 프로토콜
      • SSH(Secure Shell) 보안되지 않은 네트워크를 통해 네트워크 서비스를 안전하게 운영하기 위한 암호화 네트워크 프로토콜입
      • HTTP는 TCP를 기반으로, TCP는 IP를 기반으로, IP는 Ethernet을 기반으로 동작한다
      • MMORPG game server develop, IOT 기기 개발 등과 같이 성능 최적화 등이 필요한 경우에 TCP라는 프로토콜만으로 통신하는 코드를 짜기도 한다

비동기 실행과 Promise 객체

  1. fetch 함수와 비동기 실행
    - then() 메소드는 콜백을 등록만 하고 바로 그 다음 줄의 코드가 실행된다
    - 콜백은 나중에 response가 도착했을 때 실행된다
    - 비동기 프로그래밍(Asynchronous programming): 프로그램이 잠재적으로 장시간 실행되는 작업을 시작하고 해당 작업이 실행되는 동안 해당 작업이 완료될 때까지 기다리지 않고 다른 이벤트에 응답할 수 있도록 하는 기술
    - 비동기 실행 함수의 실행 순서
    참조

  2. 비동기 실행 함수

    • setTimeout() 첫 번째 파라미터의 콜백을 두 번째 파라미터 값의 밀리초(ms) 만큼 시간이 경과했을 때까지 실행을 미룬다
      console.log('a');
      setTimeout(() => { console.log('b'); }, 2000);
      console.log('c');
      /*
      a
      c
      b
      */
    • setInterval() 특정 콜백을 일정한 시간 간격으로 실행하도록 등록한다
      console.log('a');
      setInterval(() => { console.log('b'); }, 2000);
      console.log('c');
      /*
      a
      c
      b
      b
      ...
      */
    • el.addEventListener()
    • fetch 함수는 Promise 객체를 리턴하고, 이 Promise 객체는 비동기 실행을 지원하는 또 다른 종류의 문법을 갖는다
  3. Promise object(ES2015)

    • promise 작업에 관한 상태 정보를 갖고 있는 객체
      • pending 작업이 진행 중인 상태
      • fulfilled 작업이 성공적으로 완료된 상태
      • rejected 작업이 실패한 상태
    • promise 객체가 fulfilled 상태가 되면 promise 객체는 그 작업의 성공 결과도 함께 가진다
      • fetch 함수의 경우 then 메소드의 첫 번째 argument(response)로 리턴하는 값이 그 작업의 성공 결과에 해당한다
    • promise 객체가 rejected 상태가 되면 promise 객체는 그 작업의 실패 이유에 관한 정보도 함께 가진다
    • then() promise object's method, which resisters callback to execute when promise object's status changes from pending to fulfilled
  4. What is Promise Chaining

    • then() method can be added after evrey then() method.
    • then() method returns new promise object.
    • Promise Chaining addingthen() method back to back.
      • Each subsequent operation starts when the previous operation succeeds, with the result from the previous step.
    • Two cases in which then() method is executed
      • When the callback returns a promise object.
        • Let the promise state which the then() method returned equal to that which the callback returns
      • When the callback returns the others.
        • Let the promise state which the then() method returned fulfilled, and the operation result equal to which the callback returns
    • It is also promise object that text(), json() methods return
    • You can use promise chaining when you need to do asynchronous exectuion sequentially
  5. rejected state가 되면 실행할 callback

    • then() method의 second parameter로, 전달받은 promise state가 rejected일 때 실행할 callback을 넣어줄 수 있다
    • 두 번째 callback의 parameter로는 작업 실패 정보가 넘어온다
  6. then 메소드 완벽하게 이해하기

    • 실행된 callback이 어떤 값을 return하는 경우
      • Promise object를 return하는 경우
        - then 메소드가 return했던 promise object가 callback이 return한 promise object의 state와 result를 똑같이 따라 갖게 된다
      • Promise object 이외의 값을 return하는 경우
        • then 메소드가 리턴했던 프로미스 객체는 fulfilled 상태가 되고 작업 성공 결과로 그 값을 갖게 된다.
      • 실행된 콜백이 아무 값도 리턴하지 않는 경우
        - 콜백이 undefined를 리턴한 것으로 간주 된다.
      • 실행한 콜백 내부에서 에러가 발생했을 때
        • then 메소드가 리턴했던 프로미스 객체는 rejected 상태가 되고 작업 실패 정보로 해당 에러 객체를 갖게 된다.
      • 아무런 콜백도 실행되지 않을 때
        • then 메소드가 리턴했던 프로미스 객체는 이전 프로미스 객체와 동일한 상태와 결과를 갖게 된다
  7. catch 메소드

    • 프로미스 객체의 catch() 메소드를 사용해 then 메소드에 두 번째 콜백을 넣는 방법을 대신할 수 있다
    fetch('https://jsonplaceholder.typicode.com/users')
      .then((response) => response.text())
      .catch((error) => { console.log(error); })
      // .then(undefined, (error) => { console.log(error); })
      .then((result) => { console.log(result); });
    • 두 번째 콜백만 넣은 then 메소드와 똑같이 작동한다
    • catch 메소드는 마지막에 써야 프로미스 체이닝에서 어느 프로미스 객체가 rejected 상태가 되더라도 모두 대응할 수 있다
    • 비록 에러가 발생했다고 해도 만약 실패한 작업 대신 다른 방법을 통해서 작업을 정상적으로 끝마칠 수 있는 상황이라면 catch 메소드를 중간에 사용할 수도 있다
  8. finally 메소드

    • 그 전의 프로미스 객체가 fulfilled 상태가 되든 rejected 상태가 되든 상관 없이 항상 내부의 콜백을 실행한다
    • 보통 catch 메소드 뒤인 맨 아래에 쓴다
  9. Promise 객체의 등장 배경

    • 함수에 콜백을 직접 넣는 형식은 콜백 헬(callback hell)이라고 하는 문제를 일으킬 수도 있다
    fetch('https://first.com', (response) => {
      // Do Something
      fetch('https://second.com', (response) => {
        // Do Something
        fetch('https;//third.com', (response) => {
          // Do Something
          fetch('https;//fourth.com', (response) => {
            // Do Something
          });
        });
      });
    });
    • 프로미스 객체를 쓰지 않았다면 이런 식의 코드를 작성해야 했을 것이다
    • 콜백 헬의 문제는 가독성이 떨어지고 수정하기 어렵다는 점이다
    • 프로미스 문법은 그 뿐만 아니라 비동기 작업에 관한 좀 더 세밀한 개념들이 반영되어 있다
  10. 직접 만들어 보는 Promise 객체

    const p = new Promise((resolve, reject) => {
      setTimeout(() => { resolve('success'); }, 2000);
    });
    
    p.then((result) => { console.log(result); });
    /*
    Promise {<pending>}
    // 2초 후
    success
    */
    • new Promise(function(resolve, reject){}) 프로미스 객체 생성 메소드
    • resolve 작업 성공시 호출 되어 결과 값을 아규먼트로 받아서 fulfilled 프로미스를 리턴하는 함수
    • reject 작업 실패시 호출 되어 결과 값을 아규먼트로 받아서 rejected 프로미스를 리턴하는 함수
  11. Promisify

    • Promisify 전통적인 형식의 비동기 실행 함수를 Promise 객체로 감싸서 그 Promise 객체를 리턴하는 형식으로 만드는 작업
    function wait(text, milliseconds) {
      setTimeout(() => text, milliseconds);
    }
    
    fetch('https://jsonplaceholder.typicode.com/users')
    ...
      .then((result) => { return wait(`${result}`, 2000); })
    ...
    • 이렇게 콜백 안에 비동기 실행되는 함수를 바로 사용하면, 나중에 실행되는 부분의 리턴값을 Promise Chain에서 사용할 수 없게된다
    • 기존의 비동기 실행 함수의 콜백이 리턴하는 값을 프로미스 체인에서 사용하고 싶다면, 해당 함수를 감싸서 프로미스 객체를 직접 생성하고, 그 프로미스 객체를 리턴해야 한다
    // function wait(text, milliseconds) {
    //   setTimeout(() => text, milliseconds);
    // }
    
    function wait(text, milliseconds) {
      const p = new Promise((resolve, reject) => {
        setTimeout(() => { resolve(text); }, 2000);
      });
      return p;
    }
    • 콜백 헬을 방지하기 위해 Promisify하기도 한다
    • Promisify를 하면 안 되는 함수
      • 콜백을 여러 번 실행하는 함수(setInterval, addEventListener 등)
      • 프로미스 객체는 한번 pending 상태에서 fulfilled 또는 rejected 상태가 되고 나면 그 뒤로는 그 상태와 결과가 바뀌지 않기 때문이다
  12. 이미 상태가 결정된 Promise 객체

    • fulfilled 상태의 Promise 객체 만들기
      const p = Promise.resolve('success');
      // 작업 성공 결과로 문자열 'success'를 갖는다
    • rejected 상태의 Promise 객체 만들기
      const p = Promise.reject(new Error('fail'));
      // 작업 실패 정보로 문자열 'fail'을 갖는다
    • 프로미스 객체는 항상 결과를 줄 수 있는 공급자(Provider)이고 그것의 then 메소드는 그결과를 소비하는 콜백인 소비자(Consumer)를 설정하는 메소드이며 프로미스 객체의 상태나 시점과는 전혀 연관이 없다
  13. 여러 Promise 객체를 다루는 방법(심화)

    • 프로미스 객체들이 담긴 배열을 argument로 받아 프로미스 객체를 리턴하는 메소드
      • promise.all(array)
        • 배열에 담긴 프로미스 객체들이 모두 pending 상태에서 fulfilled 상태가 되면 all 메소드가 리턴했던 프로미스 객체는 fulfilled 상태가 되고 각 프로미스 객체의 작업 성공 결과들로 이루어진 배열을, 그 작업 성공 결과로 갖게 된다
        • 배열에 담긴 프로미스 객체 중 하나라도 rejected 상태가 되면 all 메소드가 리턴했던 프로미스 객체는 rejected 상태가되고 동일한 작업 실패 정보를 갖게 된다
        • Promise.all() 참조
      • promise.race(array)
        • 배열에 담긴 프로미스 객체 중 가장 먼저 fulfilled 상태 또는 rejected 상태가 된 프로미스 객체와 동일한 상태와 결과를 갖게 된다
        • Promise.race() 참조
      • promise.allSettled(array)
        • 배열에 담긴 모든 프로미스 객체가 pending 상태가 아니게 되면, allSettled가 리턴했던 프로미스 객체는 fulfilled 상태가 되고 그 작업 성공 결과로 하나의 배열을 갖게 된다
        • 이 배열에는 아규먼트로 받았던 배열 내의 각 프로미스 객체의 status(최종 상태), value(작업 성공 결과), reason(작업 실패 정보)을 담은 객체들이 요소로 존재한다
        [
           {status: "fulfilled", value: 1},
           {status: "fulfilled", value: 2},
           {status: "fulfilled", value: 3},
           {status: "rejected",  reason: Error: an error}
        ]
      • promise.any(array)
        • 배열에 담긴 프로미스 객체 중 가장 먼저 fulfilled 상태가 된 프로미스 객체와 동일한 상태와 결과를 갖게 된다
        • 모든 프로미스 객체가 rejected 상태가 된다면 AggregateError라고 하는 에러를 작업 실패 정보로 갖고 rejected 상태가 된다
        • Promise.any() 참조
  14. axios

    • axios 프로미스 API를 활용하는 HTTP 비동기 통신 라이브러리
      • axios 객체에서 리퀘스트를 보내는 많은 메소드들이 fetch 함수처럼 프로미스 객체를 리턴한다
      • fetch 함수보다 좋은 점
        • 모든 리퀘스트, 리스폰스에 대한 공통 설정 및 공통된 전처리 함수 삽입 가능
        • serialization, deserialization을 자동으로 수행
        • 특정 리퀘스트에 대해 얼마나 오랫동안 리스폰스가 오지 않으면 리퀘스트를 취소할지 설정 가능(request timeout)
        • 업로드 시 진행 상태 정보를 얻을 수 있음
        • 리퀘스트 취소 기능 지원 등
      • axios github page 참조

async/await을 활용한 비동기 코드

  1. async/await이란?(ES2017)

    // fetch('URL')
    //   .then((response) => response.text())
    //   .then((result) => { console.log(result); });
    
    async function fetchAndPrint() {
      const response = await fetch('URL');
      const result = await response.text();
      console.log(result);
    }
    
    fetchAndPrint();
    • fetchAndPrint() 함수는 주석 처리된 프로미스 체이닝과 똑같이 작동한다
    • async AsyncFunction 객체를 반환하는 하나의 비동기 함수를 정의하는 키워드
      • 함수의 코드 중에서 프로미스 객체를 리턴하는 코드가 있다는 뜻
    • await 비동기적으로 실행될 부분을 지정하는 키워드
      • 리턴될 프로미스 객체 앞에 붙인다
  2. catch문과 finally문

    • 비동기적으로 실행되는 코드를 try문에 넣고, catch문에 프로미스 객체가 rejected될 때 실행할 코드를 넣으면 된다
    async function name() {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/users');
        const result = await response.text();
        console.log(result);
      } catch (error) {
        console.log(error);
      } finally {
        console.log('exit');
      }
    }
  3. async 함수가 리턴하는 Promise 객체

    • 함수 내에서 프로미스 객체를 리턴하는 경우
      • 해당 프로미스 객체와 동일한 상태와 작업 성공 결과(또는 작업 실패 정보)를 가진 프로미스 객체를 리턴한다
    • 프로미스 객체 이외의 값을 리턴하는 경우
      • fulfilled 상태이면서, 리턴된 값을 작업 성공 결과로 가진 프로미스 객체를 리턴한다
    • 아무 값도 리턴하지 않는 경우
      • fulfilled 상태이면서, undefined를 작업 성공 결과로 가진 프로미스 객체를 리턴한다
    • async 함수 내부에서 에러가 발생했을 때
      • rejected 상태이면서, 해당 에러 객체를 작업 실패 정보로 가진 프로미스 객체를 리턴한다
  4. async 함수 안의 async 함수

    • async 함수도 프로미스 객체를 리턴하기 때문에, async 함수 앞에 await을 붙여서 또 다른 async 함수 안에 async 함수를 활용할 수 있다
  5. async를 붙이는 위치

    • 함수 선언식(Function Declaration)
    • 함수 표현식(Function Expression)
      • Named Function Expression
      • Anonymous Function Expression
    • 화살표 함수(Arrow Function)
    • 즉시 실행 함수(Immediately-invoked function expression, IIFE)
    // 1) Function Declaration
    async function example1(a, b) {
      return a + b;
    }
    
    // 2-1) Function Expression(Named)
    const example2_1= async function add(a, b) {
      return a + b;
    };
    
    // 2-2) Function Expression(Anonymous)
    const example2_2 = async function(a, b) {
      return a + b;
    };
    
    // 3-1) Arrow Function
    const example3_1 = async (a, b) => {
      return a + b;
    };
    
    // 3-2) Arrow Function(shortened)
    const example3_2 = async (a, b) => a + b;
    
    // 4) IIFE
    (async function print(sentence) {
      console.log(sentence);
      return sentence;
    }('I love JavaScript!'));
    
    (async function (a, b) {
      return a + b;
    }(1, 2));
    
    (async (a, b) => {
      return a + b; 
    })(1, 2);
    
    (async (a, b) => a + b)(1, 2);
  6. async 함수를 작성할 때 주의해야할 성능 문제

    async function getResponses(urls) {
      for(const url of urls){
        const response = await fetch(url);
        console.log(await response.text());
      }
    }
    • getResponse urls를 파라미터로, 여러 개의 URL들이 있는 배열을 받아서, 순서대로 각 URL에 리퀘스트를 보내고, 그 리스폰스의 내용을 출력하는 함수
    • URL을 순차적으로 처리한다는 문제가 있다
    • 리스폰스의 순서가 상관없는 경우라면 각 url에 리퀘스트를 보내고 리스폰스를 받는 코드를 즉시실행되는 async함수로 감싸서 해결할 수 있다
    async function fetchUrls(urls){
      for(const url of urls){
        (async () => { // 추가된 부분!
          const response = await fetch(url);
          console.log(await response.text());
        })(); // 추가된 부분!
      }
    }
    • 이전 코드처럼 이전 URL에 대한 리스폰스가 오기까지를 기다렸다가 다음 URL에 리퀘스트를 보내지 않고, 모든 URL에 대한 리퀘스트를 쭉 보내버리고, 먼저 리스폰스가 오는 순서대로 그 내용이 출력된다



Feedback

  • 영어로 작성하는 것을 시도해봤는데, 학습 속도가 느려져서 writing에 익숙해진다면 시도해 봐야겠다
  • axios는 사용해보면서 배울 필요가 있을 것 같다
  • 콜백이 동기 실행, 비동기 실행되는 원리를 추가로 공부하자
  • 다음으로 '자바스크립트 객체 지향 기본기' 코드잇 콘텐츠를 수강할 예정이다



Reference

profile
job's done

0개의 댓글