AOP(Aspect Oriented Programming)란?
"관점 지향 프로그래밍"을 뜻하며 이는 소프트웨어 개발 방법 중 하나로,
자바와 같은 객체 지향 프로그래밍(OOP)을 더욱 OOP 답게 사용할 수 있도록 도와주는 역할을 한다.
프로그램의 특정 부분에 공통적으로 적용되어야 하는 기능이나 로직을 별도로 분리하여 관리하는 것을 목표로 하는 것!
프로그램에 여러 가지 기능이 있는데 그 각각의 기능마다 로그를 남기거나, 에러를 처리하거나, 보안을 체크하는 등의 공통적인 코드들이 있을 것이다. 이런 공통 기능을 "관점(Aspect)"으로 분리하여 관리하게 된다. 관점도 '핵심적인 관점' 과 '부가적인 관점'으로 나뉘는데, 전자는 주요 기능 부분을 말하고 후자는 공통적으로 발생하는 기능이나 문제, 즉 아까 말했던 로깅, 예외 처리, 트랜잭션 등을 말한다.
AOP는 이러한 부가적인 관점들을 코드로부터 분리하여 각 관심사를 독립적으로 구현하고,
필요한 곳에서 필요한 시점에 적용할 수 있도록 한다.
이는 코드의 재사용성을 높이고, 유지보수를 간편하게 만들어준다.
AOP를 적용해보자
aop 라이브러리 추가
implementation 'org.springframework.boot:spring-boot-starter-aop'
LoggerAspect 클래스 생성
package com.study.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.thymeleaf.util.StringUtils;
@Slf4j
@Aspect
@Component
public class LoggerAspect {
@Around("execution(* com.study.domain..*Controller.*(..)) || execution(* com.study.domain..*Service.*(..)) || exection(* com.study.domain..*Mapper.*(..))")
public Object printLong(ProceedingJoinPoint joinPoint) throws Throwable {
String name = joinPoint.getSignature().getDeclaringTypeName();
String type =
StringUtils.contains(name, "Controller") ? "Controller ===> " :
StringUtils.contains(name, "Service") ? "Service ===> " :
StringUtils.contains(name, "Mapper") ? "Mapper ===> " :
"";
log.debug(type + name + "." + joinPoint.getSignature().getName() + "()");
return joinPoint.proceed();
}
}
AOP 로그 출력 해보기
게시글 목록 페이지에 접속해보면 어떤 메서드가 실행이 됐는지 출력 되어진 것을 확인 할 수 있다!
트랜잭션(Transaction)이란?
트랜잭션이란 데이터베이스에서 여러 작업을 하나의 단위로 묶어 처리하는 개념이다.
즉, 여러 작업이 모두 성공하거나, 모두 실패하도록 보장하는 것.
이를 통해 데이터의 일관성과 무결성을 유지할 수 있다.
트랜잭션의 핵심 요소(기본 원칙)
- 원자성(Atomicity): 트랜잭션에 포함된 모든 작업이 하나의 작업 단위로 처리되어 처리 결과가 모두 동일해야 한다. 하나라도 실패하면 모든 작업 다 처음 상태로 되돌아가야 한다.
- 일관성(Consistency): 트랜잭션이 완료되면 데이터베이스가 일관된 상태를 유지해야 한다.
- 고립성(Isolation): 트랜잭션이 실행되는 동안 다른 트랜잭션이 끼어들지 못하도록 해야 한다. (독립적으로 처리)
- 지속성(Durability): 트랜잭션이 완료된 후에는 시스템 오류가 발생하더라도 그 결과가 지속적으로 유지되어야 한다. (독립적으로 처리)
예시
은행 시스템에서 돈을 이체하는 경우
1. A 계좌에서 100달러 출금
2. B 계좌로 100달러 입금
이 두 작업은 하나의 트랜잭션으로 묶여야 한다.
만약 A 계좌에서 돈을 출금한 후에 B 계좌로 입금하는 과정에서 오류가 발생하면,
입금은 당연히 안될뿐더러 출금한 돈도 원래 계좌로 되돌아가야 맞다.
이 두 작업을 하나의 트랜잭션으로 묶게 되면, 입금 과정에서 오류가 났을 때
트랜잭션 자체가 실패로 처리되어 모두 원상태로 되돌아가게 될 것이다.
이렇게 하면 데이터베이스의 일관성이 유지될 수 있다.
※ 트랜잭션 적용은 이전에 애플리케이션 전역에서 DB Transactional이 작동하도록 설정했지만,
일부 메서드에 적용 해놓은 선언적 트랜잭션(@Transactional)이 더 낫겠다는 판단하에
전역 트랜잭션은 스킵하고, 선언적 트랜잭션을 이용하여 남은 기능 구현할 예정
모든 코드는 아래 블로그를 참고합니다!
스프링 부트(Spring Boot) - AOP와 트랜잭션(Transaction)
이전 글에서는 애플리케이션에 인터셉터를 적용해서 사용자가 요청한 기능의 URI를 로그로 출력하는 방법을 알아보았습니다. 이번 글에서는 스프링의 핵심 기능 중 하나인 AOP를 애플리케이션에
congsong.tistory.com
'SpringBoot 게시판 프로젝트' 카테고리의 다른 글
스프링부트(SpringBoot) 게시판 만들기 (14) - 댓글 등록 기능 구현 (0) | 2024.07.19 |
---|---|
스프링부트(SpringBoot) 게시판 만들기 (12) - 페이징 & 검색 기능 구현 (0) | 2024.07.13 |
스프링부트(SpringBoot) 게시판 만들기 (10) - 인터셉터 로그 출력 (0) | 2024.07.07 |
스프링부트(SpringBoot) 게시판 만들기 (8) - Alert 메시지 처리하기 (4) | 2024.07.05 |
스프링부트(SpringBoot) 게시판 만들기 (7) - 게시글 삭제 기능 구현 (0) | 2024.07.05 |