글을 쓰게 된 이유
체스 미션을 하면서 “Optional을 메서드의 파라미터로 넣는 것은 안티패턴이다.”라는 리뷰를 받았습니다.
처음에 stackoverflow를 보고 이해되질 않았습니다.
파라미터로 넣든, Optional 을 리턴하든 똑같은 거 아닌가?
스택오버플로우에 채택된 답을 보면 아래와 같습니다.
- Using Optional parameters causing conditional logic inside the methods is literally contra-productive.
- Needing to pack an argument in an Optional, is suboptimal for the compiler, and does an unnecessary wrapping.
- In comparison to nullable parameters Optional is more costly.
- The risk of someone passing the Optional as null in actual parameters.
메서드 내부에서 조건부 논리를 유발, 불필요한 래핑 수행, Optional 이 비용이 더 많이 든다 등은 Optional 을 파라미터로 넣어서가 문제가 아닌 단지 Optional 의 단점이라고 생각합니다.
마지막인 “파라미터에 누군가가 null 로 전달할 위험”이 있다는 게 가장 큰 문제입니다.
이게 왜 위험한지는 Optional 이 등장하게 된 배경부터 알아보겠습니다.
Optional은 왜 나왔을까?
Optional 은 Java 1.8 부터 나온 기능으로 왜 나왔는지는 API Note를 보겠습니다.
Optional is primarily intended for use as a method return type where there is a clear need to represent "no result," and where using null is likely to cause errors. A variable whose type is Optional should never itself be null; it should always point to an Optional instance.
“결과 없음”을 명시적으로 표현해야하고, null 을 사용하면 오류가 발생할 가능성이 있는 메서드 반환 유형으로 사용하기 위함입니다. 유형이 Optional인 변수는 그 자체가 null 이 되어서는 안 되며, 항상 Optional 인스턴스를 가리켜야 합니다.
즉, 결과가 없을 수도 있다는 것을 나타내기 위해(nullable), null을 안전하게 사용하기 위해서(nullsafe) 만들어진 ‘컨테이너 객체’ 입니다.
그리고 “메서드 반환 유형”으로 사용, “Optional인 변수는 그 자체가 null 이 되면 안 된다”라고 작성돼 있습니다.
메서드 파라미터로 Optional 을 사용하게 되면 위 두 가지 모두 위배할 수 있습니다.
class B {
public void parameterOptional(final Optional<Box> box) {
// if(box == null)
box.ifPresentOrElse(
it -> System.out.println(it.fruit()),
NoSuchElementException::new
);
}
}
@Test
void test_optional() throws Exception {
B b = new B();
Assertions.assertThatThrownBy(() -> b.parameterOptional(null))
.isInstanceOf(NullPointerException.class);
}
테스트를 해보면 NPE가 발생하는 것을 알 수 있습니다.
코드를 보면 뭔가 찜찜하지 않으신가요?
우리는 대부분 Optional 을 사용할 때, 주석과 같이 null 체크를 할까요? 하지 않습니다.
이미 Optional 객체를 호출하면서 null 이면 A 행위, null 이 아니면 B 행위를 합니다. 코드와 같이 ifPresentOrElse와 같은 메서드를 사용하면서 말이죠.
만약 파라미터 자체에 null 이 들어왔다?
그러면 바로 NPE 터지는 거죠,,
결론
위와 같은 이유로 인해서 Optional을 파라미터에 넣는 것은 안티패턴이라고 합니다.
처음에는 스택오버플로우를 보고 이해 못 했습니다.
Optional 자체를 null 로 보내는 것이 아닌, Optional.isEmpty() 와 같이 Optional 안에 null 이 있는 상황만 생각했습니다. 그래서 “파라미터로 사용, 리턴을 하던 똑같지 않나” 라고 생각했습니다.
Optional 에 대한 개발자들의 생각, 등장배경과 생각하니 Optional 자체에 null 이 들어가면 매우 위험한 상황이 생길 수 있기 때문에, 왜 안티패턴이라고 불리는지 알 수 있었습니다.
REFERENCES
'Java' 카테고리의 다른 글
try-with-resources 는 왜 사용해야할까? (0) | 2023.03.28 |
---|---|
unmodifiableList & copyOf & 방어적 복사 (0) | 2023.02.21 |
Generic & Wildcard (0) | 2022.12.29 |
Generic in Java (2) | 2022.12.17 |
JDK ? JRE ? (0) | 2022.09.15 |