8주차 Unit 1.1 — AOP란 무엇인가

Psj·2026년 6월 5일

F-lab

목록 보기
237/239

Unit 1.1 — AOP란 무엇인가

F-LAB JAVA · 8주차 · Phase 1 · AOP 입문과 동기
🌟 8주차 시작 — 프록시의 진화 (자바·Spring 학습의 클라이맥스)


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • AOP 의 정의는?
  • 7주차 @Transactional 이 AOP 인 이유는?
  • 핵심 관점 vs 부가 관점 차이는?
  • 흩어진 관심사 (Crosscutting Concerns) 의 의미는?
  • 흩어진 관심사의 사례 3가지는?
  • OOP 의 한계 는?
  • AOP 의 등장 이유 는?
  • Spring 의 AOP 적용 사례 는?
  • 8주차 학습의 의의 는?

🎯 핵심 한 문장

AOP (Aspect Oriented Programming, 관점 지향 프로그래밍) 는 어떤 로직을 핵심 관점 (비즈니스 로직) 과 부가 관점 (트랜잭션·로깅·보안·캐싱) 으로 나눠서 보고 각 관점을 별도로 모듈화하는 프로그래밍 패러다임으로, 여러 클래스에 반복적으로 등장하는 흩어진 관심사 (Crosscutting Concerns) 를 OOP 만으로는 깔끔히 처리하기 어려운 한계를 보완하기 위해 등장했으며 7주차의 @Transactional 이 가장 대표적 사례다.
AOP (Aspect Oriented Programming)관점 지향 프로그래밍 으로 — 어떤 로직을 핵심 관점 + 부가 관점 으로 나눠서 보고 각 관점을 별도로 모듈화 하는 프로그래밍 패러다임이다.
핵심 관점 (Core Concern) — 비즈니스 로직 (주문 처리, 회원 가입, 배송 처리 등 도메인 의미가 있는 핵심 동작) — 클래스마다 다르고 변화가 잦다.
부가 관점 (Cross-cutting Concern) — 로깅·트랜잭션·DB 연결·보안·캐싱·성능 측정 — 여러 클래스에 반복적으로 등장 하며 변화가 적다.
흩어진 관심사 (Crosscutting Concerns) — 여러 클래스를 횡단해서 (cross-cutting) 흩어진 부가 관점들 — OOP 의 상속·캡슐화·다형성 만으로는 깔끔히 한 곳에 모으기 어렵다.
7주차에서 학습한 @Transactional 이 정확히 이 AOP 의 대표 사례 — 트랜잭션 시작·커밋·롤백 (부가 관점) 을 비즈니스 로직 (핵심 관점) 에서 분리해 어노테이션 1줄로 적용 — 다른 부가 관점 (@Cacheable / @PreAuthorize / @Async) 도 같은 메커니즘이다.
8주차의 학습 목표 — 이 @Transactional 이 어떻게 동작하는지의 모든 메커니즘 (프록시 패턴 → 동적 프록시 → ProxyFactory) 을 깊이 파헤쳐 자바·Spring 학습의 클라이맥스에 이르는 것이다.

비유 — 영화 제작의 두 관점

AOP = 영화 제작의 두 관점:

핵심 관점 (스토리):
  - 주인공 등장
  - 갈등 발생
  - 클라이맥스
  - 결말

  → 영화마다 다름 (변화 많음)
  → 영화의 본질

부가 관점 (제작 환경):
  - 조명 (모든 신마다)
  - 카메라 워크
  - 음향
  - 자막 / 더빙

  → 모든 영화에 공통
  → 환경적 요소
  → "흩어져 있음"

OOP 의 한계:
  - 영화마다 조명 / 카메라 / 음향 직접 설정
  - 모든 영화에 같은 설정 복사
  - 변경 시 모든 영화 수정

AOP 의 답:
  - "스튜디오 자동 시스템" (조명/카메라/음향)
  - "관점" 으로 모듈화
  - 영화 (비즈니스) = 스토리만 집중
  - 환경 = 자동

7주차 @Transactional:
  - 비즈니스 로직 = 스토리
  - 트랜잭션 = 환경 (조명)
  - 어노테이션 1줄 = 자동 적용

ILIC:
  - 1020 메서드 = 1020 영화 신
  - 모두 @Transactional = 자동 환경
  - 비즈니스만 집중

8주차 학습:
  - @Transactional 의 동작 메커니즘
  - 프록시 패턴 → 동적 프록시 → AOP
  - 자바 진영의 추상화 정점

→ AOP = 핵심 관점 + 부가 관점 분리, 흩어진 관심사 해결, @Transactional 의 본질.


🧭 9개 섹션 로드맵

1. AOP 정의
2. 7주차 @Transactional 회상
3. 핵심 관점 (비즈니스 로직)
4. 부가 관점 (트랜잭션, 로깅 등)
5. 흩어진 관심사 (Crosscutting Concerns)
6. OOP 의 한계
7. AOP 의 등장 이유
8. Spring 의 AOP 적용 사례
9. 8주차 학습의 의의

1️⃣ AOP 정의

1.1 정의

AOP (Aspect Oriented Programming):

  관점 지향 프로그래밍:
    - 어떤 로직을 두 가지 관점으로 분리
    - 핵심 관점 + 부가 관점
    - 각 관점을 별도 모듈화

