안전 탐색 연산자

객체 지향 프로그래밍에서 **안전 탐색 연산자**(safe navigation operator), **옵셔널 체이닝 연산자**, **안전 호출 연산자**, **널-조건부 연산자**, **널-전파 연산자**는 첫 번째 인수가 null이면 null을 반환하는 이항 연산자이다. 그렇지 않으면 두 번째 인수에 따라 역참조 작업을 수행한다(일반적으로 객체 멤버 접근, 배열 인덱스 또는 람다 호출). 순차적인 명시적 null 검사와 할당을 피하고 이를 메서드/속성 체이닝으로 대체하는 데 사용된다. 탐색 연산자(예: ".")가 null 객체에 적용될 때 오류를 발생시키는 프로그래밍 언어에서 안전 탐색 연산자는 메서드/필드 체인의 평가를 중지하고 체인 표현식의 값으로 null을 반환한다. 2007년 Groovy 1.0에서 처음 사용되었으며accessdate=2021-01-04 현재 다음과 같은 언어에서 지원된다. C 샤프,accessdate=2016-01-28 스위프트,accessdate=2016-01-28 타입스크립트, 루비,accessdate=2016-01-28 코틀린,accessdate=2016-01-28 러스트, 자바스크립트,date=28 October 2024 등. 이 연산자에 대한 공통 명명 규칙은 현재 없지만 **안전 탐색 연산자**가 가장 널리 사용되는 용어이다. 이 연산자를 사용하는 주요 장점은 파멸의 피라미드를 피할 수 있다는 것이다. 프로그래머는 여러 중첩된 `if` 문을 작성하는 대신 일반적인 체이닝을 사용하고 점(또는 체이닝에 사용되는 다른 문자) 앞에 물음표 기호를 추가할 수 있다. **안전 탐색 연산자**와 **널 병합 연산자**는 모두 **널-인식 연산자**이지만, 작동 방식은 다르다.
# 예시

