# Optional Chaining
자바(타입)스크립트를 사용하여 개발하다 보면 자주 사용하게 되는 연산자로서 어떤 객체의 프로퍼티에 접근하거나 함수를 호출할 때 참조의 대상이 nullish 인 경우 에러를 발생시키는 대신 undefined 를 리턴하도록 작동한다.
mozila 문서에서는 optional chaining의 기능을 다음과 같이 설명하고 있다.
optional chaining 연산자 (?.) 는 체인의 각 참조가 유효한지 명시적으로 검증하지 않고, 연결된 객체 체인 내에 깊숙이 위치한 속성 값을 읽을 수 있다.
즉 누락될 가능성이 있는 속성을 참조하는 경우 optional chaining 을 이용하여 짧고 간결하게 표현식을 구성할 수 있다.
# Usage
Optional Chaining 은 다음과 같이 사용이 가능하다.
mozila 문서에서는 크게 네 가지로 case를 소개하고 있는데, 공통적인 특징은 "집합체 속에서 특정한 원소에 접근할 때" 발생 가능한 상황이라는 것이다. 여기서 집합체는 객체가 될 수도 있고, 배열이 될 수도 있으며 프로그램 전역 공간이 될 수도 있다.
(1) obj?.prop
(2) obj?.[expr]
(3) arr?.[index]
(4) func?.(args)
각 케이스의 구체적인 예제는 mozila에서 확인 할 수 있다. 사실 이 글의 작성 동기는 후술할 내용들과 밀접한 관련이 있다.
# More
proposal-optional-chaining github에 올라온 FAQ 들을 읽어보면, 개발자들이 어떤 목적이나 생각을 가지고 이 기능을 proposal 했는지 대략적으로나마 알 수 있다. 대표적인 FAQ를 가져와 보았다.
Q. Why does foo?.() throw when foo is neither nullish nor callable?
A. Imagine a library which will call a handler function, e.g. onChange, just when the user has provided it. If the user provides the number 3 instead of a function, the library will likely want to throw and inform the user of their mistaken usage. This is exactly what the proposed semantics for onChange?.() achieve.Moreover, this ensures that ?. has a consistent meaning in all cases. Instead of making calls a special case where we check typeof foo === 'function', we simply check foo == null across the board. Finally, remember that optional chaining is not an error-suppression mechanism.
질문은 optional chaining 을 이용하여 호출하는 속성이 값이 존재하지만 함수가 아닐때 에러가 발생하는 이유에 대해 물어본 것이다.
이에 대한 답변은 해당 경우는 의도치 않은 실수(mistaken usage) 에 대한 것이며 이는 error throw 를 통해 사용자에게 알려야 한다는 것이다.
더불어 optional chaining은 함수라는 특정 케이스를 상정하여 추가적인 작업을 처리하지 않고 모든 경우에 있어 동일하게 동작하도록 만들어졌다고 하며, 또한 optional chaining은 에러 우회 메커니즘이 아니라고 답변하고 있다.
이는 중요한 내용이라고 볼 수 있는데, optional chaining을 남용하는 것을 지양하고 충분히 예측 가능한 상황에서만 사용하는 것을 권장하는 것이다.
# Support
필자 역시 optional chaining을 남용했다가 피 볼 뻔 했다.
위에서 언급한 컨텍스트는 아니지만, 레거시 프로젝트에서 아무 생각 없이 optional chaining을 사용했다가 작업물이 gulp.js 로 배포될 때 이슈가 발생했었다(바로 오늘..)
따라서 optional chaining compatibility 에 대해 정리를 끝으로 글을 마무리하려 한다.
기존 프로젝트를 가지고 개발하는 경우 아무리 본인에게 익숙한 기술이라고 해도 프로젝트와의 호환성을 면밀히 살펴보고 작업하도록 하자..
Spec: ECMAScript2020 (ES6 스펙으로 착각했지만 아니었다. 구 스펙에서는 babel plugin을 이용해 사용할 수 있다.)
Node.js: v14.0.0 +
Typescript: v3.7.2 +
Browser: IE를 제외하고 최신 버전에서 모두 호환
참조
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Optional_chaining
https://github.com/tc39/proposal-optional-chaining
댓글