→ "관점 (Aspect) 으로 보는 프로그래밍"

1.2 Aspect 의 의미

Aspect (관점):

  의미:
    - 어떤 것을 보는 관점 / 측면
    - 비즈니스의 한 측면
    - 부가 기능의 한 측면

  AOP 에서:
    - 부가 관점의 모듈화
    - 포인트컷 + 어드바이스 (Phase 8 에서 상세)

1.3 OOP 와의 관계

OOP 와의 관계:

  OOP (Object Oriented Programming):
    - 객체로 본다
    - 클래스 / 상속 / 다형성
    - 자바의 기본

  AOP (Aspect Oriented Programming):
    - 관점으로 본다
    - 핵심 + 부가 분리
    - OOP 보완 (대체 X)

  관계:
    - "AOP 는 OOP 를 대체하지 않음"
    - "OOP 의 부족한 부분 (횡단 관심사) 을 보조"

→ OOP + AOP = 더 강력

1.4 출생 배경

출생 배경:

  Xerox PARC 연구:
    - 1990년대 후반
    - AspectJ 프로젝트
    - OOP 의 한계 인식

  Spring 의 차용:
    - 2003년+ Spring AOP
    - AspectJ 문법 차용
    - 프록시 방식 사용

→ Spring 의 핵심 기능

1.5 ILIC 의 맥락

ILIC 의 AOP 활용

ILIC = Spring Boot + JPA:

  AOP 의 명시적 / 암시적 활용:
    - @Transactional (트랜잭션, 7주차)
    - @Cacheable (캐시)
    - @PreAuthorize (보안)
    - @Async (비동기)
    - @Loggable (로깅, 커스텀)

  모두 AOP:
    - 어노테이션 1줄
    - 프록시 + 자동 적용
    - 비즈니스 로직 깔끔

  ILIC 의 1020 메서드:
    - @Transactional 1020개
    - 모두 AOP
    - 매일 사용

1.6 자기 점검 답변

AOP 의 정의는?

:
1. AOP:

  • 관점 지향 프로그래밍
  1. 두 관점:

    • 핵심 + 부가
  2. Aspect:

    • 관점 모듈화
  3. OOP 관계:

    • 보완 (대체 X)

2️⃣ 7주차 @Transactional 회상

2.1 7주차 학습 응축

7주차 학습 응축:

  Phase 7 — @Transactional:
    - Unit 7.1 프록시 패턴
    - Unit 7.2 동작 원리 ★★★
    - Unit 7.3 5가지 함정

  7주차에서 본 것:
    - @Transactional 1줄 = 자동 트랜잭션
    - 프록시 + AOP 가 동작 기반
    - CGLIB 자식 클래스
    - TransactionInterceptor 가로채기
    - 7 단계 호출 흐름

2.2 @Transactional 의 본질 = AOP

@Transactional 의 본질 = AOP:

  핵심 관점:
    - 비즈니스 로직
    - "주문 생성", "배송 처리" 등

  부가 관점:
    - 트랜잭션 시작 / 커밋 / 롤백
    - 자원 관리
    - 예외 처리

  AOP 의 결과:
    - 비즈니스 코드 깔끔
    - 트랜잭션 자동
    - 어노테이션 1줄

2.3 코드로 보는 분리

// AOP 적용 전 (수동 트랜잭션, 7주차 Phase 5)
public void processShipment(Long id) {
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    try {
        tx.begin();                                      // 부가 (트랜잭션)
        
        // 핵심 (비즈니스 로직)
        Shipment s = em.find(Shipment.class, id);
        s.markAsShipped();
        em.merge(s);
        
        tx.commit();                                     // 부가
    } catch (Exception e) {
        if (tx.isActive()) tx.rollback();               // 부가
        throw new RuntimeException(e);
    } finally {
        em.close();                                      // 부가
    }
}

// AOP 적용 후 (@Transactional, 7주차 Phase 7)
@Transactional   // ← 부가 관점 = 어노테이션 1줄
public void processShipment(Long id) {
    // 핵심 관점만!
    Shipment s = repo.findById(id).orElseThrow();
    s.markAsShipped();
}
class Shipment { void markAsShipped() {} }
EntityManagerFactory emf;
class EntityManagerFactory { EntityManager createEntityManager() { return null; } }
class EntityManager {
    EntityTransaction getTransaction() { return null; }
    <T> T find(Class<T> c, Object id) { return null; }
    <T> T merge(T t) { return null; }
    void close() {}
}
class EntityTransaction {
    void begin() {}
    void commit() {}
    void rollback() {}
    boolean isActive() { return false; }
}
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
@interface Transactional {}

2.4 분리의 효과

분리의 효과:

  코드:
    - 15 줄 → 3 줄
    - SoC 완벽
    - 가독성 ↑

  유지보수:
    - 비즈니스 변경 시 = 비즈니스만
    - 트랜잭션 변경 시 = 어노테이션 옵션만
    - 영향 격리

  안전:
    - 함정 자동 회피 (rollback / close 누락 X)
    - 일관 패턴

2.5 다른 AOP 어노테이션

// Spring 의 다양한 AOP 어노테이션
@Service
public class ShipmentService {
    
