스프링 OOP
는 많이 봤는데 AOP
는 이번에 처음 알게 되어서 이 부분에 대해서 정리해보았습니다. 그리고 그 과정에서 스프링의 구조를 공부하기 시작하는 단계로 IoC Container
와 Bean
의 개념을 정리해보는 시간을 가졌습니다
핵심 기능과 부가 기능을 분리하여 더 깨끗하고 유지보수하기 쉬운 코드를 만드는 것이 AOP(Aspect-Oriented Programming)
의 주요 목적입니다. AOP
는 애플리케이션의 여러 부분에서 공통적으로 사용되는 부가 기능(로깅, 보안, 트랜잭션 관리 등)을 핵심 로직과 분리하여 코드를 깔끔하게 유지할 수 있도록 도와줍니다.
핵심 기능
부가 기능
로깅, 보안, 트랜잭션 관리와 같이 주요 목적 외에 필요하지만, 여러 곳에 반복되는 기능을 말합니다.
횡단 관심사
부가 기능이 여러 곳에서 반복적으로 사용될 때 이를 횡단 관심사라 부릅니다.
AOP는 핵심 기능과 횡단 관심사(부가 기능)를 분리하여 관리하는 프로그래밍 기법입니다. 이를 통해 부가 기능이 코드 전반에 퍼지지 않고 한 곳에서 관리됩니다.
1) Advice (어드바이스)
어드바이스는 실제로 실행되는 횡단 관심사입니다. 보통 아래와 같은 어노테이션을 사용하여 정의됩니다.
@Around
: 메소드 실행 전후에 수행@Before
: 메소드 실행 전에 수행@After
: 메소드 실행 후에 수행@AfterThrowing
: 예외 발생 후 수행@AfterReturning
: 메소드가 성공적으로 반환된 후에 수행2) PointCut (포인트컷)
어드바이스를 적용할 구체적인 지점을 정의합니다. 주로 아래와 같은 표현식을 사용합니다.
@execution
: 특정 메소드 실행@annotation
: 특정 어노테이션이 붙은 메소드 실행@within
: 특정 타입에 속한 모든 메소드 실행@this
: 특정 인터페이스를 구현한 프록시 객체@target
: 특정 타입의 대상 객체@args
: 특정 타입의 파라미터를 가지는 메소드 실행3) Target (타겟)
어드바이스가 적용될 객체입니다. 예를 들어, execution(* com.example.service.CourseService.*(..))
처럼 정의하여 CourseService 클래스에 속한 메소드들에 어드바이스를 적용할 수 있습니다.
4) JoinPoint (조인포인트)
어드바이스가 적용되는 실행 시점을 의미합니다.
5) Aspect (애스펙트)
어드바이스와 포인트컷을 결합한 모듈을 애스펙트라 합니다. 하나의 애스펙트는 여러 어드바이스를 포함할 수 있습니다.
JWT(JSON Web Token)는 클라이언트가 모든 요청에 JWT를 포함하여 서버에 전달하는 방식으로 동작합니다. 이를 통해 HTTP의 stateless(상태 비저장성)와 connectionless(연결 비유지성) 특성을 극복할 수 있습니다.
스프링에서는 Filter, ArgumentResolver, Controller로 이어지는 인증 흐름을 사용합니다.
Filter는 JWT를 확인하여 유효성을 검증하고,
ArgumentResolver는 인증된 사용자 정보를 컨트롤러로 전달합니다.
Controller는 실제 로직을 처리합니다
스프링에서는 ResponseEntity를 통해 HTTP 응답 상태 코드를 명확히 지정할 수 있습니다. 예를 들어, 성공적인 요청일 경우 200 OK
응답을 반환하거나, 실패 시 404 Not Found
또는 500 Internal Server Error
를 반환할 수 있습니다. 이를 통해 서버와 클라이언트 간에 명확한 통신이 가능해집니다.
스프링에서는 객체를 직접 생성하지 않고 IoC(Inversion of Control) 컨테이너가 이를 대신합니다. 예전에는 new
키워드를 사용하여 객체를 생성했지만, 스프링에서는 @Component
, @Service
, @RestController
등의 어노테이션을 통해 객체를 빈(Bean)으로 등록하고 IoC 컨테이너에서 이를 관리합니다.
@Component
가 붙은 클래스는 스프링이 관리하는 빈(Bean)입니다.
스프링 부트 애플리케이션이 실행되면, @SpringBootApplication
에 포함된 ComponentScan이 작동하여 빈들을 스캔하고 등록합니다.
물론 new로 객체를 생성할 수 있다. 하지만 그렇게 하면 DI가 되지 않으며, 여러 객체를 사용해야 할 때마다 new
를 반복해야 합니다. 이는 메모리 낭비를 초래할 수 있습니다. 대신 스프링은 하나의 빈을 생성하고 필요할 때마다 주입함으로써 메모리 효율성을 높입니다.
오늘 배운 내용을 정리하면, AOP를 통해 핵심 로직과 부가 기능을 분리하고, 스프링의 IoC 컨테이너를 활용하여 객체 관리의 효율성을 높이는 것이 중요하다는 점을 알 수 있었습니다. 스프링의 강력한 DI
기능과 AOP
는 유지보수성과 확장성을 높여 주기 때문에, 이러한 개념들을 잘 이해하고 사용하면 많이 도움이 될 것 같습니다.