JUNIOR DEV EDUCATION · JAVA / SPRING

Spring AOP 튜토리얼
— DB 암복호화 적용 사례로 배우기

공통 기능을 비즈니스 로직에서 분리하는 방법과, 실무에서 암복호화 솔루션이 WAS에 통합되는 구조를 이해합니다.

이 문서 전체를 Markdown 형식으로 복사할 수 있습니다.

01AOP란 무엇인가

02AOP 주요 키워드 5가지

키워드의미예시
Aspect공통 기능을 모듈화한 단위암복호화 처리 모듈
Advice실제 수행되는 공통 기능 코드저장 전 암호화, 조회 후 복호화
JoinPoint공통 기능을 적용할 수 있는 지점메서드 호출 시점
Pointcut실제 적용할 대상을 지정하는 조건DAO 계층 메서드
WeavingAspect를 대상 코드에 결합하는 과정aspectjweaver가 담당

03AOP 주요 어노테이션 정리

어노테이션역할
@Aspect해당 클래스를 Aspect(공통 기능 모듈)로 선언
@Pointcut공통 기능을 적용할 대상 메서드 지정
@Before대상 메서드 실행 에 수행 (예: 저장 전 암호화)
@After대상 메서드 실행 에 수행 (성공/실패 무관)
@AfterReturning대상 메서드가 정상 반환된 후 수행 (예: 조회 후 복호화)
@AfterThrowing대상 메서드에서 예외 발생 시 수행 (예: 오류 로깅)
@Around대상 메서드 실행 전후를 모두 제어 — 가장 강력, 암복호화에 주로 사용
@EnableAspectJAutoProxy스프링에서 AOP 프록시 자동 생성 활성화 (설정 클래스에 선언)

04어노테이션별 사용 예제

1) @EnableAspectJAutoProxy — AOP 활성화 (설정)

설정 클래스에 한 번만 선언하면 스프링이 프록시를 자동 생성합니다. (Spring Boot는 기본 활성화)

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
    // 별도 내용 없이 선언만으로 AOP 활성화
}

2) @Aspect + @Pointcut — 공통 모듈과 적용 대상 선언

Pointcut을 메서드로 정의해두면 여러 Advice에서 이름으로 재사용할 수 있습니다.

@Aspect
@Component
public class DaoSecurityAspect {

    // com.example.dao 하위 모든 메서드를 대상으로 지정
    @Pointcut("execution(* com.example.dao..*(..))")
    public void daoLayer() {}
}

3) @Before — 메서드 실행 전 (저장 전 암호화)

@Before("daoLayer()")
public void encryptParams(JoinPoint jp) {
    // jp.getArgs()로 파라미터 접근 가능
    System.out.println("[Before] " + jp.getSignature().getName()
        + " 호출 전 — 파라미터 암호화");
}

4) @AfterReturning — 정상 반환 후 (조회 결과 복호화)

returning 속성으로 반환값을 파라미터로 받아 후처리할 수 있습니다.

@AfterReturning(pointcut = "daoLayer()", returning = "result")
public void decryptResult(JoinPoint jp, Object result) {
    System.out.println("[AfterReturning] 조회 결과 복호화: " + result);
}

5) @AfterThrowing — 예외 발생 시 (오류 로깅)

throwing 속성으로 발생한 예외 객체를 받을 수 있습니다.

@AfterThrowing(pointcut = "daoLayer()", throwing = "ex")
public void logError(JoinPoint jp, Exception ex) {
    System.out.println("[AfterThrowing] " + jp.getSignature().getName()
        + " 예외: " + ex.getMessage());
}

6) @After — 성공/실패 무관 항상 수행 (자원 정리)

@After("daoLayer()")
public void cleanup(JoinPoint jp) {
    System.out.println("[After] " + jp.getSignature().getName() + " 종료");
}

7) @Around — 전후 모두 제어 (수행시간 측정 + 암복호화)

pjp.proceed() 호출 전이 "실행 전", 이후가 "실행 후"입니다. 반환값을 반드시 return 해야 합니다.

@Around("daoLayer()")
public Object measureAndSecure(ProceedingJoinPoint pjp) throws Throwable {
    long start = System.currentTimeMillis();

    // (실행 전) 파라미터 암호화 등 전처리
    Object result = pjp.proceed();   // 실제 대상 메서드 실행
    // (실행 후) 결과 복호화 등 후처리

    long elapsed = System.currentTimeMillis() - start;
    System.out.println("[Around] 수행시간: " + elapsed + "ms");
    return result;   // 반환값을 돌려주지 않으면 호출자가 null을 받음!
}
💡 Advice 실행 순서: @Around(proceed 전) → @Before → 대상 메서드 → @AfterReturning 또는 @AfterThrowing → @After → @Around(proceed 후)

05프록시(Proxy) 개념

클라이언트 프록시 (부가 기능) 실제 객체
💡 비유: 연예인(실제 객체)에게 연락하면 매니저(프록시)가 먼저 받아 일정 확인 등을 처리한 뒤 전달하는 구조

06커스텀 어노테이션 + AOP 패턴

// 1. 커스텀 어노테이션 정의
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Encrypt {}

// 2. Aspect에서 어노테이션 기준으로 적용
@Aspect
@Component
public class EncryptAspect {
    @Around("@annotation(com.example.annotation.Encrypt)")
    public Object encrypt(ProceedingJoinPoint pjp) throws Throwable {
        // 암복호화 처리
        return pjp.proceed();
    }
}

// 3. 필요한 메서드에만 선언
@Encrypt
public void saveUser(User user) { ... }
💡 실무 활용 예: @Encrypt 암복호화 · @LogExecutionTime 수행시간 측정 · @Retry 재시도 · @CheckAuth 권한 체크 · @Masking 개인정보 마스킹

07DAO 암복호화 적용 사례

08관련 라이브러리 구성

라이브러리역할
aspectjweaver.jarAOP 위빙을 수행하는 오픈소스 런타임 라이브러리 (Eclipse Foundation)
securedbagent.jarDB 암복호화 상용 솔루션 에이전트 — Java WAS에 통합되어 암복호화 수행
💡 개인정보보호법·전자금융감독규정에 따라 주민번호·계좌번호 등의 암호화는 의무 — 금융권·공공기관·대기업에서 표준적으로 사용하는 구성
✓ Markdown이 클립보드에 복사되었습니다