    @Transactional         // 트랜잭션
    @Cacheable("shipments") // 캐시
    @PreAuthorize("hasRole('ADMIN')") // 보안
    @Async                  // 비동기
    @Loggable               // 커스텀 (로깅)
    public Shipment process(Long id) {
        // 비즈니스만!
    }
}

// 효과:
// - 5 어노테이션 = 5 AOP
// - 모두 자동
// - 비즈니스 코드 깔끔
class Shipment {}
@interface Service {}
@interface Transactional {}
@interface Cacheable { String value(); }
@interface PreAuthorize { String value(); }
@interface Async {}
@interface Loggable {}

2.6 8주차 학습의 동기

8주차 학습의 동기:

  7주차에서:
    - @Transactional 의 동작 원리 ★★★
    - 프록시 + AOP 의 결과 사용

  8주차에서:
    - 프록시 + AOP 의 모든 메커니즘
    - 디자인 패턴의 진화
    - 동적 프록시 기술
    - ProxyFactory 통합 추상화

  9주차에서:
    - Spring AOP 실전
    - @Aspect / @Around
    - 트랜잭션 전파 (★ 정점)

→ 7주차에서 본 결과 →
→ 8-9주차에서 메커니즘 완전 정복

2.7 ILIC 의 맥락

ILIC 의 AOP 학습 의의

ILIC 의 1020 메서드:
  - 모두 @Transactional
  - 모두 AOP 작동

  8-9주차 학습 후:
    - 동작 원리 완전 이해
    - 함정 회피 깊이
    - 디버깅 능력
    - 면접 정점

  ILIC 의 다른 AOP 활용:
    - @Cacheable (Redis)
    - @Async (비동기 알림)
    - @Loggable (감사 로그)

→ 모두 8-9주차 학습 활용

2.8 자기 점검 답변

7주차 @Transactional 이 AOP 인 이유는?

:
1. @Transactional:

  • 부가 관점 (트랜잭션)
  1. 분리:

    • 비즈니스 + 트랜잭션
  2. AOP 의 본질:

    • 핵심 + 부가 모듈화
  3. 8주차 학습:

    • 동작 원리

3️⃣ 핵심 관점 (비즈니스 로직)

3.1 핵심 관점 정의

핵심 관점 (Core Concern):

  비즈니스 로직:
    - 도메인 의미가 있는 동작
    - "주문 처리", "결제", "배송"
    - 클래스마다 다름
    - 변화가 잦음

  애플리케이션의 본질:
    - "이 시스템이 무엇을 하는가"
    - 매출 / 가치 직결

3.2 사례

사례 (ILIC):

  ShipmentService:
    - process(): 배송 처리
    - markAsShipped(): 선적 표시
    - calculateFreight(): 운임 계산

  CustomerService:
    - register(): 고객 등록
    - updateProfile(): 정보 변경
    - checkCredit(): 신용 검사

  BookingService:
    - createBooking(): 예약 생성
    - confirmBooking(): 예약 확정
    - cancelBooking(): 예약 취소

→ 모두 도메인 의미
→ ILIC 의 본질

3.3 핵심 관점의 특징

핵심 관점의 특징:

  1. 도메인 의미:
     - 비즈니스 용어
     - 사용자에게 가치

  2. 다양성:
     - 클래스마다 다름
     - 메서드마다 다름

  3. 변화 잦음:
     - 비즈니스 요구사항 변경
     - 자주 수정

  4. 분리 단위:
     - 클래스 / 메서드 단위
     - OOP 로 잘 표현 가능

3.4 OOP 의 강점

OOP 의 강점 (핵심 관점):

  - 캡슐화: 도메인 상태 보호
  - 상속: 도메인 공통 부분
  - 다형성: 다른 도메인 처리

  핵심 관점은:
    - OOP 로 잘 표현
    - 자연스러움

→ 핵심 관점 = OOP 의 영역

3.5 ILIC 의 맥락

// ILIC 의 핵심 관점

@Entity
public class Shipment {   // 도메인 객체
    @Id Long id;
    String blNo;
    ShipmentStatus status;
    
    // 핵심 비즈니스 메서드 (도메인 의미)
    public void markAsShipped() {
        if (status != ShipmentStatus.CONFIRMED) {
            throw new IllegalStateException("CONFIRMED 상태만 선적 가능");
        }
        this.status = ShipmentStatus.SHIPPED;
    }
    
    public BigDecimal calculateFreight() {
        // 운임 계산 로직 (핵심)
    return null;
    }
}

@Service
public class ShipmentService {
    @Autowired ShipmentRepository repo;
    
    public Shipment process(Long id) {   // 핵심 (비즈니스)
        Shipment s = repo.findById(id).orElseThrow();
        s.markAsShipped();
        return s;
    }
}

// → 핵심 관점만 (도메인)
// → 부가 관점 X
enum ShipmentStatus { CONFIRMED, SHIPPED }
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
@interface Entity {}
@interface Id {}
@interface Service {}
@interface Autowired {}

3.6 자기 점검 답변

핵심 관점 (비즈니스 로직) 의 의미는?

:
1. 핵심 관점:

  • 비즈니스 로직
  1. 특징:

    • 도메인 / 다양 / 잦은 변경
  2. OOP:

    • 잘 표현
  3. ILIC:

    • process / markAsShipped 등

4️⃣ 부가 관점 (트랜잭션, 로깅 등)

4.1 부가 관점 정의

