ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2025.05.07 - NPE 굴레
    업무 2025. 5. 9. 09:27

    이번 프로젝트를 마무리하면서 제일 흔하게 발생하는 에러는 NPE였다

     

     

     

     

     

    NPE 방어

    1. equals 사용 주의 : equals 앞에 명확히 Null 값이 아닌 값을 넣기

    if (isTdrSaveY.equals("N")) {
        return true;
    } 
    
    if ("N".equals(isTdrSaveYn)) {
        return true;
    }

     

     

    2. Vo 객체 생성

    if (tdrStat == null) {
        tdrStat = new TdrStatVo();
    }
                		
    if (exQR.getTdrInfo().isTdrType()) {
    	tdrStat.setStatMessage("정상결제");
    } else {
        tdrStat.setStatMessage("정상취소");
    }

    결제와 반품을 함께 타는 로직인데 결제할 때는 Vo가 초기화/생성되니 NPE가 없었고 반품 시 Vo 초기화/생성 로직이 없어 NPE가 발생했다

    따라서 앞부분에서 VO의 존재 여부를 확인하는 로직을 넣어주면 된다

     

     

    3. 삼항연산자

    if (orgTdr == null) {
        tdr.setCrcoCd(StringUtils.isNotBlank(rspn.getCardCo()) ? rspn.getCardCo() : exQR.getCardPrefixVo().getCrcoCd());
    } else {
        // 반품일 경우
        tdr.setCrcoCd(StringUtils.isNotBlank(rspn.getCardCo()) ? rspn.getCardCo() : orgTdr.getCrcoCd());
    }

     

     

    4. java.util.Optional

    - Optional : null이 될 수도 있는 객체를 감싸고 있는 래퍼 클래스

    int lth = Optional.ofNullable(getText()).map(String::length).orElse(0);

     

     

     

    이대로 수정하다보니 StringUtil 과 StringUtils 와 같은 라이브러리를 혼합해서 사용했다

    두 개가 있다는 사실도 모르고 일단 import해서 사용하다 보니...

    나중에 차장님이 수정하라고 하셔서 그 부분도 찾아봤다

     

     

     

     

     

     

    StringUtil vs StringUtils

    package ch.qos.logback.core.util;
    import ch.qos.logback.core.CoreConstants;
    
    /**
     * @since 1.5.0
     */
    public class StringUtil {
    
        public static String nullStringToEmpty(String input) {
            if (input != null)
                return input;
            else
                return CoreConstants.EMPTY_STRING;
        }
        
        ...
    }

     

    package org.apache.commons.lang3;
    
    import java.io.UnsupportedEncodingException;
    import java.nio.charset.Charset;
    import java.text.Normalizer;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Locale;
    import java.util.Objects;
    import java.util.Set;
    import java.util.function.Supplier;
    import java.util.regex.Pattern;
    
    import org.apache.commons.lang3.function.Suppliers;
    import org.apache.commons.lang3.function.ToBooleanBiFunction;
    import org.apache.commons.lang3.stream.LangCollectors;
    import org.apache.commons.lang3.stream.Streams;
    
    //@Immutable
    public class StringUtils {
    
        /**
         * A String for a space character.
         *
         * @since 3.2
         */
        public static final String SPACE = " ";
    
        ...
    }
    package org.springframework.util;
    
    import java.io.ByteArrayOutputStream;
    import java.nio.charset.Charset;
    import java.util.ArrayDeque;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Deque;
    import java.util.Enumeration;
    import java.util.Iterator;
    import java.util.LinkedHashSet;
    import java.util.List;
    import java.util.Locale;
    import java.util.Properties;
    import java.util.Set;
    import java.util.StringJoiner;
    import java.util.StringTokenizer;
    import java.util.TimeZone;
    import java.util.stream.Collectors;
    
    import org.springframework.lang.Nullable;
    
    public abstract class StringUtils {
    
    	private static final String[] EMPTY_STRING_ARRAY = {};
        
        ...
    }

    패키지 구조

    • StringUtil : package ch.qos.logback.core.util;
    • StringUtils :
      • package org.apache.commons.lang3;
      • package org.springframework.util;

     

    어디서 제공하는 라이브러리인가가 제일 큰 차이겠지만 apache StringUtils가 제일 많은 메서드를 제공하고 있었고 이번 프로젝트에서도 apache StringUtils를 위주로 사용하고 있었다

    springframework에서 제공하는 StringUtils도 혼합되어 사용되고 있지만 나 같이 생각 없이 import 해서 사용한 게 아닌가 싶은....

    springframework의 StringUtils은 별도의 설정 없이 바로 사용할 수 있다는 장점이 있지만 apache가 더 많은 기능을 제공하기 때문에 apache StringUtils로 통일하는 것도 좋아 보인다 

     

     

    그리고 org.apache.commons.lang 같은 패키지에 있는 ObjectUtils의 사용도 많이 했다

    두 개의 이름에서부터 차이가 나지만 StringUtils는 String에 특화된, ObjectUtils는 Object에 특화된 기능을 제공한다

    1. StringUtils
    org.apache.commons.lang.StringUtils
    자바의 String 클래스가 제공하는 문자열 관련 기능을 강화한 클래스
    
    2. ObjectUtils
    org.apache.commons.lang.ObjectUtils
    모든 Object에 대응 가능하다

     

     


    마지막으로 비슷해 보이는 StringUtils의 isEmpty와 isBlank 차이점

    1. StringUtils.isEmpty
    - null이나 ("")이면 true 값을 반환
    
    2. StringUtils. isBlank
    - (" ") 이거나 공백문자("") 혹은 null이면 true를 반환

    isBlank의 경우 "   "까지 잡아준다

    728x90

    '업무' 카테고리의 다른 글

    20250207  (0) 2025.02.08
    Enum, Java Stream API  (1) 2025.01.21
    pull patch 한 번에 뜰 때, commit 오류  (0) 2025.01.13
Designed by Tistory.