개발자라면 한 번쯤은 if-else 문으로 가득한 클래스를 만들어본 적이 있을 겁니다.
하지만 시간이 지나고 코드가 커질수록, 우리는 더 깔끔하고 유연한 구조를 원하게 됩니다.
이번 포스팅에서 if-else 코드를 줄이면서 코드를 단순하고 유지보수에 유리한 구조로 변경하는 방법을 알아 보겠습니다.

if-else 지옥

간단한 예시부터 시작해보겠습니다.
당신은 배송 서비스를 개발 중이고, 현재는 도보, 트럭, 기차 세 가지 배송 수단을 지원하고 있습니다.

public class DeliveryService { 
    public void delivery (String deliveryType) { 
        if ("WALK".equals(deliveryType)) { 
            // 도보
         } else if ("TRUCK".equals(deliveryType)) { 
            // 트럭
         } else if ("TRAIN".equals(deliveryType)) { 
            // 기차
         } 
    } 
}

그런데 어느날 기획팀에서 이렇게 말합니다.
“배송수단 선박, 항공을 추가할 수 있을까요?”

이제 여러분의 클래스는 else if 블록이 계속 추가되며 점점 복잡해집니다.
처음에는 단순했던 로직이 어느새 거대한 조건 분기문으로 뒤덮이게 되죠.

if-else 방식의 문제점

  • 조건이 늘어날수록 로직이 복잡해지고 유지보수가 어려워짐
  • 새로운 타입이 생길 때마다 기존 코드를 수정해야 함 → OCP 위반
  • 테스트, 가독성, 확장성 모두 악화

이제는 if-else 지옥에서 벗어나 더 유연하고 확장 가능한 구조로 나아갈 때입니다.
바로, 전략 패턴(Strategy Pattern) 을 통해 말이죠.

전략 패턴으로 구조 개선하기

전략 패턴(Strategy Pattern)은 알고리즘(또는 행위)을 캡슐화하여 여러 개의 알고리즘을 상호 교환 가능하게 만들고, 실행 시점에 적절한 알고리즘을 선택할 수 있도록 하는 디자인 패턴입니다.

즉, “어떤 작업을 수행하는 방법(전략)을 클래스로 분리하고, 필요에 따라 해당 전략을 동적으로 바꿔가며 사용할 수 있게 하는 패턴” 입니다.

이를 통해 조건문 분기를 줄이고, 확장성과 유지보수성을 높일 수 있습니다.

1.전략 인터페이스 정의

public interface DeliveryStrategy {
    void deliver();
}

2.각 타입별 전략 클래스 구현

@Component("WALK")
public class WalkDeliveryStrategy implements DeliveryStrategy {
  @Override
  public void deliver() {
    System.out.println("도보로 배송합니다.");
  }
}

@Component("TRUCK")
public class TruckDeliveryStrategy implements DeliveryStrategy {
  @Override
  public void deliver() {
    System.out.println("트럭으로 배송합니다.");
  }
}

@Component("TRAIN")
public class TrainDeliveryStrategy implements DeliveryStrategy {
  @Override
  public void deliver() {
    System.out.println("기차로 배송합니다.");
  }
}

@Component("SHIP")
public class ShipDeliveryStrategy implements DeliveryStrategy {
    @Override
    public void deliver() {
        System.out.println("선박으로 배송합니다.");
    }
}

@Component("AIRPLANE")
public class AirplaneDeliveryStrategy implements DeliveryStrategy {
  @Override
  public void deliver() {
    System.out.println("항공으로 배송합니다.");
  }
}

3.전략을 직접 주입받아 사용하는 서비스 클래스

@Service
public class DeliveryService {
    
    private final Map<String, DeliveryStrategy> strategyMap;

    public DeliveryService(Map<String, DeliveryStrategy> strategyMap) {
        this.strategyMap = strategyMap;
    }

    public void deliver(String deliveryType) {
        DeliveryStrategy strategy = strategyMap.get(deliveryType);
        if (strategy == null) {
            throw new IllegalArgumentException("지원하지 않는 배송 타입: " + deliveryType);
        }
        strategy.deliver();
    }
}

전략 패턴 도입 전후 비교

항목 if-else 방식 전략 패턴 방식
유지보수 및 확장성 ❌ 새로운 조건 추가 시 기존 코드 수정 필요 ✅ 기존 코드는 그대로, 클래스만 추가하면 됨
가독성 ❌ 긴 조건문으로 인해 가독성 저하 ✅ 각 전략은 역할이 명확, 읽기 쉬움
테스트 용이성 ❌ 전체 조건 로직 묶여 있어 테스트 어려움 ✅ 전략별로 단위 테스트 가능

마무리

조건문은 개발 초기엔 빠르게 구현할 수 있는 좋은 수단이지만, 복잡도가 커지는 시스템에서는 유지보수의 큰 장애물이 될 수 있습니다.

전략 패턴은 단순한 디자인 패턴이지만, 적재적소에 적용했을 때 코드의 유연성과 확장성을 극적으로 개선할 수 있습니다.

더 이상 if-else 지옥에 갇히지 마세요. 전략 패턴으로 깔끔하고 유지보수 쉬운 코드를 만들어 보세요!