[REAL Deep Dive into JS] 43. AJAX

young_pallete·2022년 10월 28일
0

REAL JavaScript Deep Dive

목록 보기
44/46

🚦 본론

드디어 AJAX가 나오네요. 이 친구를 통해 서버에서 데이터를 주고 받으며 HTML을 부분적으로 바꾸는 방식을 쓰게 됐는데요.

사실 SSR이라고 불리는 친구는, 검색 최적화에 있어 CSR의 대안으로 나온 친구 같지만, 알고 보면 원래 있던 친구입니다.

AJAX가 있던 이전에는 HTML을 주고 받으며 처음부터 다시 렌더링하는 방식이 성행되었는데요. 이것이 SSR입니다. 다른 곳도 아니고 '서버(Server)' 쪽에서 (Side) 렌더링(Rendering)을 한다는 거죠.

이렇게 하면, 검색 최적화에 유리해집니다. 봇이 정확히 이 HTML에 어떤 콘텐츠가 들어 있는지를 확인할 수 있게 되기 때문이죠.

이런 SSR이라는 것이 지금 당장 중요한 내용이 아니군요.
결국 AJAX가 무엇인지를 설명하는 글이기에, 결국 AJAX는 SSR로만 렌더링하는 방식을 개선한 방안이라 생각하면 됩니다.

배경

이렇게 HTML을 계속해서 받아오는 것은 성능에서도, UX에서도 불편함을 주었어요.

  • 화면이 계속해서 전환할 때 깜빡거리는 현상과 (다시 HTML을 처음부터 렌더링하기 때문이죠)
  • 리소스 낭비가 분명히 존재했고 (부분을 위해 전체를 바꿔야 하니)
  • 마지막으로 서버와 동기적으로 주고 받았으므로 블로킹이 발생했죠.

이를 해결하고자 한 것이 바로 AJAX입니다.

JSON의 등장

XML이라는 친구가 있어요.
이 친구는 HTML과 비슷하게 생겼는데, 역할이 좀 달랐어요. 데이터를 주고 받기 위한 목적으로 사용했거든요.

그런데... 느려요. 내가 전달해야 할 데이터의 양보다 텍스트를 더 넣어야 할 것도 많았고요.

그런 상황에서, JSON이 등장했어요.
아니, 키랑 값만 잘 전달해주고, 직렬화 처리만 잘해주면 너무 간편하잖아요!
심지어, 전송이 빨랐습니다.

그래서 AJAXAsynchronous JavaScript and XML이지만, 아이러니하게도 JSON을 좀 더 많이 쓰게 된 웃픈(?) 상황이 연출되었답니다.

참고로, 직렬화란 JSON.stringify([[JSON Format]])으로 stringify를 해주는 것을 말하고, 받을 때에는 JSON.parse([[Stringified JSON]])로 처리합니다. 이는 역직렬화라고 불러요.

XMLHttpRequest

결국 데이터를 주고받는다는 것은, 이를 위한 통신이 필요하다는 것이고,
통신이 있다는 것은 통신을 위한 규약이 존재하겠죠?

결국 데이터는 우리가 담아서 전송해야 하는데, 이에 대한 처리를 담당하는 객체가 필요했어요.

그 친구가 바로 XMLHttpRequest입니다.
이 친구에다가 데이터를 담아두고 날려보내면 되는 거에요.
다만 이 친구는, 브라우저 환경에서만 동작하니 참고해주세요!

생성

const xhr = new XMLHttpRequest();

프로퍼티와 메서드

프로퍼티

  • readyState: 현재 상태를 나타내고 있어요. 0~4까지의 값을 갖고 있어요.
  • status: 응답 결과를 나타내죠. 흔히 말하는 404가 이런 상태에요. 정수입니다.
  • statusText: 전송에 대한 여부를 응답 메시지로 전달해줘요.
  • responseType: 응답 데이터를 전송할 때 어떤 타입으로 주는 건지를 명시해줘요.
  • response: 응답에 대한 body를 나타내요. 응답 데이터 타입에 따라 달라져요.
  • responseText: 응답 메시지를 가끔 같이 담아서 보내는 경우가 있어요. 그럴 때 씁니다.

이벤트 핸들러 프로퍼티

  • onreadystatechange: 해당 객체의 상태 변경 시 호출돼요.
  • onloadstart: HTTP 요청에 대한 응답을 받기 시작할 때 호출돼요.
  • onprogress: 우리 상태 진행률 알아야 할 때 있죠? 진행률이 나옵니다.
  • onabort: abort로 인해 메서드가 중단될 경우 나옵니다.
  • onerror: 요청 에러가 발생하면 나와요.
  • onload: 요청이 완료되면 나와요.
  • ontimeout: 요청 시간이 초과되면 나와요.
  • onloadend: 요청이 완료되거나 실패하면 나와요.

