AOP, IOC, SOLID

AOP, IOC, SOLID

Tags
Published
Author

AOP(Aspect-Oriented Programming)

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과 κ΄€λ ¨ μ—†λŠ” 뢀가적인 κΈ°λŠ₯듀을 λͺ¨λ“ˆν™”ν•˜μ—¬ μ½”λ“œμ˜ 쀑볡을 쀄이고 μœ μ§€λ³΄μˆ˜μ„±μ„ ν–₯μƒμ‹œν‚€λŠ”λ° 주둜 ν™œμš©
  1. μ€‘λ³΅λ˜λŠ” 곡톡 μ½”λ“œ 뢀뢄을 λ³„λ„μ˜ μ˜μ—­μœΌλ‘œ 뢄리
  1. μ½”λ“œκ°€ μ‹œν–‰ 되기 μ „μ΄λ‚˜ 이 ν›„μ˜ μ‹œμ μ— ν•΄λ‹Ή μ½”λ“œλ₯Ό λΆ™μ—¬ λ„£μŒ
πŸ’‘
μ†ŒμŠ€ μ½”λ“œμ˜ 쀑볡을 쀄이고 ν•„μš”ν•  λ•Œλ§ˆλ‹€ κ°€μ Έλ‹€ μ“Έ 수 있게 객체화 ν•˜λŠ” 기술
λΆ€κ°€ κΈ°λŠ₯(ex: λ‘œκΉ…, λ³΄μ•ˆ, νŠΈλžœμž­μ…˜)을 핡심 κΈ°λŠ₯μ—μ„œ 뢄리해 ν•œ 곳으둜 κ΄€λ¦¬ν•˜λ„λ‘ ν•˜κ³  이 λΆ€κ°€ κΈ°λŠ₯을 어디에 μ μš©ν• μ§€ μ„ νƒν•˜λŠ” κΈ°λŠ₯을 ν•©ν•œ ν•˜λ‚˜μ˜ λͺ¨λ“ˆ
notion image
μ„œλ‘œ λ‹€λ₯Έ 클래슀라고 ν•˜λ”λΌλ„ λΉ„μŠ·ν•œ κΈ°λŠ₯을 ν•˜λŠ” λΆ€λΆ„(Concern)이 μžˆλ‹€. - Cross-Cutting-Corncern
λ§Œμ•½ λ…Έλž€μƒ‰ κΈ°λŠ₯을 μˆ˜μ •ν•΄μ•Όν•˜λ©΄ 각각 클래슀의 λ…Έλž€μƒ‰ κΈ°λŠ₯을 일일이 μˆ˜μ •ν•΄μ€˜μ•Όν•˜λŠ”λ° μœ μ§€λ³΄μˆ˜λ©΄μ—μ„œ 뢈리
notion image
AOPλ₯Ό μ΄μš©ν•œ 방법

AOP νŠΉμ§•

  • ν”„λ‘μ‹œ νŒ¨ν„΄ 기반
    • ν”„λ‘μ‹œ 객체λ₯Ό μ“°λŠ” μ΄μœ λŠ” μ ‘κ·Ό μ œμ–΄ 및 λΆ€κ°€κΈ°λŠ₯을 μΆ”κ°€ν•˜κΈ° μœ„ν•¨
  • ν”„λ‘μ‹œκ°€ ν˜ΈμΆœμ„ κ°€λ‘œμ±” (Intercept)
    • νƒ€κ²Ÿ 객체에 λŒ€ν•œ ν˜ΈμΆœμ„ κ°€λ‘œμ±ˆ λ‹€μŒ λΆ€κ°€κΈ°λŠ₯ λ‘œμ§μ„ μˆ˜ν–‰ν•˜κ³ λ‚œ 후에 νƒ€κ²Ÿμ˜ 핡심기λŠ₯

