반응형

기본적으로 Javascript의 원시 타입(Undefined, Null, Boolean, Number, String 등)을 제외한 모든 객체는 mutable하다.

즉 생성된 이후에 언제든 변경될 수 있다.

 

이런 mutable한 객체를 immutable하게 변경하는 것도 가능하다. 다음의 두 옵션을 활용해볼 수 있다.

 

1. Object.defineProperty를 통한 설정

let customObj = {};
Object.defineProperty(customObj, "newKey", {value: "newValue"});

위와 같이 Object.defineProeprty 메소드를 사용하면 newKey의 값은 읽기 전용이되어 수정하는 것이 불가해진다.

이 메소드는 writable 옵션을 포함하고 있는데 기본 값이 false이다.

하지만 새로운 프로퍼티를 추가하는 것은 얼마든 가능하며, {writable: true} 옵션을 설정할 경우 수정이 가능해진다.

let customObj = {};
Object.defineProperty(customObj, "newKey", {value: "newValue"});

customObj.anotherKey = "anotherValue"; // 새로운 프로퍼티를 추가할 수 있다.
// customObj = {newKey: "newValue", anotherKey: "anotherValue"}

customObj.anotherKey = "theOtherValue"; // 수정도 가능하다.
// customObj = {newKey: "newValue", anotherKey: "theOtherValue"}

customObj.newKey = "anotherValue"; // 하지만 writable: false인 프로퍼티의 경우 암묵적으로 무시된다.
// customObj = {newKey: "newValue"}

Object.defineProperty(customObj, "theOtherKey", {value: "theOtherValue", writable: true});
customObj.theOtherKey = "newValue"; // 수정이 가능하다.
// customObj = {theOtherKey: "newValue"}

 

2. Object.freeze 를 통한 설정

let customObj = {};
customObj.newKey = "newValue";
Object.freeze(customObj);

위와 같이 freeze를 사용하게 되면 객체가 말그대로 얼어 붙는다. 추가하거나 삭제, 수정 모두가 불가해진다.

let customObj = {};
customObj.newKey = "newValue";
Object.freeze(customObj);

// 모든 편집 작업이 암묵적으로 무시된다.
customObj.anotherKey = "anotherValue"; // 추가할 수 없다.
// customObj = {newKey: "newValue"}

delete customObj.newKey; // 제거할 수 없다.
// customObj = {newKey: "newValue"}

customObj.newKey = "anotherValue"; // 수정할 수 없다.
// customObj = {newKey: "newValue"}

 

 

특정 프로퍼티를 immutable하게 하려면 Object.defineProperty를, 객체 자체를 immutable하게 하려면 Object.freeze를 활용하면 된다.

반응형
반응형

TL;DR(Too Long; Didn't Read). 요약.

AbortController API를 사용해 응답이 반환되지 않은 비동기 요청을 취소할 수 있다.

const abortController = new AbortController();
fetch(request, {signal: abortController.signal}) // signal을 설정한다.
  .then(doSomthing)
});
abortController.abort(); // 원할 때 호출하면, signal을 등록한 요청을 취소한다.

 

 

 

 

전형적인 웹에서는 한번 요청이 시작하면 취소하는 것이 불가했고 그럴 필요성도 별로 없었다. 요청을 취소해야할 만한 상황이 발생한다면 요청 자체를 정말 필요한 때에만 수행하도록 처리하는 방식으로 다뤄왔을 것이다. 그렇지 않을 경우 원치 않는 응답에 대한 결과 처리가 부가적으로 필요했을 것이다.

 

하지만 이제는 AbortController API를 활용하여 응답이 반환되지 않은 요청을 취소할 수 있다.

 

과도한 새로운 정보 요청은 클라이언트(렌더링)와 서버(응답)에 부하를 주며 상용 서비스에서는 보통 비용으로도 이어진다. 따라서 필요한 시점에 요청할 수 있도록 처리가 필요하다.

중요한 점.

AbortController API는 클라이언트 API이므로, 요청을 취소한다고해도 이미 전송된 요청은 서버가 그대로 받는다. 브라우저가 자신이 전송한 요청의 응답에 대한 핸들링을 취소한다 정도로 이해하면 좋을 것 같다.

(이제와 생각해보니, 이미 서버로 날아간 요청을 어떻게 취소할 수 있다고 생각했었는지...)

 

지도를 포함하는 페이지가 있고, 지도를 이동할 때마다 화면에 나타나는 영역에 해당하는 새로운 정보를 서버로 요청하는 기능을 구현하였다고 가정해보자.

지도의 이동(move)이 발생할 때마다 새로운 정보를 요청한다면 셀 수 없이 많은 수의 요청이 발생할 것이고, 그에 따라 필요한 처리도 늘어날 것이다. 그래서 보통은 지도의 이동이 끝났을 때(moveend) 새로운 정보를 요청하는 방식을 사용한다.

하지만 원하는 영역이 나타날 때 까지 빠르게 연속해서 지도를 이동한다면, 응답이 오기전에 새로운 요청을 계속해서 생성하게 되고 응답이 오지 않은 과거의 요청은 그 의미를 잃게 된다.

 

이 경우, 각 요청에 대해 다음과 같이 AbortController를 생성하고 그 signal을 요청하는 fetch에게 넘겨주자.

map.on("moveend", (e) => {
  const abortController = new AbortController();
  fetch(request, {signal: abortController.signal})
      .then(doSomthing)
});

그 다음, 취소가 필요할 때 abortController의 abort 메소드를 호출하면된다.

let isPending = false;
let abortController;

map.on("moveend", (e) => {
  if (isPending) { // 요청이 pending 상태일 때 취소
	abortController.abort();
  }

  abortController = new AbortController();
  isPending = true;

  fetch(request, {signal: abortController.signal})
      .then((res) => {
        doSomething
      })
      .finally(() => {
      	isPending = false;
      });
});

 

자세한 내용은 MDN을 참조하자.

https://developer.mozilla.org/ko/docs/Web/API/AbortController/abort

 

AbortController.abort()

AbortController 인터페이스의 abort() 메소드는 DOM 요청(Fetch 요청과 같은)이 완료되기 전에 취소한다. 이를 통해 fetch 요청, 모든 응답 Body 소비, 스트림을 취소할 수 있다.

developer.mozilla.org

반응형
반응형

테스트 코드를 작성하거나, 기능상의 이유로 마우스나 터치 이벤트를 프로그래밍적인 방식으로 발생시켜야 하는 경우가 있다.

다음과 같이 몇 가지 browser API를 사용하여 구현이 가능하다.

 

 

반응형

+ Recent posts