-
Spring Framework 시리즈 10화 – 실무 예제: 간단한 DI 기반 계산기 시스템 구현기술과 산업/언어 및 프레임워크 2025. 5. 29. 16:30728x90
스프링 핵심 개념인 @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'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
Spring Boot 시리즈 38편 – Spring Boot에서 분산 트레이싱(Distributed Tracing) 적용하기 (1) 2025.05.29 Spring Boot 시리즈 37편 – 실시간 기능을 위한 WebSocket 연동 전략 (0) 2025.05.29 전자정부 표준프레임워크 시리즈 11화 – 공통 코드 관리 기능 완벽 정리: 코드 테이블, 조회 서비스, 화면 연동까지 (2) 2025.05.28 Spring Framework 시리즈 9화 – ApplicationContext의 역할과 이벤트 처리 구조 (0) 2025.05.28 NestJS 마스터 시리즈 16화. 인증 시스템 구현 (2) – AuthGuard와 역할 기반 인가 처리 (0) 2025.05.28