How to implement AOP

  1. 컴파일 νƒ€μž„ μœ„λΉ™
  1. 클래슀 λ‘œλ”© νƒ€μž„ μœ„λΉ™
  1. λŸ°νƒ€μž„ μœ„λΉ™(ν”„λ‘μ‹œ)
  • 컴파일 νƒ€μž„ μœ„λΉ™μ€ 컴파일 μ‹œμ μ— μ½”λ“œλ₯Ό λ§λΆ™μ—¬μ£ΌλŠ” 방법
  • 클래슀 λ‘œλ”© μœ„λΉ™μ€ 클래슀 파일 λ‘œλ”© νƒ€μž„μ— μ½”λ“œλ₯Ό λ§λΆ™μ—¬μ£ΌλŠ” 방법
  • λŸ°νƒ€μž„ μœ„λΉ™μ€ ν”„λ‘μ‹œλ₯Ό ν™œμš©ν•œ 방법

Weaving

λͺ¨λ“ˆν™”ν•œ λΆ€κ°€ κΈ°λŠ₯을 νƒ€κ²Ÿμ— μ μš©ν•΄ 핡심 κΈ°λŠ₯κ³Ό μ—°κ²°ν•˜λŠ” κ³Όμ •

Runtime Weaving

Proxy 객체λ₯Ό 생성해 μ‹€μ œ νƒ€κ²Ÿ 였브젝트의 λ³€ν˜•μ—†μ΄ λŸ°νƒ€μž„ 쀑 λ©”μ„œλ“œ 호좜이 μΌμ–΄λ‚˜λŠ” μ‹œμ μ— μœ„λΉ™μ„ μˆ˜ν–‰

Proxy

ν΄λΌμ΄μ–ΈνŠΈ-μ„œλ²„ λ“±μ˜ κ΄€κ³„μ—μ„œ 쀑간에 끼어 λŒ€λ¦¬μΈ 역할을 ν•˜λŠ” 객체
  • ν”„λ‘μ‹œμ™€ μ‹€μ œ 객체가 κ³΅μœ ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€κ°€ 있고 ν΄λΌμ΄μ–ΈνŠΈλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 ν”„λ‘μ‹œλ₯Ό μ‚¬μš©
  • ν΄λΌμ΄μ–ΈνŠΈλŠ” μ‹€μ œ 객체λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμ²˜λŸΌ λ™μž‘ν•˜μ§€λ§Œ μ‹€μ œλ‘œλŠ” ν”„λ‘μ‹œλ₯Ό ν†΅ν•΄μ„œ μ ‘κ·Όν•˜κ²Œ λœλ‹€
  • 쀑간에 ν”„λ‘μ‹œλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ„œ 접근관리(λ³΄μ•ˆ), 캐싱(μ„±λŠ₯), ν•„ν„° λ“±μ˜ λΆ€κ°€κΈ°λŠ₯듀을 μ œκ³΅ν•  수 μžˆλ‹€
  • μ‹€μ œ κ°μ²΄λŠ” μžμ‹ μ΄ ν•΄μ•Όν•  일(단일 μ±…μž„ 원칙)만 μ§‘μ€‘ν•˜λ©΄μ„œ 뢀가적인 κΈ°λŠ₯(λ‘œκΉ…, νŠΈλžœμž­μ…˜ μ²˜λ¦¬λ“±)을 ν”„λ‘μ‹œ κ°μ²΄μ—κ²Œ λ„˜κ²¨ 객체지ν–₯적인 ν”„λ‘œκ·Έλž˜λ°μ„ ν•  수 있게 λœλ‹€

