본문 바로가기

클린 코드

[주클] 주관적인 클린 코드 - NPE 피하기

이 시리즈는 어떤 코드가 좋은 코드일까라는 질문에 답하기 위한 저의 주관 100%의 시리즈입니다.
제가 생각한 것이 정답이 아닐 확률이 높습니다.
여러분들이 생각했을 때 더 좋은 방법이 있다 하시면 댓글로 달아주세요!

 

제가 Java를 사용해서 코드를 작성하고 테스트 중에 가장 민감하게 느껴지는 예외는 Null Pointer Exception입니다.

이는 처음 개발에 대해서 배울 때도 여러 번 주의를 들었던 부분이어서 그런 것 같기도 합니다.

 

Null Pointer Exception(이하 NPE)는 왜 발생할까요?

 

Null인 객체를 참조하여 발생하는 Runtime Exception입니다. 즉, Null인 객체를 이용하여 무언가를 하려고 한다면 에러가 발생합니다.

 

NPE를 발생하지 않게 하려면 어떻게 해야 하나요?

Null을 참조하지 않도록 체크하는 로직이 우선되어야 합니다. 혹은 Null을 리턴하거나 참조되더라도 Null이 아닌 객체를 통해서 사용할 수 있게 만들어야 합니다.

 

주관적인 클린 코드 방법

NPE를 해결하는 방법은 예외 발생 가능 상황에 따라 여러 방법들이 있겠지만 제가 가장 많이 사용하는 것은 아래 2개 정도입니다.

 

  • StringUtils, ObjectUtils와 같은 라이브러리 사용
  • Optional 사용

Utils 사용

아래와 같은 코드는 NPE를 발생시킬 우려가 있습니다. nullableParam에 null이 들어온다면 split 실행 시점에 NPE가 발생할 수 있습니다. null 객체에 split이란 함수가 없으니까요.

 

public String[] testFunction(String nullableParam) {
	// nullableParam이 null이라면 split 실행 시점에서 NPE 발생
	return nullableParam.split(",");
}

 

null이 들어오지 않는 게 최선이지만 위의 testFunction 함수에서는 그것을 확신할 수 없기에 Null Safe 하게 구성해야 합니다. 이때 저는 보통 Util들을 사용합니다. 

 

import org.apache.commons.lang3.StringUtils;

public String[] testFunction(String nullable) {
	return StringUtils.split(nullableParam, ",");
}

 

여기서는 apache.commons의 유틸을 사용했습니다. StringUtils는 Null이 될 리가 없고 split 함수 내에서는 null 체크를 하고 있습니다. 파라미터가 null이면 null을 반환하도록 되어있습니다.

 

// StringUtils.split(...)
public static String[] split(final String str, final String separatorChars) {
	return splitWorker(str, separatorChars, -1, false);
}

// StringUtils.splitWorker(...)


private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
	// Performance tuned for 2.0 (JDK1.4)
	// Direct code is quicker than StringTokenizer.
	// Also, StringTokenizer uses isSpace() not isWhitespace()

	if (str == null) {
		return null;
	}
	final int len = str.length();
	if (len == 0) {
		return ArrayUtils.EMPTY_STRING_ARRAY;
	}
    ...
}

 

단 3줄, 짧으면 1줄이면 null 체크가 가능하지만 Utils를 쓰는 이유는 그냥 보기에 깔끔해 보여서입니다 :D

 

Optional

Optional에 대한 설명은 저의 다른 게시물로 대체하겠습니다.

 

Optional 설명

 

Java 1.8 Optional

Optional Optional을 사용하지 않을 때는 메서드의 결과값이 null일 경우를 체크하고 분기를 나눠서 처리해야 했습니다. 코드가 지저분해지고 길어졌죠. Optional을 사용하면 조금 더 직관적으로 표현할

marrrang.tistory.com

 

위의 설명에서 보듯 Optional은 지원하는 목적이 아래와 같습니다.

 

메서드가 반환할 결괏값이 '없음'을 명확하게 표현하고, null을 반환하면 에러를 유발할 가능성이 높은 상황에서 Optional을 반환 타입으로 사용하는 것이 목적이다.

 

목적에도 나와 있듯이 null을 반환하면 에러를 유발할 가능성이 높은 상황에 사용하도록 권장하고 있습니다.

 

따라서 Java를 사용하신다면 Nullable 한 상황에 Optional을 사용하지 않고 계셨다면 사용해보는걸 추천드립니다.

 

정리

Nullable한 상황에서는 Null 체크를 항상 생각해야 하고 이를 지원해주는 Utils 라이브러리나 Java에서 지원하는 Optional 등을 활용하면 좋다. 

 

반응형