Notice
Recent Posts
Recent Comments
«   2024/03   »
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
Archives
Today
Total
관리 메뉴

Keep calm and code on

Lambda를 이용하여 null 안전하게 처리하기 본문

카테고리 없음

Lambda를 이용하여 null 안전하게 처리하기

Sejong Park 2019. 7. 31. 09:27

NullPointerException은 자바 언어로 개발하면서 가장 친근하게 느껴지는 예외이다. 컴파일 레벨에서 쉽사리 잡히지도 않거니와 경우의 수가 너무나 다양하기 때문에 이를 잘 처리하는 것도 쉽지 않다. 코틀린처럼(Null Safety - Kotlin Programming Language) 예쁘게 null을 처리할 수 있는 방법이 있지도 않으며 Optional을 모든 경우에 쓰기에는 복잡성만 한가득 늘어나게 된다.

일반적으로 애플리케이션간 혹은 메시지를 주고 받을때 주로 DTO형식을 많이 이용하게 된다. 외부지점에서 DTO를 받는 경우 보통 이를 정제/변환하는 과정을 거쳐 활용을 하도록 로직을 작성하는 경우가 많은데, 이러한 정제/변환 과정에서 다음과 같은 코드를 필연적으로 많이 만날수밖에 없다.

String name = book.getAuthor().getName();

book 객체 하위 author의 값이 제대로 할당되지 않은 경우, 즉 null인 경우를 자주 만나곤 한다. 만약 NullPointerException을 예방하기 위해선 다음과 같이 작성하여야 한다.

String name = book.getAuthor() != null? book.getAuthor().getName() : null;

book이 null인 상황도 존재할것이다. 이러한 경우에는 위의 코드에 앞서서 book이 null인지 여부도 확인을 해야한다.

String name = null;
if(book != null) {
  name = book.getAuthor() != null? book.getAuthor().getName():null;  
}

단순하게 값을 하나 가져오는데 있어서 준비과정이 지나치게 길어지는 느낌이 든다. 이러한 경우 Lambda를 이용하여 복잡한 null 검증 로직을 쉽게 처리할 수 있을 것이다.

public static <R> R nullsafe(Supplier<R> supplier) {
    try {
        return supplier.get();
    } catch (NullPointerException e) {
        return null;
    }
}

NullPointerException을 메서드 바디에서 나도록 만들어버리고 외부에 전파되지 않도록 기본값을 설정하여 주었다. Supplier를 이용하여, null인지 여부를 파라미터 레벨에서는 검증하지 못하도록 설정하였다. 작성된 메서드는 아래와 같이 사용할 수 있다.

String name = nullsafe(() -> book.getAuthor().getName());

이렇게 할 경우 book이 null인지, name이 null인지 여부를 일일히 체크하지 않고 간결하게 값을 가져올 수 있다.
이때 유의하여야 할 점은 method reference를 이용해서는 안된다는 점이다. 할당된 값이 없기에 메서드 레퍼런스 구문이 제대로 동작하지 않게 된다.

Book book = null;

// name = null;
String name = nullsafe(() -> book.getAuthor());

// throw nullPointerException
Strign npeName = nullsafe(Book::getAuthor);

값이 존재하지 않는 경우 null 대신 기본값을 넣는 경우도 생각해볼수 있을것이다.

public static <R> R nullsafe(Supplier<R> supplier, R defaultValue) {
    try {
        return supplier.get();
    } catch (NullPointerException e) {
        return defaultValue;
    }
}

public static <R> R nullsafe(Supplier<R> mapper) {
    return nullsafe(mapper, null);
}

위의 코드는 아래와 같이 사용할 수 있을것이다.

Book book = new Book(1L, "Harry Porter", /*author*/ null);

String authorName = nullsafe(()->book.getAuthor().getName(), "J. K. Rowling");
Comments