KT에이블스쿨 7기

[KT AIVLE School 7기] Spring Framework(3)

CodeForWelfare 2025. 6. 24. 10:48

1. 컴포넌트 스캔과 어노테이션

스프링은 설정 파일 없이도 어노테이션을 기반으로 객체를 자동 등록할 수 있도록 컴포넌트 스캔(Component Scan) 기능을 제공합니다. 스프링 컨테이너는 특정 패키지를 스캔하여 @Component, @Service, @Controller, @Repository 등의 어노테이션이 붙은 클래스를 자동으로 Bean으로 등록합니다.

주요 어노테이션

어노테이션설명

@Component 일반 컴포넌트로, 빈으로 등록됩니다.
@Service 비즈니스 로직을 수행하는 서비스 클래스에 사용됩니다.
@Repository DAO 계층에 사용되며, 데이터 접근 예외를 Spring의 예외로 변환합니다.
@Controller 웹 요청을 처리하는 컨트롤러 클래스에 사용됩니다.
@Configuration Java 기반 설정 클래스에 사용되며, 내부에 @Bean 메서드를 정의할 수 있습니다.
@Bean 수동으로 객체를 생성하여 빈으로 등록할 때 사용됩니다.

예시

@Component
public class GreetingComponent {
    public String greet() {
        return "안녕하세요!";
    }
}

@Service
public class GreetingService {
    private final GreetingComponent greetingComponent;

    @Autowired
    public GreetingService(GreetingComponent greetingComponent) {
        this.greetingComponent = greetingComponent;
    }

    public void sayHello() {
        System.out.println(greetingComponent.greet());
    }
}

스프링 부트 프로젝트에서는 @SpringBootApplication 내부에 @ComponentScan이 포함되어 있어, 기본적으로 같은 패키지 이하에 위치한 컴포넌트를 자동 등록합니다.


2. AOP - 관점 지향 프로그래밍

AOP(Aspect Oriented Programming)는 핵심 로직과 부가 기능(로깅, 트랜잭션, 보안 등)을 분리하여 개발할 수 있도록 도와주는 프로그래밍 기법입니다. 중복된 코드 없이 공통 기능을 분리하여 코드의 재사용성과 유지보수성을 높입니다.

AOP 핵심 개념

용어 설명
Aspect 공통 관심사를 모듈화한 것 (예: 로깅 기능)
JoinPoint Advice가 적용되는 지점 (보통 메서드 실행 시점)
Pointcut JoinPoint를 선별하는 표현식
Advice 실제 수행될 공통 기능 코드
Weaving Advice를 실제 객체에 적용하는 과정

Advice 유형

유형 설명
@Before 메서드 실행 전 수행
@After 메서드 실행 후 수행
@AfterReturning 메서드 정상 종료 후 수행
@AfterThrowing 예외 발생 시 수행
@Around 메서드 실행 전/후 모두 수행하며 흐름 제어 가능

AOP 적용 예시

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        System.out.println("[Before] " + joinPoint.getSignature());
    }

    @AfterReturning(value = "execution(* com.example.service.*.*(..))", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("[AfterReturning] Result: " + result);
    }

    @Around("execution(* com.example.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("[Around] 시작");
        Object result = joinPoint.proceed();
        System.out.println("[Around] 종료");
        return result;
    }
}

스프링 AOP는 기본적으로 프록시 기반 AOP를 제공합니다. 클래스 기반(CGLIB) 혹은 인터페이스 기반(JDK Proxy) 프록시가 사용됩니다.


3. 트랜잭션 관리

트랜잭션(Transaction)은 데이터베이스 작업을 하나의 작업 단위로 묶어 일관성을 보장하기 위한 기능입니다. 스프링은 선언적 트랜잭션 처리를 지원하며, @Transactional 어노테이션을 통해 쉽게 구현할 수 있습니다.

주요 설정 옵션

옵션 설명
propagation 트랜잭션 전파 방식 (REQUIRED, REQUIRES_NEW 등)
isolation 트랜잭션 격리 수준 (READ_COMMITTED, SERIALIZABLE 등)
rollbackFor 특정 예외 발생 시 롤백 처리 지정

트랜잭션 예시

@Service
public class OrderService {

    @Transactional(rollbackFor = Exception.class)
    public void processOrder(Order order) {
        orderRepository.save(order);
        paymentService.pay(order);
    }
}

스프링 트랜잭션 관리 기능은 JDBC, JPA, Hibernate 등 다양한 기술과 통합됩니다. 트랜잭션 실패 시 롤백 처리가 자동으로 수행됩니다.


4. 예외 처리

스프링에서는 일관된 예외 처리를 위해 @ControllerAdvice@ExceptionHandler를 제공합니다. 이를 활용하면 전역에서 발생하는 예외를 일괄적으로 처리할 수 있습니다.

예외 처리 예시

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
        return ResponseEntity.badRequest().body("잘못된 요청입니다: " + ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("서버 오류 발생: " + ex.getMessage());
    }
}

사용자 정의 예외 예시

public class NotFoundException extends RuntimeException {
    public NotFoundException(String message) {
        super(message);
    }
}
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<String> handleNotFound(NotFoundException ex) {
    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}

스프링의 예외 처리 구조는 클라이언트와의 명확한 의사소통뿐만 아니라, 개발자에게도 로그 추적 및 디버깅에 매우 유용합니다.


9. 스프링 MVC 구조

스프링 MVC는 웹 애플리케이션 개발을 위한 Model-View-Controller 패턴을 기반으로 한 웹 프레임워크입니다. 각 계층의 역할이 명확하게 분리되어 있어 유지보수가 용이하고, 다양한 뷰 기술과도 유연하게 통합됩니다.

스프링 MVC 흐름

  1. 클라이언트가 요청을 보냄
  2. DispatcherServlet이 요청을 받아 처리 시작
  3. HandlerMapping이 해당 요청을 처리할 컨트롤러를 찾음
  4. 해당 컨트롤러가 요청을 처리하고 Model과 View 이름 반환
  5. ViewResolver가 View 이름에 해당하는 실제 View를 찾아 응답 생성
  6. DispatcherServlet이 최종적으로 클라이언트에 응답

주요 구성 요소

구성요소설명

@Controller 사용자의 요청을 처리하는 클래스
@RequestMapping URL 요청과 컨트롤러 메서드를 매핑
Model View로 데이터를 전달하기 위한 객체
ViewResolver 논리적 뷰 이름을 실제 JSP, Thymeleaf 등으로 변환

예시

@Controller
@RequestMapping("/greeting")
public class GreetingController {

    @GetMapping
    public String greet(Model model) {
        model.addAttribute("message", "안녕하세요!");
        return "greet"; // greet.jsp or greet.html
    }
}

스프링 MVC는 RESTful 웹서비스를 구현할 수 있도록 @RestController, @ResponseBody, @RequestBody 등 다양한 기능도 함께 제공합니다.