ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java Optional과 container object
    Java & Kotlin 2022. 9. 10. 21:07
    반응형

    1) 서론

    혹시 '열 길 물속은 알아도 한 길 사람 속은 모른다'라는 속담을 들어보신 적 있으신가요? 물은 직접 들어가 보면 알 수 있지만, 사람의 속은 알 수 없다는 의미인데요.

    학교, 회사 등에서 사람과의 관계는 언제나 어렵습니다. 실제의 마음을 잘 못 전달해서 오해를 살 수도 있습니다. 때로는 오히려 드러내지 않는 것이 더 좋았을까라는 고민도 하게 됩니다.

    최근에 개발을 하다가 내부 구현을 추상화된 표면과 내부 구현의 로직이 다른 것을 만났었는데요.

    Optional.isEmpty() 사용 중 당황했던 경험 그리고 이를 stackoverflow에 질문을 올리고, 이유와 철학을 알아가는 과정을 공유드리려고 합니다.


    2) Optional.isEmpty()의 속은 모르겠다

    Java8부터 등장한 Optional은 null을 우아하게 처리할 수 있는 방법인데요.

    Kotlin 혹은 기타 함수형 언어처럼 elvis operator(?:)가 없는 Java에서는 null을 항상 조심해야 합니다. 하지만 optional의 등장으로 nullable 객체를 사용하는 것에 편리해졌는데요.

    이렇게 편리한 optional 중 isEmpty()를 사용하며 조금 당황스러웠던 경험이 있는데요. Optional이 감싼 List 객체 내부 값의 empty 여부를 확인하려고 했습니다.

    Optional<List<String>> optional = Optional.of(new ArrayList<>());
    optional.isEmpty(); // alwasy false
    • Emtpy list를 optional 객체로 감싸고 있습니다.
    • 그리고 isEmpty()를 사용하여 확인하지만, 항상 false입니다.


    분명히 List 객체의 값은 empty인데 아니라고 합니다.

    이유가 뭘까요?

    • 추상화된 메서드의 이름은 isEmpty()
    • 내부 구현은 객체의 NULL 확인

    3) 의문

    의문이 발생합니다.

    "isEmpty()가 아니라, isNull() 이어야 하는 거 아닌가?"
    "왜 isEmpty()라고 지어서 헷갈리게 하는 거지?"

    고민을 내부 구현 로직을 봤는데 오히려 더더욱 고민이 증가합니다.

    그래서 stackoverflow에 질문을 해보기로 합니다. 혹시나 알고 있을 전 세계의 집단지성과 미래의 저와 같은 질문을 할 사람을 위해서입니다.


    4) 질문과 고민



    짧은 영어로 힘들게 질문을 남겨봅니다. 영어로 충분히 설명하기에 쉽지 않기 때문에 상세한 코드도 첨부해봅니다.

    그리고 오라클 공식 문서도 같이 확인해봅니다.

    요약하자면 이렇습니다.

    • 오라클 공식 문서에 의하면 Optional은 nullable 객체를 가질 수 있는 'container object'
    • container 내부의 객체를 확인하기 때문에 'empty'라는 표현을 사용하는 것이다
    • 즉 컨테이너 자체의 null 여부를 확인하는 것이 아니다


    여기서 얻을 수 있는 키워드는 container object라는 것인데요.

    오라클 공식 문서

    그림을 그려보자면 아래와 같을 것 같습니다.

    즉 우리가 확인하고자 하는 것은 optinal 컨테이너 내부 값의 존재 여부입니다. List object든, 단건 Object 형태이든 중요한 것은 컨테이너 내부의 값을 확인하고자 하는 겁니다.

    Container인 optional 객체 자체의 null 여부를 검증하는 것이 아닙니다. List 객체의 내부 값들을 확인하는 것과 마찬가지로 컨테이너도 같은 개념으로 empty라는 표현을 사용했다고 생각합니다.

    Optional<List<String>> optional = Optional.ofNullable(null);
    optional.isEmpty(); // true
    • Optional container 내부의 값이 null입니다.
    • isEmpty()로 검증 시 true 반환합니다.


    Optional의 철학을 이해하고 나니 List 타입의 객체를 감싸는 것 자체가 좋지 못 한 접근이었습니다.

    • List 객체 자체의 생성이 의심되는 게 아니라면 optional을 사용할 이유가 없습니다.
    • 내부의 값의 존재 여부를 확인할 때는 List.isEmpty()를 사용하면 됩니다.

     

    그리고 Java의 optional 기능에 참여한 개발자는 stackoverflow에서 이렇게 밝힙니다.

    • Optional 객체는 명확히 어떤 값이 없음을 표현하기 위한 기능이다.
    • 왜냐하면 null은 시스템 오류를 일으킬 가능성이 매우 높기 때문이다.
    • 그리고 Optional.get()을 절대로 사용하지 마라.

     

    위와 같이 밝히는것에서 optional을 어떠한 철학을 가지고 만들었는지 알 수 있는것 같습니다. NULL 객체가 있더라도 시스템 오류를 발생시키는것이 아닌, optional container에 담아 안정성을 확보하려는 목적으로 이해가 됩니다.


    5) 결론

    Stackoverflow에 질문을 던지기 전까지는 container object라는 키워드를 생각해보지 않았습니다. "내부 로직은 null을 확인하는데 메서드명은 다를까"와 같이 단순하고 표면적으로 드러나는 것에 대해서만 고민을 했는데요.

    그리고 List 객체도 일반 Object와 동일하게 optional로 감싸곤 했습니다.

    실제 오라클 문서에는 Optional 객체가 어떤 철학을 가지고 있는지 잘 설명하고 있었습니다. 공식문서를 바탕으로 해당 객체가 만들어진 철학에 대한 이해를 놓쳤던 것 같습니다.

    이번 기회를 통해서 공식문서를 더더욱 잘 읽고, 구현의 철학과 이유에 대해서 더더욱 파악하기 위해서 노력해야 할 것 같습니다.

    그리고 stackoverflow에 질문을 남기는 과정을 통해서 질문을 잘하는 방법에 대해서 고민해보게 됐습니다.

    반응형

    댓글

Designed by Tistory.