부가 관점 (Cross-cutting Concern):

  핵심 외의 부가 기능:
    - 로깅
    - 트랜잭션
    - 보안 (인증/인가)
    - 캐싱
    - 성능 측정
    - 예외 처리
    - 모니터링
    - 트레이싱

  여러 클래스에 공통:
    - "횡단" (cross-cutting)
    - 흩어져 있음

4.2 사례

사례:

  로깅:
    - 메서드 진입 / 종료
    - 인자 / 반환값
    - 예외

  트랜잭션:
    - begin / commit / rollback
    - 7주차 @Transactional

  보안:
    - 권한 검사 (@PreAuthorize)
    - 인증 확인

  캐싱:
    - 결과 캐시 (@Cacheable)
    - 만료 정책

  성능 측정:
    - 실행 시간
    - 호출 횟수

  → 모두 부가

4.3 부가 관점의 특징

부가 관점의 특징:

  1. 비도메인:
     - 인프라 / 기술
     - 비즈니스 외

  2. 공통성:
     - 여러 클래스
     - 비슷한 패턴
     - 반복

  3. 변화 적음:
     - 정책 / 기술 변경 외 안 변함
     - 보일러플레이트

  4. 횡단:
     - 여러 메서드 / 클래스 가로질러
     - 모듈화 어려움 (OOP 만으로)

4.4 부가 관점의 비율

부가 관점의 비율 (수동 시):

  메서드별:
    - 핵심: 3-5 줄
    - 부가: 12-15 줄
    - 비율: 부가 > 핵심

  본말 전도:
    - 비즈니스보다 인프라
    - 가독성 ↓

→ AOP 로 분리 필수

4.5 부가 관점 분리의 가치

분리의 가치:

  1. 비즈니스 집중:
     - 코드 깔끔
     - 의도 명확

  2. 일관 적용:
     - 모든 메서드 같은 방식
     - 누락 X

  3. 변경 안전:
     - 부가 정책 변경 시
     - 한 곳만 (Aspect)

  4. 테스트:
     - 비즈니스만 테스트
     - 부가 분리

4.6 ILIC 의 맥락

ILIC 의 부가 관점

ILIC 의 102 테이블 × 1020 메서드:

  부가 관점 (모두 적용):
    1. 트랜잭션 (@Transactional)
       → 1020 곳
    2. 로깅 (@Loggable, 커스텀)
       → 1020 곳
    3. 보안 (@PreAuthorize)
       → 일부 (인증 필요)
    4. 캐싱 (@Cacheable)
       → 일부 (조회)
    5. 비동기 (@Async)
       → 일부 (알림 등)

  AOP 없으면:
    - 1020 메서드 × 5 부가 = 5,100 곳 수정 필요
    - 일관성 ↓
    - 함정 ↑

  AOP 있으면:
    - 어노테이션 5개 × 1020 = 5,100 어노테이션
    - 일관 패턴
    - 자동

4.7 자기 점검 답변

부가 관점 (트랜잭션, 로깅 등) 의 의미는?

:
1. 부가 관점:

  • 핵심 외 기능
  1. 특징:

    • 비도메인 / 공통 / 횡단
  2. 사례:

    • 트랜잭션 / 로깅 / 보안 등
  3. 분리 가치:

    • 비즈니스 집중

5️⃣ 흩어진 관심사 (Crosscutting Concerns)

5.1 흩어진 관심사

흩어진 관심사 (Crosscutting Concerns):

  여러 클래스를 횡단해서 흩어진 부가 관점:
    - 한 곳에 모으기 어려움
    - 여러 클래스에 반복 등장
    - OOP 만으로는 깔끔히 처리 X

  "흩어진" 의 의미:
    - 100 클래스 × 같은 코드
    - "관심사가 흩어져 있다"

5.2 시각화

시각화:

  핵심 관심사 (각 클래스 다름):
  ┌──────────────┬──────────────┬──────────────┐
  │ ShipmentService │ CustomerService │ BookingService │
  ├──────────────┼──────────────┼──────────────┤
  │ 배송 처리      │ 고객 등록      │ 예약 생성      │
  │ (도메인)      │ (도메인)      │ (도메인)      │
  └──────────────┴──────────────┴──────────────┘

  흩어진 관심사 (모든 클래스에 공통):
  ┌──────────────┬──────────────┬──────────────┐
  │ 로깅          │ 로깅          │ 로깅          │  ← 같은 코드
  │ 트랜잭션      │ 트랜잭션      │ 트랜잭션      │  ← 같은 코드
  │ 보안          │ 보안          │ 보안          │  ← 같은 코드
  └──────────────┴──────────────┴──────────────┘

  → 흩어져 있음 (여러 클래스에)
  → 한 곳에 모을 수 없을까?

5.3 OOP 의 도전

OOP 의 도전:

  OOP 의 도구:
    - 상속: 부모 클래스에 부가 코드?
      → 다중 상속 X (자바)
      → 강한 결합
      → 부적합

    - 인터페이스 + 디폴트 메서드:
      → 부가 관점 모듈화 가능?
      → 한계 있음

    - 합성:
      → 매번 부가 객체 호출
      → 비즈니스 코드 어지러움

  → OOP 만으로는 한계

5.4 흩어진 관심사의 사례 3가지

