Spring의 핵심 개념 4가지
IoC(Inversion of Control) : 객체의 생성 및 생명주기를 개발자가 직접 제어하지 않고, Spring 컨테이너가 대신 관리하는 구조.
이는 객체간 결합도를 낮추고 전체 애플리케이션의 유연성과 확장성을 높이는 중요한 기반이 됨
Bean : IoC 컨테이너가 관리하는 객체이다. Bean들은 XML, Java Config, 애너테이션 등의 방식으로 등록할 수 있다.
Spring이 제공하는 다양한 생명주기 훅을 통해 체계적으로 관리된다.
DI(Dependency Injection) : 객체 간 의존관계를 외부에서 주입하는 방식이다. 테스트 가능성 향상, 유연한 구현체 교체, 관심사 분리 등의 효과를 제공함. 특히 Spring은 생성자 주입을 중심으로 강력한 DI구성을 제공함.
AOP(Aspect Oriented Programming) : 트랜잭션 로깅, 보안 검사와 같은 횡단 관심사를 핵심 로직과 분리하여 관리할 수 있는 구조를 제공함. 코드의 모듈화, 가독성, 재사용성을 크게 향상시킨다
AOP(Aspect Oriented Programming)
관점 지향 프로그래밍
객체지향 프로그래밍(OOP)의 한계
객체지향 프로그래밍은 역할에 다라 책임을 분리하는 장점이 있지만, 모든 모듈에서 반복적으로 등장하는 로직들이 존재함 :
로깅, 트랜잭션 처리, 보안검사, 실행시간 측정
실제로 과제를 통해 공부할때도 직렬화 등에서 반복적인 코드가 등장했었다.
객제지향 프로그래밍만으로는 이 중복코드를 효과적으로 제거하기 어렵다고 함.
※ 트랜잭션?
트랜잭션(Transaction)이란 데이터를 처리하는 하나의 작업 단위를 말한다. 무슨 소리지..
DB에 A 데이터와 B 데이터를 두번에 걸쳐 각각 insert하는 작업을 하나의 트랜잭션으로 묶는다면,
A, B 데이터는 모두 DB에 저장되던지 아니면 둘 다 오류가 발생하여 DB에 반영되지 않아야함. (All or Nothing)
이런 처리를 위해 일반적으로 트랜잭션에는 commit, 또는 rollback이라는 기능이 있다.
commit은 모든 작업이 성공적으로 수행됐을 때 DB에 모두 반영하는것이고
rollback은 하나라도 실패했을 경우 이전에 성공한 작업들이 있다면 모두 포함하여 이전상태로 되돌리는것을 말함
아무튼 애플리케이션 전반에 걸쳐 트랜잭션 관련한 중복코드가 많~~이 생긴다면 어떻게 할까?
중복된 코드를 공통화해서 재사용 가능하도록 만들어야한다. 이를 AOP를 통해서 할 수 있다.
AOP(Aspect Oriented Programming, 관점지향 프로그래밍)은 핵심 비즈니스 로직과는 별개인 공통기능(횡단 관심사)을 하나의 모듈로 분리하여 관리할 수 있게 해주는 프로그래밍 패러다임임
핵심 개념 : 관심사의 분리(Separation of Concerns)
AOP를 적용하면 반복코드를 적는게 아니라 핵심로직에 미리 만든걸 자동으로 끼워넣는 방식으로 처리할 수 있음
횡단 관심사(Cross-Cutting Concern)
비즈니스 로직과는 직접적인 관련은 없지만 여러 계층 또는 컴포넌트에 걸쳐 반복적으로 나타나는 관심사.
각 클래스에서 이런 관심사를 직접 처리하면 중복을 유발하고 코드의 유지보수성을 크게 떨어트림
@Service // Annotation Config 방식 Bean 등록
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
public void join(Member member) { // 쪼인
long start = System.currentTimeMillis(); // 시작시간을 현재시간으로
try {
memberRepository.save(member); // 핵심로직
} finally { // catch없이 finally를 바로
long end = System.currentTimeMillis();
long time = end - start; // 걸린 시간같음
System.out.println("MemberService.join 실행시간 = " + time + "ms");
}
}
}
위 코드는 AOS 적용 전이다
핵심 로직과 부가 로직이 하나의 소스코드 파일에 섞여있다.
join() 메서드의 경우 핵심로직(memberRepository.save(member)) 외에도 실행시간 측정 코드가 섞여있다.
이러한 로직이 여러 메서드나 클래스에 반복되면 솔직히 어지러울 것 같다..
// 핵심 로직 클래스
@Service
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) { // 생성자
this.memberRepository = memberRepository;
}
public void join(member member) {
memberRepository.save(member); // 핵심 로직
}
}
// 공통 기능들
public class TimeTraceAspect {
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
try {
return joinPoint.proceed(); // 인자로 받은 대상의 메서드 실행
} finally {
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("실행시간 : " + joinPoint.getSignature() + time + "ms"); // ???
}
}
}
위 코드는 AOS 적용 후이다.
두번째 trace는 ProceedingJoinPoint의 메서드를 활용하는 것 같다.
뭐가 어쨌건 핵심 로직과 부가 로직을 이렇게 분리해서 사용하면 유지보수와 확장성이 크게 향상된다.
활용방식
Spring에선 @AspectJ 스타일의 AOP를 지원하며 AspectJ 전체기능 중 프록시 기반 AOP(Proxy-based AOP)를 기본 제공함.
@AspectJ가 AOS를 활용하는 데 쓰는 애너테이션이라는걸 기억하자....
- 프록시 기반의 AOP 구현체 : 대상 객체에 대한 프록시를 만들어 제공하며, 대상 객체(Target)를 감싸는 프록시는 서버 런타임시에 생성됨.
- 메서드 조인 포인트만 제공 : 핵심기능의 메서드가 호출되는 런타임 시점에만 부여기능을 적용가능.
Aspect : AOP에서 공통 관심 사항에 대한 기능
- 공통기능이 정의된 모듈
- 핵심로직과는 별도로 수행되는 횡단관심사(로깅, 트랜잭션)
Join Point : 어드바이스가 적용될 지점을 정의함
Advice : 공통기능과 적용시점을 정의함
- @Before, @After, @Around, @AfterReturning, @AfterThrowing 등..
Pointcut : Join Point중 Advice를 적용할 가능성이 있는 대상을 선별한것, 주로 표현식을 사용해 선별한다
Weaving : Advice를 핵심 비즈니스 로직에 적용한다.
AOP의 한계
- 프록시 기반 AOP는 메서드 수준에서만 작동함
- 클래스 내부의 메서드 호출(self-invocation)에는 적용되지 않는다
- 복잡한 AOP기능이 필요한 경우 AspectJ 컴파일 타임 위빙 등을 고려할 수 있다
스프링의 핵심 개념 4가지
IoC, Bean, DI, AOC
'Spring Boot' 카테고리의 다른 글
| Web Server와 Web Application Server, 그리고 내장 Tomcat에 대해 (0) | 2025.06.24 |
|---|---|
| Spring 연습예제 1 (0) | 2025.06.24 |
| Spring 핵심 개념 - Bean (1) | 2025.06.23 |
| Spring 핵심 개념 - IoC(Inversion of Control) (0) | 2025.06.19 |
| 테스트 주도 개발(TDD) (1) | 2025.06.19 |