메서드

  • open: 요청 초기화를 해줘요.
  • send: 요청을 전송해줘요.
  • abort: 이미 전송된 HTTP가 있다면 중단시켜요.
  • setRequestHeader: 특정 요청 헤더 값을 설정해줘요.
  • getResponseHeader: 특정 HTTP 요청 헤더의 값을 문자열로 반환해요.

정적 프로퍼티

  • UNSENT: open 메서드 호출 이전을 의미해요. 값은 0입니다.
  • OPENED: open 메서드 호출 이후를 의미합니다. 값은 1이에요.
  • HEADERS_RECEIVED: send 메서드 호출 이후를 의미해요. 값은 2에요.
  • LOADING: 서버가 응답 중임을 의미해요. 값은 3입니다.
  • DONE: 응답이 완료되었음을 의미해요. 값은 4입니다.

XMLHttpRequest.prototype.open(method, url[, async])

결과적으로 3개의 인자를 받는데요.
앞의 2개는 많이들 아실 것 같고, 3번째 인자를 살펴보죠.
이 친구가 이제 비동기로 요청할 것인지에 대한 여부를 설정하는데요.
기본값은 true라고 합니다. 따라서 기본적으로 비동기 통신을 지향하는 AJAX를 알 수 있죠.

XMLHttpRequest.prototype.send

이 친구가 이제 요청을 전송한다고 했죠?
그런데 요청할 때에는 담을 데이터들을 메서드에 따라 다르게 처리해줘야 해요.

  • GET: URL의 쿼리 문자열에 전달해줘요.
  • POST: 요청 몸체에 담아서 전달해줘요.

데이터의 타입을 생각하면 쉬워요.
보통 GET을 요청했다는 건 받아오는 요청을 할 때에요. 따라서 굳이 body를 쓸 이유가 없죠. 줄 데이터가 없으니까요.

그런데 POST는 새롭게 데이터를 추가하도록 요청할 때 씁니다.
따라서 페이로드가 있어야 하므로 이를 전달할 때 body를 씁니다.

항상 JSON은 직렬화, 역직렬화 주의해주세요!

XMLHttpRequest.prototype.setRequestHeader

다음과 같이 사용해요.

const xhr = XMLHttpRequest();
xhr.setRequestHeader([[요청 헤더]], [[]])

요청할 때는 서버와 통신하기 위한 헤더를 서로 잘 설정해줘야 통신이 잘 이루어집니다.
이를 위한 친구에요.

이 책에서는 AcceptContent-type에 대해 살펴봤군요!

Content-type

우리는 전송할 데이터의 MIME 타입 정보를 적어줘야 해요.
웹에서는 MIME 타입이 가장 적절한 방식으로 인정받고 있어요.
대개 [[카테고리]]/[[개별타입]]의 방식으로 타입을 적어준답니다.

카테고리는

  • text
  • application
  • video
  • audio
  • image
  • multipart등이 있는데요.

이는 상황에 맞춰서 잘 살펴보면 좋을 것 같아요.

Accept

이건 반대로 서버가 응답할 데이터의 타입을 지정해주는 거에요.
우리도 요청을 받았을 때, 엉뚱한 데이터 타입이 나온다면 곤란해지니까요!
헤더를 accept로 설정해주고, 원하는 적절한 MIME 타입을 지정해주면 된답니다.

🎉 마치며

사실 저는 fetchaxios를 많이 써서인지, XMLHttpRequest는 좀 많이 낯설기는 해요.
실제로 XHR 방식이 유용한 기능들도 많지만 지금의 트렌드와는 좀 달라요.

Promise가 아닌 이벤트를 통해 받는다는 점도 그렇고, 크로스 브라우징 이슈도 있다고 합니다.

timeout같은 유용한 기능들도 있긴 하지만, axios 선에서 컷... 😭
하지만, 나중에 레거시 코드를 본다던지, 혹은 비동기를 이해하는 데 있어서는 전혀 부족함 없는 친구인 것 같네요. 저도 이번에 잘 살펴보았어요!

그럼, 다들 즐거운 코딩하시길 바라며. 이상! 🌈

profile
People are scared of falling to the bottom but born from there. What they've lost is nth. 😉

0개의 댓글