IoC(Inversion of Control)

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 흐름 μ œμ–΄λ₯Ό κ°œλ°œμžκ°€ μ•„λ‹Œ ν”„λ ˆμž„μ›Œν¬ λ˜λŠ” μ»¨ν…Œμ΄λ„ˆκ°€ λ‹΄λ‹Ήν•˜λŠ” 것
  • 객체의 생성 및 객체 κ°„μ˜ μ˜μ‘΄μ„±μ„ μˆ˜λ™μœΌλ‘œ μ²˜λ¦¬ν•˜μ§€ μ•Šκ³  ν”„λ ˆμž„μ›Œν¬ λ˜λŠ” μ»¨ν…Œμ΄λ„ˆκ°€ λŒ€μ‹  κ΄€λ¦¬ν•΄μ£ΌλŠ” 것
  • 객체의 생성과 관리, 객체 κ°„μ˜ μ˜μ‘΄μ„± 처리 등을 ν”„λ ˆμž„μ›Œν¬μ—μ„œ λŒ€μ‹  μ²˜λ¦¬ν•΄μ£ΌλŠ” 것

IoC Container

IoCλ₯Ό κ΅¬ν˜„ν•œ ꡬ체적인 ν”„λ ˆμž„μ›Œν¬
πŸ’‘
전톡적인 절차적 ν”„λ‘œκ·Έλž˜λ°μ—μ„  μžμ‹ μ˜ μ½”λ“œκ°€ 직접 μ‚¬μš©ν•  였브젝트λ₯Ό κ²°μ •ν•˜κ³ , κ²°μ •ν•œ 였브젝트λ₯Ό μƒμ„±ν•˜κ³  μƒμ„±ν•œ 였브젝트의 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” μ‹μ΄μ§€λ§Œ IoCλ₯Ό μ μš©ν•˜λ©΄ λͺ¨λ“  μ œμ–΄ κΆŒν•œμ„ μžμ‹ μ΄ μ•„λ‹Œ λ‹€λ₯Έ λŒ€μƒμ—κ²Œ μœ„μž„ν•©λ‹ˆλ‹€.
  1. Injection Configuration : μ„€μ • μ£Όμž…
  1. Inject Dependencies : μ˜μ‘΄μ„± μ£Όμž…
  1. Manage Lifecycle : 라이프사이클 관리

DI(Dependency Injection)

객체 κ°„μ˜ μ˜μ‘΄μ„±μ„ ν”„λ ˆμž„μ›Œν¬κ°€ μ£Όμž…ν•˜λŠ” κ°œλ…
  • 객체가 직접 μ˜μ‘΄ν•˜λŠ” 객체λ₯Ό μƒμ„±ν•˜κ±°λ‚˜ μ°Έμ‘°ν•˜λŠ” λŒ€μ‹  μ΄λŸ¬ν•œ μ˜μ‘΄μ„±μ„ μ™ΈλΆ€μ—μ„œ μ£Όμž… 받도둝 ν•œλ‹€.
Denpendency Injection을 μ‚¬μš©ν•˜μ§€ μ•Šμ€ 경우
public class UserService { private UserRepository userRepository; public UserService() { this.userRepository = new UserRepository(); // 직접 생성 } }
Dependency Injection을 μ‚¬μš©ν•œ 경우
  1. Constructor Injection
      • μƒμ„±μžλ₯Ό 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…ν•˜λŠ” 방식
      • 클래슀의 μƒμ„±μžλ₯Ό μ •μ˜ν•˜κ³  μ˜μ‘΄ν•˜λŠ” 객체λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›μ•„ ν•„λ“œμ— ν• λ‹Ή
public class UserService { private UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } }
  1. Setter Injection
      • Setter λ©”μ„œλ“œλ₯Ό 톡해 μ˜μ‘΄μ„±μ„ μ£Όμž…ν•˜λŠ” 방식
      • Setter λ©”μ„œλ“œλ₯Ό μ •μ˜ν•˜κ³  ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό 톡해 μ˜μ‘΄ν•˜λŠ” 객체λ₯Ό μ£Όμž…
public class OrderService { private PaymentGateway paymentGateway; @Autowired public void setPaymentGateway(PaymentGateway paymentGateway) { this.paymentGateway = paymentGateway; } }
  1. Method Injection
      • λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜λ‘œ μ˜μ‘΄μ„±μ„ μ£Όμž…ν•˜λŠ” 방식
@Component public class ReportGenerator { private EmailService emailService; @Autowired public void setEmailService(EmailService emailService) { this.emailService = emailService; } public void generateReport() { } }

S.O.L.I.D

객체지ν–₯ μ„€κ³„μ—μ„œ μ§€μΌœμ€˜μ•Ό ν•  5개의 μ†Œν”„νŠΈμ›¨μ–΄ 개발 원칙
  1. SRP (Single Responsibilty Principle) : 단일 μ±…μž„ 원칙
  1. OCP (Open Closed Principle) : 개방 폐쇄 원칙
  1. LSP (Listov Subsititution Principle) : λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙
  1. ISP (Interface Segregation Principle) : μΈν„°νŽ˜μ΄μŠ€ 뢄리 원칙
  1. DIP (Dependency Inversion Principle) : 의쑴 μ—­μ „ 원칙

단일 μ±…μž„ 원칙