흩어진 관심사 사례 3가지:

  1. 로깅 (Logging):
     - 모든 서비스 메서드의 진입 / 종료
     - 호출 깊이 추적
     - 인자 / 반환값
     - 예외

  2. 트랜잭션 (Transaction):
     - 모든 비즈니스 메서드의 begin / commit / rollback
     - 7주차 @Transactional

  3. 보안 (Security):
     - 모든 보호된 메서드의 권한 검사
     - 인증 / 인가
     - 감사 로그

5.5 흩어진 관심사의 사례 (확장)

흩어진 관심사 확장:

  4. 캐싱:
     - 조회 결과 캐시
     - 만료 정책

  5. 성능 측정:
     - 실행 시간
     - 호출 횟수
     - 메트릭 (Prometheus 등)

  6. 예외 처리:
     - 공통 예외 변환
     - 로깅 + 알림

  7. 트랜잭션 격리:
     - propagation 정책
     - readOnly 최적화

  8. 모니터링:
     - APM (New Relic, Datadog)
     - 트레이싱 (OpenTelemetry)

  9. 감사 로그:
     - 누가 / 언제 / 무엇을
     - 규제 준수

5.6 ILIC 의 맥락

ILIC 의 흩어진 관심사

ILIC 의 1020 메서드:

  각 메서드에 공통 부가:
    1. @Transactional (트랜잭션)
    2. @Loggable (로깅, 커스텀)
    3. @PreAuthorize (일부, 보안)
    4. @Cacheable (일부, 캐싱)

  횡단:
    - ShipmentService 메서드
    - CustomerService 메서드
    - BookingService 메서드
    - ...
    
    모두 같은 부가 관점 가짐
    
    "흩어진"
    "여러 클래스 횡단"

  AOP 의 해결:
    - 각 부가 = 한 Aspect 모듈
    - 어노테이션 1줄로 적용
    - 일관 + 자동

5.7 자기 점검 답변

흩어진 관심사 (Crosscutting Concerns) 의 의미는?

:
1. 흩어진:

  • 여러 클래스 횡단
  1. 반복:

    • 같은 코드 여러 곳
  2. OOP 한계:

    • 모듈화 어려움
  3. 사례:

    • 로깅 / 트랜잭션 / 보안

6️⃣ OOP 의 한계

6.1 OOP 의 강점

OOP 의 강점:

  - 캡슐화: 도메인 상태 보호
  - 상속: 공통 부분
  - 다형성: 확장
  - 클래스 / 인터페이스 / 메서드

  핵심 관점 = OOP 가 강함:
    - 도메인 표현
    - 클래스 단위 분리

6.2 OOP 의 한계

OOP 의 한계:

  부가 관점 (흩어진 관심사) 처리 어려움:

  1. 상속의 한계:
     - 단일 상속 (자바)
     - 강한 결합
     - "이미 다른 부모 있음"
     
     예: ShipmentService extends BaseService
        → 로깅 부모로 못 만듦

  2. 합성의 한계:
     - 매번 부가 객체 호출
     - 비즈니스 코드 어지러움
     - 일관성 ↓
     
     예: public void process() {
            logger.log("진입");        // 일일이
            tx.begin();
            // 비즈니스
            tx.commit();
            logger.log("종료");        // 일일이
         }

  3. 인터페이스의 한계:
     - 부가 코드는 X
     - 단순 계약만

6.3 횡단 (Crosscutting) 의 의미

횡단 (Crosscutting):

  OOP:
    - 수직 분류 (상속 트리)
    - 클래스 위계 구조

  흩어진 관심사:
    - 수평 분포 (여러 클래스)
    - 위계 무관
    - "가로질러" 분포

  OOP 의 수직 모듈화 ≠ 수평 모듈화
  → AOP 가 필요

6.4 시각적 이해

시각적 이해:

  OOP (수직 분류):
       Animal
       /    \
      Dog    Cat
      /        \
   Bulldog   Persian

  → 같은 부모 → 공통 행동
  → 수직 모듈화

  흩어진 관심사 (수평 분포):
    Dog → 로깅, 트랜잭션, 보안
    Cat → 로깅, 트랜잭션, 보안
    Car → 로깅, 트랜잭션, 보안
    
  → 다른 부모 (다른 도메인)
  → 같은 부가 관점
  → 수평 분포
  → OOP 모듈화 어려움

6.5 데코레이터 패턴의 한계

데코레이터 패턴의 한계:

  OOP 의 패턴 (데코레이터):
    - 부가 기능 추가 가능
    - 같은 인터페이스
    - 중첩 가능

  하지만:
    - 각 메서드마다 데코레이터 클래스 작성
    - 100 메서드 → 100 데코레이터
    - 보일러플레이트 폭증

→ 패턴 자체는 한 단계 (필요한 자동화 X)

6.6 ILIC 의 맥락

ILIC 의 OOP 한계

ILIC = 102 도메인 객체 (Entity):
  - Shipment, Customer, Booking, ...
  - 각자 다른 부모 / 도메인

  공통 부가 관점:
    - 모두 트랜잭션 필요
    - 모두 로깅 필요

  OOP 만:
    - 각 Service 에 부가 코드
    - 일일이 작성
    - 1020 메서드 × 부가 코드

  AOP 의 필요성:
    - "관점" 으로 모듈화
    - 한 Aspect = 모든 적용
    - 어노테이션 1줄

