Java개발자로 전향한지 4년차가 되었습니다. 문득 저에 대해서 돌아보는 시간을 강제로 갖게되었고 난 개발자로써 살아가고 있는가에 대해서 궁금해졌습니다.
모든 소스는 github에 올려두었습니다.
나에게 질문을 해보았습니다.
기초는 튼튼한가?
자바에 대해서 얼만큼 알고 있지? Spring은?
블로그를 시작한지 한달이 조금 넘어가는 시점에서 다시 개념을 정리하고 복습하는 의미에서 되돌아가기로 하였습니다.
이번 글에서는 Spring Triangle 중 하나인 AOP에 대해서 정리해보겠습니다.
AOP란?
Aspect Oriented Programming
관점 지향 프로그램입니다. 처음에 이 말만 듣고 아... 그렇쿠나 무슨말이구나? 머리가 하얘졌었습니다.
간단하게 이해해보자!
기존의 코드는 수정하지 않고 새로운 기능을 추가할 수 있다! 우리가 가장 흔히 접할 수 있는 예제가 바로 @Transactional 입니다.
@Transactional이란?
db connect을 맺어 처리하는 로직들을 하나의 트랜잭션으로 관리하겠다는 의미입니다.
하나의 트랙잭션에서 N번의 CRUD가 일어날 때 commit은 하지 않는다. 모든 트랜잭션에 해당하는 로직이 끝나면 commit 명령어를 수행합니다.
Exception이 발생하면 처리했던 CRUD 모두 Rollback 처리합니다.
@Transactional을 아래와 같이 사용한다고 가정합니다.
@Transactional
public String sqlExcetion () {
mapper.select();
mapper.update();
mapper.insert();
mapper.delete();
}
내부적으로 처리는 아래와 같이 할 것입니다.
Connection connection = dataSource.getConnection();
try (connection) {
connection.setAutoCommit(false);
mapper.select();
mapper.update();
mapper.insert();
mapper.delete();
connection.commit();
} catch (SQLException e) {
connection.rollback();
}
기존의 로직 전 후에 새로운 기능이 생성되었습니다. 이것이 AOP 입니다.
사용 이유로는 예제 소스로 간단히 설명하자면 모든 CRUD를 처리할 떄마다 위와 같은 코드를 전부 붙히는 것은 관리도 힘들 뿐더러 중복코드도 생깁니다. 이를 방지하기 위해서 관점 지향 프로그래밍 AOP를 사용합니다.
AOP 방법은 컴파일, 바이트코드, 프록시 패턴이 있습니다.
@Transacional은 프록시 패턴을 사용한 것입니다.
다른 예제를 들어보겠습니다.
먼저 Controller, Service를 생성합니다.
@RestController
@RequiredArgsConstructor
public class AopController {
private final AopService aopService; // IoC
@GetMapping(value = "/aop")
public String aopGet() {
return aopService.run();
}
}
@Slf4j
@Service
public class AopService {
@LogExcution // AOP annotation
public String run() {
log.info("aop service run.");
return "aop_service_run";
}
}
Service에 AOP를 적용할 Annotation을 생성합니다.
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExcution {
}
@Slf4j
@Component
@Aspect
public class LogAspect {
@Around("@annotation(LogExcution)")
public Object logExcution(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object proceed = joinPoint.proceed();
stopWatch.stop();
log.info(stopWatch.prettyPrint());
return proceed;
}
}
실행해보겠습니다.
이처럼 간단하게 Annotation Aspect를 사용해서 AOP를 적용할 수도 있습니다.
결론
앞서 보여드린 두 가지 예제에서 기존의 소스는 전혀 변경되지 않고 새로운 기능을 추가할 수 있는 기능입니다!
다음 글에서는 PSA를 정리해보도록 하겠습니다.
'Study > spring' 카테고리의 다른 글
@Autowired vs @Inject vs @Resource (4) | 2021.02.18 |
---|---|
[Hateoas] Rest API를 구현해보자 (0) | 2020.12.17 |
Rest API란? (0) | 2020.12.16 |
Spring Triangle [IoC, AOP, PSA] - 3탄 PSA편 (0) | 2020.12.15 |
Spring Triangle [IoC, AOP, PSA] - 1편 IOC편 (0) | 2020.12.13 |