## Apex
Apex의 안전 탐색 연산자 예시:website=세일즈포스닷컴 a[x]?.aMethod().aField // a[x] == null 이면 null로 평가된다 a[x].aMethod()?.aField // a[x].aMethod()가 null로 평가되면 null을 반환한다 String profileUrl = user.getProfileUrl()?.toExternalForm(); return [SELECT Name FROM Account WHERE Id = :accId]?.Name;
## C#
C# 6.0 이상에는 `?.` (널-조건부 멤버 접근 연산자, Microsoft에서는 엘비스 연산자라고도 부르지만, C#에서 널 병합 연산자인 `??`와 동일한 일반적인 엘비스 연산자의 사용과는 혼동해서는 안 된다)와 인덱서 get 접근자의 널-안전 호출을 수행하는 `?[]` (널-조건부 요소 접근 연산자)가 있다. 멤버 접근 결과의 유형이 값 형식인 경우, 해당 멤버에 대한 널-조건부 접근 결과의 유형은 해당 값 형식의 널러블 버전이다.accessdate=29 August 2019 다음 예제는 문서 배열에서 첫 번째 문서의 저자 이름을 검색한다(각 문서에 `Author` 멤버가 있고 각 저자에 `Name` 멤버가 있다고 가정). 배열이 `null`이거나, 첫 번째 요소가 `null`이거나, 해당 문서의 `Author` 멤버가 `null`이거나, 해당 저자의 `Name` 멤버가 `null`이면 결과는 `null`이다. 배열이 null이 아니지만 비어 있는 경우(즉, 길이가 0인 경우) `IndexOutOfRangeException`이 여전히 발생한다는 점에 유의하라. string name = articles?[0]?.Author?.Name; 람다를 호출하려면 `callback?.Invoke()`가 필요하다. 널-조건부 호출(`callback?()`는 허용되지 않는다)이 없기 때문이다. Func callback = x => x * x; // x를 제곱한다 int result = callback?.Invoke(5);
## 클로저 (프로그래밍 언어)
클로저는 다른 언어에서 사용하는 의미의 진정한 연산자를 가지고 있지 않지만, 자바와 상호 운용되고 객체 탐색을 수행해야 하므로 `some->`accessdate=2019-06-07 매크로를 사용하여 안전 탐색을 수행할 수 있다. 확장된 매크로 `safe->`accessdate=2025-11-05는 nil 값 호출을 방지한다. (some-> article .author .name)
## CoffeeScript
실존 연산자:accessdate=2017-06-15 zip = lottery.drawWinner?().address?.zipcode
## Crystal
Crystal은 `try` 안전 탐색 메서드를 지원한다 url=https://crystal-lang.org/api/0.27.0/Object.html#try%28%26block%29-instance-method name = article.try &.author.try &.name
## Dart
조건부 멤버 접근 연산자:access-date=2020-01-08var name = article?.author?.name
## Gosu
널 안전 호출 연산자:accessdate=2018-12-18 var name = article?.author?.name 널-안전 호출 연산자는 Gosu 속성으로 선언된 클래스 속성에는 필요하지 않다. class Foo { var _bar: String as Bar } var foo: Foo = null // 아래 코드는 null로 평가되며 NullPointerException을 반환하지 않는다 var bar = foo.Bar
## Groovy
안전 탐색 연산자 및 안전 인덱스 연산자:accessdate=2020-09-25 def name = article?.authors?[0].name
## 자바스크립트
ECMA스크립트 2020에 추가된 선택적 체이닝 연산자는 참조나 함수가 undefined 또는 null일 가능성이 있을 때 연결된 객체를 통해 값에 접근하는 것을 간소화하는 방법을 제공한다.title = Optional Chaining in ECMAScript 2020 주요 데스크톱 브라우저는 2020년부터 이를 지원했으며, 대부분의 모바일 브라우저는 2024년까지 지원을 추가했다.title = Browser Support for Optional Chaining in JavaScript const name = article?.authors?.[0]?.name const result = callback?.() 이 연산자는 오른쪽에 있는 전체 호출 체인을 단락한다. 다음 예시에서는 bar가 "접근"되지 않는다. null?.foo.bar
## Kotlin
안전 호출 연산자: val name = article?.author?.name
## Objective-C
대부분의 경우 NULL에 대해 걱정할 필요 없이 일반적인 탐색 구문을 사용할 수 있다. 이는 NULL로 메시지가 전송될 때 아무런 부작용 없이 폐기되기 때문이다. NSString *name = article.author[0].name;
## Perl 5
Perl 5에는 이러한 종류의 연산자가 없지만, 다음 구문으로 포함 제안이 수락되었다.url=https://github.com/Perl/PPCs/blob/main/ppcs/ppc0021-optional-chaining-operator.md my $name = $article?->author?->name;
## PHP
널 안전 연산자는 PHP 8에 채택되었다.website=wiki.php.net $name = $article?->author?->name;
## Raku (Perl 6)
안전한 메서드 호출:accessdate=2022-09-16 my $name = $article.?author.?name;
## 루비 (프로그래밍 언어)
루비는 버전 2.3.0부터 `&.` 안전 탐색 연산자(외로운 연산자라고도 함)를 지원한다. name = article&.author&.name
## 러스트 (프로그래밍 언어)
러스트는 안전 탐색 연산자처럼 보일 수 있는 `?` 연산자를 제공한다.accessdate=2021-10-04 그러나 주요 차이점은 `?`가 `None` 값을 만날 때 `None`으로 평가되지 않는다는 것이다. 대신 `return` 문처럼 동작하여 둘러싼 함수나 클로저가 즉시 `None`을 반환하게 한다. `Option` 메서드 `map()` 및 `and_then()`을 안전 탐색에 사용할 수 있지만, 이 옵션은 안전 탐색 연산자보다 장황하다. fn print_author(article: Option) { println!( "Author: {}", article.and_then(|y| y.author) .map(|z| z.name) .unwrap_or("Unknown".to_owned()) ); } `?`를 사용하는 구현은 `article`이 `None`이거나 `article.unwrap().author`가 `None`이면 아무것도 출력하지 않는다("Author:"조차도). `?`가 `None`을 보는 즉시 함수는 반환된다. fn try_print_author(article: Option) -> Option{ println!("Author: {}", article?.author?.name); Some(()) }
## Scala
Scala의 null-safe 연산자는 Dsl.scala 라이브러리에서 제공한다.access-date=2019-06-03 val name = article.?.author.?.name : @ ? `@ ?` 어노테이션은 null을 허용하는 값을 나타내는 데 사용될 수 있다. case class Tree(left: Tree @ ? = null, right: Tree @ ? = null, value: String @ ? = null) val root: Tree @ ? = Tree( left = Tree( left = Tree(value = "left-left"), right = Tree(value = "left-right") ), right = Tree(value = "right") ) Scala의 일반적인 `.`는 `null` 값에서 메서드를 수행할 때 null-safe하지 않다. a[NullPointerException] should be thrownBy { root.right.left.right.value // root.right.left는 null이다! } 대신 널 허용 값에 `?` 연산자를 사용하여 예외를 피할 수 있다. root.?.right.?.left.?.value should be(null) `?` 중 하나가 `null` 값에서 수행되면 전체 표현식은 `null`이다. `null` 안전 연산자 `?`의 경계는 `@ ?`로 타입이 주석 처리된 가장 가까운 바깥쪽 표현식이다. ("Hello " + ("world " + root.?.right.?.left.?.value)) should be("Hello world null") ("Hello " + (("world " + root.?.right.?.left.?.value.?): @ ?)) should be("Hello null") (("Hello " + ("world " + root.?.right.?.left.?.value.?)): @ ?) should be(null)
## 스위프트 (프로그래밍 언어)
옵셔널 체이닝 연산자, 서브스크립트 연산자, 그리고 호출: let name = article?.authors?[0].name let result = protocolVar?.optionalRequirement?()
## 타입스크립트
옵셔널 체이닝 연산자는 타입스크립트 3.7 릴리스에 포함되었다.accessdate=2019-11-06 let x = foo?.bar?.[0]?.baz();
## Visual Basic .NET
Visual Basic 14 이상에는 C#과 유사한 `?.`(null-조건부 멤버 접근 연산자) 및 `?()`(null-조건부 인덱스 연산자)가 있다. 이들은 C#의 해당 연산자와 동일한 동작을 한다.accessdate=29 August 2019 다음 문은 위의 C# 예시와 동일하게 동작한다. Dim name = articles?(0)?.Author?.Name