오픈을 한 달 앞둔 시점, 기획팀 혹은 고객사로부터 이런 피드백을 받은 경험이 한 번쯤은 있을 것이다.

 "이거 우리가 원했던 기능이 아닌데요????"

이러한 비극은 왜 터지는 것일까? 이는 우리가 여전히 요구사항이 변하지 않을 것이라 가정하는 워터폴(Waterfall)속에서 개발하고 있기 때문이다. 이번 포스팅에서는 워터폴의 한계와 이를 극복하기 위한 에자일(Agile)의 본질에 대해 정리해본다.

 

https://hsunnystory.tistory.com/260

 

[Software Enginnering] 워터폴(Waterfall) 방법론의 명과 암

대형 SI 프로젝트나 공공기관 차세대 시스템 구축에 투입되면, 어김없이 거대한 엑셀 파일 두 개를 마주하게 된다. 수개월의 일정이 빼곡히 적힌 WBS와 수백 페이지에 달하는 요구사항 정의서다.

hsunnystory.tistory.com

 

1. 에자일(Agile): 방법론이 아닌 마인드셋

에자일을 지라(Jira)를 쓰고, 아침마다 스탠드업 미팅을 하는 도구나 프로세스로 오해하는 경우가 많다. 하지만 에자일의 본질은 기법이 아니라 변화를 수용하는 마인드셋이다.

 

애자일은 소프트웨어 개발의 불확실성을 인정한다. 처음부터 완벽한 설계는 없으므로, 동작하는 가장 작은 단위의 소프트웨어를 빠르게 만들어 고객에게 전달하고, 피드백을 받아 지속적으로 개선해 나가는 것이 핵심이다.

 

이러한 애자일의 철학은 개발자가 작성하는 코드, 그리고 객체지향 설계의 원리와도 정확히 맞닿아 있다. 변화에 유연하게 대응하기 위해 우리는 코드 레벨에서 어떤 고민을 해야 할까?

 

2. 변화를 대하는 코드의 자세

워터폴 방식처럼 요구사항은 고정되어 있다고 가정하는 코드는 확장에 닫혀 있어 작은 변경에도 시스템 전체가 흔들린다. 반면, 애자일 방식의 코드는 다형성과 OCP를 활용해 변화를 부드럽게 수용한다.

 

결제 시스템의 알림 기능을 예로 들어보자. 초기 요구사항은 이메일 알림 하나 였다.

 

[Bad Code : 워터풀 방식의 경직된 설계]

새로운 요구사항(SMS, 카카오톡 알림 등)이 추가될 때마다 핵심 비즈니스 로직인 OrderSerivce의 코드를 직접 수정해야 한다. 이는 변경에 취약하고 테스트하기 어려운 구조다.

 

// 핵심 비즈니스 로직이 구체 클래스에 강하게 결합되어 있음 (OCP 위반)
public class OrderService {
    private EmailSender emailSender = new EmailSender(); // 구체 클래스 의존

    public void completeOrder(Order order) {
        // 1. 주문 처리 로직
        processPayment(order);
        
        // 2. 알림 발송 (요구사항이 변경되면 이곳을 직접 수정해야 함)
        emailSender.send(order.getUserEmail(), "주문이 완료되었습니다.");
        // 만약 SMS 알림이 추가된다면? if문이 추가되고 코드가 뚱뚱해진다.
    }
}

 

[Good Code: 에자일 방식의 유연한 설계]

에자일 환경에서는 요구사항이 언제든 변할 수 있음을 전제한다. 따라서 인터페이스에 의존하도록 설계하여, 새로운 알림 수단이 추가되더라도 기존 코드를 수정하지 안하고 확장만으로 대응할 수 있게 한다.

 

// 변화를 수용하는 인터페이스 설계
public interface NotificationSender {
    void send(User user, String message);
}

public class EmailSender implements NotificationSender { /* 구현 생략 */ }
public class SmsSender implements NotificationSender { /* 구현 생략 */ }

// 핵심 비즈니스 로직 (수정에 닫혀 있고 확장에 열려 있음 - OCP 준수)
@Service
@RequiredArgsConstructor
public class OrderService {
    
    // 다형성을 활용하여 런타임에 전략을 주입받음
    private final NotificationSender notificationSender; 

    public void completeOrder(Order order) {
        // 1. 주문 처리 로직
        processPayment(order);
        
        // 2. 알림 발송 (알림의 종류가 SMS든 카카오톡이든 OrderService는 변경되지 않음)
        notificationSender.send(order.getUser(), "주문이 완료되었습니다.");
    }
}

 

결국 코드를 유연하게 짜는 객체지향 설계와 일하는 방식을 유연하게 가져가는 애자일은 변화에 대한 비용을 최소화 한다는 동일한 본질을 공유한다.

 

3. IT기업에서 애자일을 중요시 하는 이유

실무에서 비즈니스 환경은 매일 바뀐다. 경쟁사는 새로운 기능을 출시하고, 유저의 트렌드는 급변한다. 이런 상황에서 6개월 뒤에나 결과를 볼 수 있는 워터폴 방식은 비즈니스의 사형선고나 다름 없다.

 

리스크 최소화

6개월간 개발해서 실패하는 것보다, 2주 만에 핵심 기능만 배포해 보고 고객 반응이 없으면 빠르게 방향을 트는 것이 훨씬 안전하다.

 

지속적 가치 전달

MSA나 CI/CD 파이프라인 같은 현대적인 백엔드 인프라 기술들은 모두 하루에도 몇 번씩 안전하고 빠르게 배포한다는 애자일 철학을 기술적으로 뒷받침하기 위해 탄생한 것이다.

 

결론

애자일은 개발을 빨리하는 방법이 아니다. 올바른 방향으로 개발하고 있는지 지속적으로 확인하는 방법이다.

 

 

 

 

 

 

 

 

+ Recent posts