6.7 자기 점검 답변

OOP 의 한계는?

:
1. OOP 강점:

  • 핵심 관점 (도메인)
  1. 한계:

    • 부가 관점 / 흩어진 관심사
  2. 이유:

    • 수직 vs 수평
  3. 결과:

    • AOP 필요

7️⃣ AOP 의 등장 이유

7.1 AOP 의 등장

AOP 의 등장:

  1990년대 후반 ~ 2000년대:
    - OOP 의 한계 인식
    - 흩어진 관심사 문제
    - "더 좋은 모듈화"

  Xerox PARC:
    - AspectJ 프로젝트
    - 1997년 ~
    - 자바 확장

  Spring AOP:
    - 2003년 ~
    - AspectJ 차용
    - 프록시 방식

7.2 AOP 의 답

AOP 의 답:

  "흩어진 관심사를 Aspect (관점) 로 모듈화":
    - 부가 관점 = 한 Aspect
    - 적용 지점 = Pointcut
    - 적용 코드 = Advice

  결과:
    - 부가 관점 = 한 곳
    - 비즈니스 = 별도
    - 깔끔 분리

7.3 핵심 통찰

핵심 통찰:

  "부가 기능 + 부가 기능을 어디에 적용할지 의 선택을
   합쳐서 하나의 모듈로 만든다.
   그게 Aspect."

  Aspect = Pointcut + Advice:
    - Pointcut: 어디에?
    - Advice: 무엇을?
    - 합쳐서 = Aspect (관점)

7.4 Aspect 의 모듈화 효과

Aspect 의 모듈화 효과:

  로깅 Aspect:
    - Pointcut: 모든 Service 메서드
    - Advice: 진입 / 종료 로깅

  트랜잭션 Aspect:
    - Pointcut: @Transactional 메서드
    - Advice: begin / commit / rollback

  보안 Aspect:
    - Pointcut: @PreAuthorize 메서드
    - Advice: 권한 검사

  → 각 Aspect = 한 모듈
  → 한 곳에 관리

7.5 OOP + AOP

OOP + AOP:

  대체 X, 보완 ✓:
    - OOP: 핵심 관점 (수직)
    - AOP: 부가 관점 (수평)

  같이 사용:
    - 자바 = OOP + AOP
    - Spring = OOP + AOP
    - 더 강력

  실무:
    - OOP 로 도메인 표현
    - AOP 로 부가 기능
    - 완벽 분리

7.6 ILIC 의 맥락

ILIC = OOP + AOP

ILIC 의 도메인:
  OOP (Entity 객체):
    - Shipment, Customer, Booking ...
    - 102 테이블
    - 도메인 의미
    - 비즈니스 메서드

ILIC 의 부가 기능:
  AOP (Aspect):
    - 트랜잭션 (@Transactional)
    - 캐싱 (@Cacheable)
    - 보안 (@PreAuthorize)
    - 비동기 (@Async)

  결과:
    - 도메인 = OOP 깔끔
    - 부가 = AOP 자동
    - 1020 메서드 효율 운영

→ ILIC = OOP + AOP 결정체

7.7 자기 점검 답변

AOP 의 등장 이유는?

:
1. OOP 한계:

  • 흩어진 관심사
  1. AspectJ:

    • 1997 ~
  2. :

    • Aspect 모듈화
  3. OOP + AOP:

    • 보완

8️⃣ Spring 의 AOP 적용 사례

8.1 Spring 의 AOP 활용

Spring 의 AOP 활용:

  Spring Framework 자체:
    - @Transactional (트랜잭션)
    - @Cacheable (캐시)
    - @Async (비동기)
    - @Retryable (재시도)
    - @Validated (검증)

  Spring Security:
    - @PreAuthorize (사전 인가)
    - @PostAuthorize (사후 인가)
    - @Secured

  Spring Cloud:
    - @CircuitBreaker (서킷 브레이커)
    - @Retry
    - @TimeLimiter

→ AOP 가 곳곳에

8.2 사례 1 — @Transactional

// @Transactional (7주차)
@Service
public class ShipmentService {
    @Transactional
    public void process(Long id) {
        // 비즈니스
    }
}

// AOP 동작:
// - Pointcut: @Transactional 메서드
// - Advice: 트랜잭션 시작 / 커밋 / 롤백
// - 어노테이션 1줄
@interface Service {}
@interface Transactional {}

8.3 사례 2 — @Cacheable

// @Cacheable
@Service
public class ShipmentService {
    @Cacheable("shipments")
    public Shipment getById(Long id) {
        return repo.findById(id).orElseThrow();
    }
}

// AOP 동작:
// - Pointcut: @Cacheable 메서드
// - Advice: 
//   1. 캐시 확인 → 있으면 반환
//   2. 없으면 메서드 호출 → 결과 캐시 저장
class Shipment {}
ShipmentRepository repo;
interface ShipmentRepository { java.util.Optional<Shipment> findById(Long id); }
@interface Service {}
@interface Cacheable { String value(); }

8.4 사례 3 — @PreAuthorize

// @PreAuthorize (Spring Security)
@Service
public class ShipmentService {
    @PreAuthorize("hasRole('ADMIN')")
    public void delete(Long id) {
        repo.deleteById(id);
    }
}