  • 클래슀(객체)λŠ” 단 ν•˜λ‚˜μ˜ μ±…μž„λ§Œ κ°€μ Έμ•Ό ν•œλ‹€
  • ν•˜λ‚˜μ˜ ν΄λž˜μŠ€λŠ” ν•˜λ‚˜μ˜ κΈ°λŠ₯을 λ‹΄λ‹Ήν•˜μ—¬ ν•˜λ‚˜μ˜ μ±…μž„μ„ μˆ˜ν–‰

개방 폐쇄 원칙

  • ν™•μž₯μ—λŠ” μ—΄λ €μžˆμ–΄μ•Ό ν•˜λ©° μˆ˜μ •μ—λŠ” λ‹«ν˜€μžˆμ–΄μ•Ό ν•œλ‹€
  • 좔상화 μ‚¬μš©μ„ ν†΅ν•œ 관계 ꡬ좕을 ꢌμž₯

λ¦¬μŠ€μ½”ν”„ μΉ˜ν™˜ 원칙

  • μ„œλΈŒ νƒ€μž…μ€ μ–Έμ œλ‚˜ 기반(λΆ€λͺ¨) νƒ€μž…μœΌλ‘œ ꡐ체할 수 μžˆμ–΄μ•Ό ν•œλ‹€
  • μƒμœ„ 클래슀 νƒ€μž…μœΌλ‘œ 객체λ₯Ό μ„ μ–Έν•˜μ—¬ ν•˜μœ„ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ°›μœΌλ©΄ μ—…μΊμŠ€νŒ… 된 μƒνƒœμ—μ„œ λΆ€λͺ¨μ˜ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄λ„ λ™μž‘μ΄ μ˜λ„λŒ€λ‘œ ν˜λŸ¬κ°€μ•Ό ν•˜λŠ” 것

μΈν„°νŽ˜μ΄μŠ€ 뢄리 원칙

  • μΈν„°νŽ˜μ΄μŠ€λ₯Ό 각각 μ‚¬μš©μ— 맞게 끔 잘게 λΆ„λ¦¬ν•΄μ•Όν•œλ‹€
  • ν΄λΌμ΄μ–ΈνŠΈμ˜ λͺ©μ κ³Ό μš©λ„μ— μ ν•©ν•œ μΈν„°νŽ˜μ΄μŠ€ λ§Œμ„ 제곡

의쑴 μ—­μ „ 원칙

  • μ–΄λ–€ Classλ₯Ό μ°Έμ‘°ν•΄μ„œ μ‚¬μš©ν•΄μ•Όν•˜λŠ” 상황이 생긴닀면 κ·Έ Classλ₯Ό 직접 μ°Έμ‘°ν•˜λŠ” 것이 μ•„λ‹ˆλΌ κ·Έ λŒ€μƒμ˜ μƒμœ„ μš”μ†Œ(좔상 클래슀 or μΈν„°νŽ˜μ΄μŠ€)둜 μ°Έμ‘°ν•˜λΌ
  • μΈν„°νŽ˜μ΄μŠ€μ— μ˜μ‘΄ν•΄λΌ
Β