콘솔 기반의 커머스 시스템을 만드는 작업을 하고 있습니다. 

그러던중 조건을 만족하는 상품 목록만 출력하도록하는 기능을 구현해야했습니다. 

처음에 작성한 코드는 다음과 같습니다. 

int getProductsSize(Predicate<Product> condition) {
	return (int) products.stream().filter(condition).count(); 
}

getProductsSize(p -> p.getPrice() > 1_000_000); 
getProductsSize(p -> p.getPrice() <= 1_000_000); getProductsSize(p -> true); // 전체

 

이러한 방식으로 코드를 작성해도 괜찮을지 궁금해졌습니다. 

이를 개선한다면 다음과 같이 코드를 작성해야겠다고 생각했습니다. 

// 전부 출력 
int getExpensiveProductsSize() { ... } 
// 100만원 초과 
int getCheapProductsSize() { ... } 
// 100만원 이하 
int getAllProductsSize() { ... }

 

현 상황의 작은 프로젝트에서는 사실 두 방식 모두 큰 차이가 없을 수 있습니다.

하지만 각 방식이 어떤 차이가 있고 어떤 상황에서 쓰이면 좋을지 이유를 알고 고르는 것이 좋겠다는 생각에 비교해보고자 합니다. 


1. 람다를 파라미터로 받는 경우 

 

✅ 장점

  • 유연성: 원하는 조건을 즉석에서 정의할 수 있어 메서드 하나로 무한히 다양한 경우를 처리 가능.
  • 중복 제거: 메서드 로직(스트림 처리 등)은 한 곳에만 존재 → 유지보수 용이.
  • 확장성: 새로운 조건이 생겨도 메서드를 새로 만들 필요 없음. 그냥 람다만 전달.

❌ 단점

  • 가독성↓: 조건이 복잡해질수록 호출부가 지저분해질 수 있음.
    (특히 조건이 길면 getProductsSize(p -> { ... })가 한눈에 잘 안 읽힘)
  • IDE 자동완성 활용성↓: "가격 100만원 이상 개수" 같은 도메인 용어가 바로 보이지 않음 → 의미 전달력이 약해짐.
  • 재사용성↓: 같은 조건을 여러 군데서 쓴다면 매번 같은 람다를 작성해야 함.

📌 적합한 상황

  • 조건이 다양하게 바뀌는 경우
    → 예: 가격 10만원 이상, 100만원 이상, 재고 10개 이하, 특정 브랜드 상품 등.
  • 일회성 조건을 처리할 때
    → 굳이 메서드로 이름을 만들 필요가 없고, 호출부에서 바로 정의 가능.
  • 범용 유틸리티성 코드를 만들 때
    → 라이브러리, 툴킷 같은 곳에서는 보통 조건을 전달받는 방식이 선호됨.
  • 학습/연습 단계
    → 스트림, 람다, 함수형 인터페이스 개념을 익히기에 최적.

 

2. 메서드를 조건별로 분리하는 경우

 

✅ 장점

  • 가독성↑: 호출부에서 의미가 명확 → getExpensiveProductsSize()만 봐도 의도 이해 가능.
  • 도메인 표현력↑: "비싼 상품 개수"라는 개념 자체가 메서드 이름으로 문서화됨.
  • 중복 람다 입력 방지: 호출하는 사람은 조건을 몰라도 됨.

❌ 단점

  • 유연성↓: 조건이 바뀌면 메서드를 계속 추가해야 함.
  • 중복 코드 가능성↑: 필터 로직이 여러 메서드에 분산 → 유지보수 시 리스크.
  • 확장성↓: 조건이 많아질수록 메서드가 폭발적으로 늘어남.

 

📌 적합한 상황

  • 조건이 도메인 개념으로 자리 잡을 때
    → “고가 상품 개수”, “재고 부족 상품 개수”, “VIP 고객 수” 같은 건 시스템에서 자주 쓰이는 의미 있는 비즈니스 용어.
  • 팀 단위 협업
    → getExpensiveProductsSize()처럼 이름만 봐도 바로 이해 가능 → 가독성, 커뮤니케이션 효율 ↑.
  • 조건이 바뀔 가능성이 적은 경우
    → 예: “회원 등급별 분류”처럼 도메인 규칙이 명확히 정해져 있는 경우.
  • 테스트/문서화가 중요한 경우
    → 메서드 이름 자체가 문서 역할을 하므로 유지보수 편리.

3. 어느 쪽이 더 좋은가? (판단 기준)

  • 조건이 자주 바뀌거나 다양하다람다 파라미터 방식
    (범용적이고 재사용 가능한 로직을 만드는 것이 목표일 때)
  • 조건이 도메인적으로 중요한 의미를 가진다메서드 분리 방식
    (예: “VIP 고객 수”, “재고 부족 상품 수” 같은 개념은 메서드 이름으로 표현하는 게 더 직관적임)

정리하자면

    • 조건이 비즈니스 의미(도메인 용어)를 가지면 → 메서드 분리
    • 조건이 단순 필터링 로직이고 다양하게 변할 수 있으면 → 람다 전달

 

혹은 다음과 같이 절충하여 사용할 수도 있다.

  • getProductsSize(Predicate<Product> condition) 같은 범용 메서드 하나는 기본 제공.
  • 자주 쓰이거나 도메인적으로 중요한 조건은 별도 메서드로 감싸서 제공.
int getExpensiveProductsSize() { 
	return getProductsSize(p -> p.getPrice() > 1_000_000); 
}

+ Recent posts