본문 바로가기

이슈

[트러블슈팅]java.lang.NullPointerException: Cannot invoke "java.util.List.stream()" because "this.items" is null

커머스 시스템에서 고객의 장바구니에 아이템을 넣는 서비스를 제작중 발생한 이슈에 대해서 작성해보겠습니다.

java.lang.NullPointerException: Cannot invoke "java.util.List.stream()" because "this.items" is null

 

문제확인

장바구니에 데이터를 상품의 데이터를 넣으려 하는데 잔여 수 보다 적은값을 입력했음에도, 정상적으로 동작하지 않고

NullPointerException 에러가 발생하였습니다.

[ 전자 제품 카테고리 ] 원하시는 상품 ID를 입력하세요.
상품 ID = 1 | 상품 이름 = Galaxy S25 | 상품 가격 = 1,200,000 | 잔여 갯수 = 100
상품 ID = 2 | 상품 이름 = iPhone 16 | 상품 가격 = 1,350,000 | 잔여 갯수 = 50
상품 ID = 3 | 상품 이름 = MacBook Pro | 상품 가격 = 2,400,000 | 잔여 갯수 = 100
상품 ID = 4 | 상품 이름 = AirPods Pro | 상품 가격 = 350,000 | 잔여 갯수 = 100
0 -> 뒤로가기
==================================
2
선택하신 상품을 장바구니에 넣을까요? 0: 뒤로가기 그외 숫자 : 장바구니에 넣을 숫자.
20
에러 발생. 다시 시도 해 주세요 = java.lang.NullPointerException: Cannot invoke "java.util.List.stream()" because "this.items" is null

 

private void shoppingProcess() {
        showProductCategory();
        try {
            Optional<Product> selectedProduct = selectProduct();
            selectedProduct.ifPresent(product -> {
                System.out.println("선택하신 상품을 장바구니에 넣을까요? 0: 뒤로가기 | 그외 숫자 : 장바구니에 넣을 숫자.");
                int quantity = sc.nextInt();
                if (quantity == 0){
                    System.out.println("제품 추가 취소");
                    return;
                }
                //올바른 갯수를 입력했는지 확인
                product.checkIsValidQuantity(quantity);
                // 고객이 들고있는 카트에 아이템 추가
                customer.cart.addItemToCart(product.getId(),product.getQuantity(),product.getName(),product.getPrice());
            });
        }catch (Exception e) {
            System.out.println("에러 발생. 다시 시도 해 주세요 = " + e);
        }
    }

문제가 되는 메서드는 

1. checkIsValidQuantity

2. addItemToCart 

두 메서드 중 하나라고 추측하고 추적을 시작하였습니다. 

 

해결과정

원인파악

1. checkIsValidQuantity 메서드를 먼저 보면 큰 로직없이 단순 수 비교 후 에러를 던지는 로직이고 기존 잔여량보다 많은 수를 입력시 해당 메서드에서 에러가 잘 발생하는것을 확인하여서, 문제가 없다고 판단하였습니다.

public void checkIsValidQuantity(int quantity) {
        if(this.quantity < quantity) {
            throw new IllegalArgumentException("현재 재고 수량보다 많은 수가 입력 되었습니다.");
        }
    }

 

2. addItemToCart 메서드를 살펴보면 findItemByProductId 을 옵셔널로 받아서 잘 nullpoint를 잘 방지했다고 생각을 했습니다.

 public void addItemToCart(String productId, int quantity , String productName , int productPrice) {
        //이미 저장된 데이터가 있는지 확인
        Optional<CartItem> isCartItem = findItemByProductId(productId);
        isCartItem.ifPresentOrElse(item -> {
            // 있으면 기존 카트에 갯수만 추가.
            // 새로운 객체 생성 X
            item.manageProductQuantity(quantity);
        }, //없으면 새로운 카트 아이템 추가
                () -> items.add(new CartItem(productId,productName,productPrice,quantity)));

        System.out.println("장바구니 추가 완료!");
    }

그러나 에러 메세지를 자세히 살펴보면 Cannot invoke "java.util.List.stream()"because "this.items" is null

 

items 이 null이기 때문에 stream을 적용할 수 없다고 나옵니다. 그럼 findItemByProductId 안을 살펴보면

private Optional<CartItem> findItemByProductId(String productId) {
    return items.stream().filter(i -> productId.equals(i.getProductId())).findFirst();
}

 

아 생각을 해보니 지금 고객은 처음 입장한 상태이고 카트에는 아무것도 없는데 items를 stream을 시도하려고해서 발생한 이슈구나..

아무것도 없으니 당연히 할 수 없지..

원인 수정

지금 코드를보면 변수를 선언만 해주고 실제로 생성자를 통해 만들어 주고있지 않다.

private final List<CartItem> items;

기본적으로 컬랙션의 경우 바로 객체를 필드에서 만들어 주도록 하자.

private final List<CartItem> items = new ArrayList<>();

 

결과

이젠 정상적으로 동작하는것을 확인 할 수 있었다!!

[ 주방 용품 카테고리 ] 원하시는 상품 ID를 입력하세요.
상품 ID = 17 | 상품 이름 = 반찬통 | 상품 가격 = 5,500 | 잔여 갯수 = 1
상품 ID = 18 | 상품 이름 = 트레이 세트 | 상품 가격 = 10,000 | 잔여 갯수 = 2
상품 ID = 19 | 상품 이름 = 바겐슈타이거 후라이펜 | 상품 가격 = 25,000 | 잔여 갯수 = 5
상품 ID = 20 | 상품 이름 = 바겐슈타이거 국자 | 상품 가격 = 13,500 | 잔여 갯수 = 10
0 -> 뒤로가기
==================================
18
선택하신 상품을 장바구니에 넣을까요? 0: 뒤로가기 | 그외 숫자 : 장바구니에 넣을 숫자.
1
장바구니 추가 완료!

 

 

이번 이슈를 통해 NullPointerException은 단순히 “값이 없다”가 아니라, “객체 자체가 존재하지 않는다”는 의미라는 점을 다시 한 번 체감했다.
장바구니에 아직 아무 상품도 담지 않은 상태는 List가 비어 있는 상태이지, List 자체가 null이어서는 안 된다는 사실을 간과하고 있었다.