티스토리 뷰

JavsScript에서 물음표를 사용하는 사례가 몇 가지 있는데, 예를 들어 삼항연산자 / null 병합 연산자 등, 그 중에 하나가 바로 optional chainig 이다. 나는 사실 옵셔널 체이닝이라는 단어를 잘 몰라서 물음표 연산자라고만 생각했었는데, 이게 잘 사용하면 코드가 간결해지는 효과가 탁월한 것 같다.


예를들어 깊이 중첩된 오브젝트 내의 한 데이터에 접근한다고 하자. 그럼 다음과 같이 표현하는게 일반적인데,

let nestedProp = obj.first && obj.first.second;

이 뜻은 obj.first.second에 접근하기 전에 obj.first가 존재하는지 먼저 확인하라는 의미이다.

만약 다음과 같이 코드를 작성하게 된다면 obj.first가 없을 때, 에러를 발생시키게 된다.

let nestedProp = obj.first.second;

 

그럼 혹시 저 깊이 중첩의 중첩의 중첩이 된 데이터가 있다면 마냥 &&와 &&와 &&의 조합으로 검증을 해야할까? 이런 문제를 해결하기 위하여 사용되는 것이 optional Chaning이다. 옵셔널 체이닝은 다음과 같은 형식으로 사용하는데,

let nestedProp = obj.first?.second;

obj.first를 먼저 확인하고, null 혹은 undefined가 아닐 시, second의 데이터를 찾아 nestedProp 변수에 할당하라는 의미이다. obj.first가 null 혹은 undefined를 반환했을 때, 더이상 second가 존재하는지의 판단은 하지 않고 해당 값 (null || undefined)을 nestedProp에 반환시킨다.

참고로 이와 같이 우측의 데이터 존재 여부를 확인 하기 전에 undefined를 발현하고, 반환하는 현상을 '단락평가'라고 칭한다.

 


옵셔널 체이닝은 또한 함수에도 사용할 수 있는데, 다음과 같이 사용한다면

let result = someInterface.customMethod?.();

someInterface.customMethod 함수가 존재하지 않을 때, undefined를 반환하여 에러를 없앨 수 있다. 함수가 존재한다면 그대로 수행하여 결과값을 반환받을것이다.

하지만 someInterface 자체가 없다면 여전히 에러를 발생하게 될텐데, 상단과 같은 코드를 응용하여 다음과 같이 작성하면 간단하게 해결할 수 있다.

let result = someInterface?.customMethod?.();

이와 같은 방식으로 모든 것을 검증하면 상관은 없지만 개인적으로 옵셔널 체이닝 남발하는 것은 비추천한다. 미관상으로 모든 단어의 끝에 물음표가 붙게 된다면 오히려 더 지저분한 코드가 되기 때문이다. 그러니 옵셔널 체이닝은 꼭 존재하지 않아도 되는, 즉 있어도 없어도 되는 데이터의 존재를 확인할 때 사용하는 것이 좋을 것 같다. 


MDN에서 좋은 예시가 하나 있어서 소개한다.

하단 코드에서 catch 부분을 보면 error가 캐치 되었고, onError가 파라미터로 넘어왔을 때, err.message를 띄우는데 이 검증을 마무리하기까지 총 5줄의 코드가 사용되었다.

// Written as of ES2019
function doSomething(onContent, onError) {
  try {
    // ... do something with the data
  }
  catch (err) {
    if (onError) { // Testing if onError really exists
      onError(err.message);
    }
  }
}

하지만 옵셔널 체이닝을 사용한다면 단 3줄. catch문을 제외한 내부 로직만 본다면 무려 3줄을 1줄로 줄여서 표현할 수 있는 것이다. (물론 1줄로 압축할 수 있다고 무조건 좋은 코드는 절대 아니다.)

// Using optional chaining with function calls
function doSomething(onContent, onError) {
  try {
   // ... do something with the data
  }
  catch (err) {
    onError?.(err.message); // no exception if onError is undefined
  }
}

 


옵셔널 체이닝은 심지어 다음과 같은 형식으로 배열 혹은 오브젝트에 접근도 가능하다.

let nestedProp = obj?.['prop' + 'Name'];
let arrayItem = arr?.[42];

 

다만 이를 응용하여 할당하게 되면 에러를 발생하니 주의하자!

let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment

 

뿐만 아니라 null 병합 연산자와 함께 사용도 가능한데, 이는 나중에 null 병합 연산자 포스팅 할 기회가 될 때 예시를 찾아봐야겠다.


아무튼 내가 이해한 혹은 느낀 옵셔널 체이닝의 가장 큰 장점은 깊은 곳 까지 이해가 가능하고, 그 이해를 짧은 식으로 표현할 수 있다는 점이다. 다만 단점으로는 최신 문법이라 지원하지 않는, 예를 들어 IE, 브라우저에서는 폴리필이 필요하다. 

 

상단의 모든 이해와 예시는 MDN을 참고하였다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Optional_chaining

 

Optional chaining - JavaScript | MDN

optional chaining 연산자 (?.) 는 체인의 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성 값을 읽을 수 있다.

developer.mozilla.org

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함