ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Framework 시리즈 10화 – 실무 예제: 간단한 DI 기반 계산기 시스템 구현
    기술과 산업/언어 및 프레임워크 2025. 5. 29. 16:30
    728x90

    스프링 핵심 개념인 @Component, @Autowired, @Value, @EventListener 등을 실제 프로젝트에 통합하여 DI 기반 계산기 시스템을 구현해봅니다. 학습한 이론을 코드로 연결하고 구조적으로 정리합니다.

    프로젝트 개요

    우리는 간단한 계산기 시스템을 만들 겁니다.
    사용자가 두 수와 연산자(+, -, *, /)를 입력하면, 계산을 수행하고 결과를 출력하며, 이벤트 리스너를 통해 로그 또는 통계 처리를 따로 분리합니다.


    📁 프로젝트 구조

    src/
     └── main/
         ├── java/
         │   └── com.example.calculator/
         │        ├── AppConfig.java
         │        ├── Calculator.java
         │        ├── OperatorService.java
         │        ├── ResultPrinter.java
         │        ├── CalculationEvent.java
         │        ├── CalculationEventListener.java
         │        └── CalculatorApp.java
         └── resources/
             └── application.properties
    

    1. 설정값 주입 – application.properties

    calculator.name=스프링 계산기
    

    2. OperatorService – 연산 수행 컴포넌트

    @Component
    public class OperatorService {
    
        public double calculate(double a, double b, String op) {
            return switch (op) {
                case "+" -> a + b;
                case "-" -> a - b;
                case "*" -> a * b;
                case "/" -> b != 0 ? a / b : 0;
                default -> throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
            };
        }
    }
    

    3. CalculationEvent – 이벤트 객체

    public class CalculationEvent {
        private final double a;
        private final double b;
        private final String operator;
        private final double result;
    
        public CalculationEvent(double a, double b, String operator, double result) {
            this.a = a;
            this.b = b;
            this.operator = operator;
            this.result = result;
        }
    
        // Getter 생략
    }
    

    4. Calculator – 주입 구조 구성

    @Component
    public class Calculator {
    
        private final OperatorService operatorService;
        private final ApplicationEventPublisher publisher;
    
        @Value("${calculator.name}")
        private String name;
    
        public Calculator(OperatorService operatorService, ApplicationEventPublisher publisher) {
            this.operatorService = operatorService;
            this.publisher = publisher;
        }
    
        public void calculate(double a, double b, String op) {
            System.out.println("[" + name + "] 연산 수행: " + a + " " + op + " " + b);
            double result = operatorService.calculate(a, b, op);
            publisher.publishEvent(new CalculationEvent(a, b, op, result));
        }
    }
    

    5. ResultPrinter – 이벤트 리스너를 통한 결과 처리

    @Component
    public class ResultPrinter {
    
        @EventListener
        public void handleResult(CalculationEvent event) {
            System.out.println("결과: " + event.getResult());
        }
    }
    

    6. AppConfig – 설정 클래스

    @Configuration
    @ComponentScan(basePackages = "com.example.calculator")
    public class AppConfig {}
    

    7. CalculatorApp – 실행 메인 클래스

    public class CalculatorApp {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            Calculator calculator = context.getBean(Calculator.class);
    
            calculator.calculate(5, 3, "+");
            calculator.calculate(10, 2, "/");
            calculator.calculate(7, 8, "*");
        }
    }
    

    실행 결과 예시

    [스프링 계산기] 연산 수행: 5.0 + 3.0
    결과: 8.0
    
    [스프링 계산기] 연산 수행: 10.0 / 2.0
    결과: 5.0
    
    [스프링 계산기] 연산 수행: 7.0 * 8.0
    결과: 56.0
    

    이 예제를 통해 확인한 개념 정리

    적용 기능 사용 위치

    DI 및 컴포넌트 주입 @Component, @Autowired, 생성자 주입
    외부 설정값 주입 @Value, application.properties
    ApplicationContext 구성 AnnotationConfigApplicationContext
    이벤트 퍼블리싱 ApplicationEventPublisher 사용
    이벤트 리스닝 @EventListener 로 결과 처리

    마무리 – 실전은 연결이다

    이전 회차까지 개별적으로 배운 기능들을 하나의 프로젝트로 통합해 보았습니다.
    의존성 주입, 설정 분리, 이벤트 처리 등은 개념 그 자체보다 서로 어떻게 연결되고 설계되는지가 실무 핵심입니다.

    이 계산기 프로젝트처럼 작고 명확한 구조를 설계하면서 핵심 요소를 조립해보면, 더 복잡한 서비스에서도 유사한 패턴으로 확장할 수 있습니다.


    다음 11화에서는 테스트 가능한 구조 만들기를 주제로, 이 프로젝트를 단위 테스트 및 통합 테스트 가능한 구조로 리팩토링하고, @TestConfiguration, @MockBean 등을 활용해 실전 테스트 전략을 소개할 예정입니다.

     

    728x90
Designed by Tistory.