// AOP 동작:
// - Pointcut: @PreAuthorize 메서드
// - Advice:
//   1. 현재 사용자 권한 확인
//   2. ADMIN → 메서드 호출
//   3. 아니면 → AccessDeniedException
ShipmentRepository repo;
interface ShipmentRepository { void deleteById(Long id); }
@interface Service {}
@interface PreAuthorize { String value(); }

8.5 사례 4 — @Async

// @Async (비동기 실행)
@Service
public class NotificationService {
    @Async
    public void sendEmail(String to, String subject) {
        // 시간 걸리는 작업
        emailService.send(to, subject);
    }
}

// AOP 동작:
// - Pointcut: @Async 메서드
// - Advice:
//   1. 별도 스레드에서 실행
//   2. 호출자는 즉시 반환
class EmailService { void send(String to, String s) {} }
EmailService emailService;
@interface Service {}
@interface Async {}

8.6 사례 5 — 커스텀 AOP

// 커스텀 @Loggable (개발자가 만듦)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {}

@Aspect
@Component
public class LoggingAspect {
    @Around("@annotation(com.ilic.Loggable)")
    public Object log(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object result = pjp.proceed();
            log.info("{} took {}ms", 
                pjp.getSignature(), 
                System.currentTimeMillis() - start);
            return result;
        } catch (Exception e) {
            log.error("{} failed", pjp.getSignature(), e);
            throw e;
        }
    }
}

// 사용
@Service
public class ShipmentService {
    @Loggable   // 커스텀 AOP
    public void process(Long id) { }
}
@interface Target { ElementType[] value(); }
enum ElementType { METHOD }
@interface Retention { RetentionPolicy value(); }
enum RetentionPolicy { RUNTIME }
@interface Aspect {}
@interface Component {}
@interface Around { String value(); }
class ProceedingJoinPoint {
    Object proceed() throws Throwable { return null; }
    Object getSignature() { return null; }
}
@interface Service {}
@interface Loggable {}
org.slf4j.Logger log;

8.7 ILIC 의 맥락

// ILIC 의 AOP 종합 활용

@Service
public class ShipmentService {
    @Autowired ShipmentRepository repo;
    
    // 다중 AOP
    @Transactional
    @Cacheable("shipments")
    @Loggable
    @PreAuthorize("hasRole('USER')")
    public Shipment getShipment(Long id) {
        return repo.findById(id).orElseThrow();
    }
    
    @Transactional
    @Loggable
    @PreAuthorize("hasRole('ADMIN')")
    @CacheEvict(value = "shipments", key = "#id")
    public void delete(Long id) {
        repo.deleteById(id);
    }
}

// 한 메서드 = 여러 AOP:
// - 트랜잭션
// - 캐시
// - 로깅
// - 보안

// 모두 어노테이션 1줄씩
// 모두 자동
// 모두 분리
class Shipment {}
ShipmentRepository repo;
interface ShipmentRepository {
    java.util.Optional<Shipment> findById(Long id);
    void deleteById(Long id);
}
@interface Service {}
@interface Autowired {}
@interface Transactional {}
@interface Cacheable { String value(); }
@interface CacheEvict { String value(); String key(); }
@interface Loggable {}
@interface PreAuthorize { String value(); }

8.8 자기 점검 답변

Spring 의 AOP 적용 사례는?

:
1. Spring 자체:

  • @Transactional / @Cacheable / @Async
  1. Spring Security:

    • @PreAuthorize
  2. 커스텀:

    • @Loggable 등
  3. 혼합:

    • 한 메서드 다중 AOP

9️⃣ 8주차 학습의 의의

9.1 8주차의 위치

8주차의 위치:

  1주차 OOP →
    2주차 JVM →
      3주차 함수형 →
        4주차 동시성 →
          5주차 디자인 패턴 →
            6주차 DB 접근 →
              7주차 JPA + @Transactional →
                8주차 프록시의 진화 ← 여기
                  9주차 Spring AOP 실전

→ 7주차의 동작 원리 (★★★) 를 깊이 파헤치는 단계

9.2 8주차 학습 흐름

8주차 학습 흐름:

  Phase 1 — AOP 입문과 동기 (지금)
    - Unit 1.1 AOP 정의 ← 여기
    - Unit 1.2 로그 추적기
    - Unit 1.3 ThreadLocal

  Phase 2 — 디자인 패턴의 진화
    - 템플릿 메서드 → 전략 패턴

  Phase 3 — 콜백과 프록시의 만남
    - 템플릿 콜백 → 프록시 개념

  Phase 4 — 프록시 vs 데코레이터
    - 의도 구분

  Phase 5 — 동적 프록시 기술
    - Reflection / JDK / CGLIB

  Phase 6 — ProxyFactory (★ 정점)
    - Pointcut / Advice / Advisor

9.3 5+6+7주차와의 연결

5+6+7주차와의 연결:

  5주차 (디자인 패턴):
    - 템플릿 메서드 / 전략 / 프록시
    → 8주차 Phase 2-4

  5주차 (DI / IoC):
    - 빈 관리
    → 8주차 Phase 7 (빈 후처리기)

  6주차 (JdbcTemplate):
    - 템플릿 콜백 패턴
    → 8주차 Phase 3

  7주차 (@Transactional):
    - AOP 의 결과 사용
    → 8주차에서 메커니즘 파헤치기

→ 모든 학습 응축

9.4 9주차 예고

9주차 예고:

  Phase 7 — 빈 후처리기와 자동 프록시 생성기
  Phase 8 — @Aspect 와 AOP 용어
  Phase 9 — Spring AOP 실전 패턴
  Phase 10 — @Transactional 함정 + 트랜잭션 전파 ★ 정점

  특히:
    - Internal call 문제 (★★★)
    - 트랜잭션 전파 (★★★)
    - UnexpectedRollbackException

9.5 학습 성취

학습 성취:

  8-9주차 완주 후:
    - AOP 메커니즘 완전 이해
    - @Transactional 동작 원리 (7주차 + 8주차)
    - 프록시 기술 (JDK / CGLIB)
    - ProxyFactory 활용
    - 트랜잭션 전파 마스터
    - 면접 시니어 시험 통과

  자바 백엔드 시니어 :
    - 7주차 + 8주차 + 9주차 응축
    - 깊은 이해
    - 운영 안정

9.6 면접 단골 질문 매핑

Q핵심 답변
AOP?관점 지향
핵심 vs 부가?비즈니스 vs 트랜잭션 등
흩어진 관심사?횡단 분포
OOP 한계?수평 모듈화 어려움
등장 이유?흩어진 관심사 해결
Aspect?Pointcut + Advice
Spring 사례?@Transactional / @Cacheable 등
OOP + AOP?보완
8주차 학습?메커니즘 파헤치기
9주차?실전 + 전파

9.7 자기 점검 체크리스트

AOP 정의

  • 관점 지향

@Transactional

  • AOP 사례

핵심 관점

  • 비즈니스 로직

부가 관점

  • 트랜잭션 등

흩어진 관심사

  • Crosscutting

OOP 한계

  • 수평 모듈화

등장 이유

  • AspectJ

Spring 사례

  • 다양

학습 의의

  • 7주차 깊이

9.8 추가 심화 질문

Q1: AOP 와 OOP 의 차이는?

답:

  • OOP: 객체 중심 (수직 분류)
  • AOP: 관점 중심 (수평 분포)
  • 보완 관계 (대체 X)
  • 같이 사용 (자바 / Spring)

Q2: AOP 의 단점?

답:

  • "마법" 느낌 (보이지 않는 동작)
  • 디버깅 어려움 (스택 트레이스 복잡)
  • 학습 곡선
  • 함정 위험 (7주차 5가지)

Q3: AspectJ 와 Spring AOP 차이?

답:

  • AspectJ: 별도 프레임워크 (컴파일러)
  • Spring AOP: AspectJ 문법 차용, 프록시 방식
  • AspectJ 가 더 강력 (필드, 생성자 등)
  • Spring AOP 가 가볍고 일반적 (9주차 Phase 8)

Q4: 자바 외 언어의 AOP?

답:

  • JavaScript (decorators)
  • Python (decorators)
  • C# (Aspects)
  • 대부분 언어에 유사 개념

Q5: AOP 의 미래?

답:

  • Spring Boot 3 / Native 호환
  • 컴파일 시점 AOP (AOT)
  • 더 효율적
  • 표준화 지속

🎯 핵심 요약 — 3줄 정리

1. AOP = 관점 지향 프로그래밍

  • 어떤 로직을 핵심 관점 (비즈니스) + 부가 관점 (트랜잭션·로깅·보안) 으로 나눠서 봄
  • 각 관점을 별도 모듈화 → Aspect (Pointcut + Advice)
  • 7주차 @Transactional 이 가장 대표 사례

2. 흩어진 관심사 (Crosscutting Concerns)

  • 여러 클래스를 횡단해서 분포하는 부가 관점
  • OOP 의 수직 분류 (상속) 로는 수평 분포 (횡단) 처리 어려움
  • 사례: 로깅 / 트랜잭션 / 보안 / 캐싱 / 성능 측정 / 감사 등

3. OOP + AOP = 자바 백엔드의 강력

  • OOP 가 핵심 관점 (도메인) 처리 / AOP 가 부가 관점 처리
  • Spring 의 @Transactional / @Cacheable / @Async / @PreAuthorize 모두 AOP
  • 8주차 = 이 모든 AOP 의 동작 메커니즘 (프록시) 완전 정복

📚 다음으로...

Unit 1.2 — 로그 추적기로 보는 흩어진 관심사

이번 Unit에서 AOP 정의를 봤다면, 다음은 로그 추적기 시나리오로 흩어진 관심사를 코드로 본다.

  • 메서드 호출 시 자동 로깅
  • 호출 깊이 / 실행 시간 / 예외 추적
  • 100 메서드 = 100 곳 수정?
  • 변하는 것 vs 변하지 않는 것

Phase 1 진행 상황

📚 Phase 1 — AOP 입문과 동기
  ✅ Unit 1.1 AOP 란 무엇인가 ← 여기
  ⏭ Unit 1.2 로그 추적기
  ⏭ Unit 1.3 ThreadLocal

8주차 누적 진행

🌟 8주차 — 프록시의 진화

📚 Phase 1 (1/3)
⏭ Phase 2-6 (총 14 Unit)

총: 1/17 Unit (6%)

🌟 8주차 시작 — 프록시의 진화 (자바·Spring 학습의 클라이맥스)

profile
Software Developer

0개의 댓글