AOP(Aspect Oriented Programming)
1. AOP๊ฐ ํ์ํ Example
public Long join(Member member){
long start = System.currentTimeMillis();
try{
//๊ฐ์ ์ด๋ฆ์ด ์๋ ์ค๋ณต ํ์X ๋ผ๊ณ ๊ฐ์
validateDuplicateMember(member); //์ค๋ณต ํ์ ๊ฒ์ฆ
memberRepository.save(member);
return member.getId();
}finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("join = " + timeMs + "ms");
}
}
๋ง์ฝ ์์ ๊ฐ์ด ํ์๊ฐ์ , ํ์์กฐํ ๋ฑ๋ฑ ์ฌ๋ฌ ๋ฉ์๋์์ ์๊ฐ ์ธก์ ์ ํด์ผํ๋ค๊ณ ๊ฐ์ ํ๊ณ ์๊ฐ ์ธก์ ์ฝ๋๋ฅผ ์ถ๊ฐํ์๋ค.
๋ฌธ์ ์
1. ํ์๊ฐ์ , ์กฐํ ๋ฑ์ ๊ธฐ๋ฅ์์ ์๊ฐ ์ธก์ ์ ํต์ฌ ๊ด์ฌ์ฌํญ X
2. ์๊ฐ ์ธก์ ๋ก์ง์ ๊ณตํต ๊ด์ฌ ์ฌํญO
3. ๋น์ง๋์ค ๋ก์ง์ ์๊ฐ ์ธก์ ๋ก์ง์ด ์์ฌ์ ์ ์ง๋ณด์๊ฐ ์ด๋ ค์.
4. ์๊ฐ์ ์ธก์ ํ๋ ๋ก์ง์ ๋ฐ๋ก ๋นผ์ ๊ณตํต ๋ก์ง์ผ๋ก ๋ง๋ค๊ธฐ๋ ์ด๋ ค์.
5. ๋ง์ฝ ์๊ฐ์ธก์ ๋ก์ง์ ๋ณ๊ฒฝํด์ผ ํ๋ฉด ํ๋์ฉ ๋ค ์ฐพ์๊ฐ๋ฉด์ ๋ณ๊ฒฝํด์ผ ํ๋ ๋์ฐํ ์ํฉ์ด ๋ฒ์ด์ง.
2. ๊ณตํต ๊ด์ฌ ์ฌํญ vs ํต์ฌ ๊ด์ฌ ์ฌํญ์ ๋ถ๋ฆฌ
- ๊ณตํต ๊ด์ฌ ์ฌํญ(cross-cutting concern)
- ํต์ฌ ๊ด์ฌ ์ฌํญ(core concern)
- ์คํ๋ง์์๋ ์์ ๊ฐ์ด ๊ณตํต ๊ด์ฌ ์ฌํญ์ ์ ์ฉ๊ฐ๋ฅํ๋๋ก ๊ธฐ์ ์ ์ง์ํ๋ค.
3. AOP ์ฌ์ฉํ์ฌ ๋ถ๋ฆฌ ํด๋ณด์!
(1) aop / TimeTraceAop.java
@Aspect
public class TimeTraceAop {
@Around("execution(* hello.hellospring..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{
long start = System.currentTimeMillis();
System.out.println("START: " + joinPoint.toString());
try{
return joinPoint.proceed(); //๋ฉ์๋๋ฅผ ์คํ
}finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
}
}
}
@Aspect๋ฅผ ๋ถ์ฌ์ค์ผ AOP๋ก ์ฌ์ฉํ ์ ์์.
@Around๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฉ์๋๋ฅผ ์ ์ฉํ ํด๋์ค๋ฅผ ์ง์ ํ ์ ์๋ค.
(2) SpringConfig.java
@Configuration
public class SpringConfig {
private final MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository);
}
@Bean
public TimeTraceAop timeTraceAop(){
return new TimeTraceAop();
}
}
AOPํด๋์ค๋ฅผ Bean์ผ๋ก ๋ฑ๋กํด์ค์ผ ํจ.
Component Scan๋ฐฉ์์ ์จ๋ ๋์ง๋ง ํน๋ณํ ํด๋์ค ์ด๋ฏ๋ก ์ง์ Bean์ผ๋ก ๋ฑ๋กํด์ฃผ๋๊ฒ ์ข๋ค.
ํ์๋ชฉ๋ก์ ํด๋ฆญํ์ฌ ์์ฒญ์ ๋ณด๋ด๋ณด๋ฉด ์์ ๊ฐ์ด
Controller, Service, Repository ์์ผ๋ก ์์๋๊ณ ์ญ์ผ๋ก ์ข ๋ฃ๋๊ณ ์๊ฐ ์ธก์ ์ด ๋๊ฑธ ๋ณผ ์ ์๋ค.
๊ฒฐ๊ณผ
- ์๊ฐ์ ์ธก์ ํ๋ ๋ก์ง์ ๋ณ๋์ ๊ณตํต ๋ก์ง์ผ๋ก ๋ง๋ค์ด ํต์ฌ ๊ด์ฌ์ฌํญ๊ณผ ๊ณตํต ๊ด์ฌ์ฌํญ์ ๋ถ๋ฆฌํ์๋ค.
- ๋ณ๊ฒฝํ๊ธฐ ํธํ์ฌ ์ ์ง๋ณด์์ ์ฉ์ดํ๋ค.
- AOP๋ฅผ ์ ์ฉํ๊ธฐ๋ฅผ ์ํ๋ ๋์์ ์ ํํ ์ ์๋ค.
4. AOP ๋ด๋ถ ๋์ ์๋ฆฌ
(1) AOP ์ ์ฉ ์ ์์กด๊ด๊ณ
(2) AOP ์ ์ฉ ํ ์์กด๊ด๊ณ
์คํ๋ง์ด ์ปจํ ์ด๋์ ๋น์ ๋ฑ๋กํ ๋ ์ง์ง Spring Bean๋ง๊ณ Proxy(๋๋ฆฌ, ๊ฐ์ง) Spring Bean์ ์ง์ง ์์ ๋ฑ๋กํด์ค๋ค. jointPoint๋ก ์ด๋ค ์คํ์ด ๋ฐ์ํ๋ฉด ๊ทธ๋ ์ง์ง Bean์ ํธ์ถ ํด์ค๋ค.
์ค์ ์ปจํธ๋กค๋ฌ๊ฐ @Autowired๋ก Service๋ฅผ ์๋ ์ฃผ์ ๋ฐ์ ๋ service.getClass()๋ฅผ ํตํด ์ด๋ค ํด๋์ค๊ฐ ์ฃผ์ ๋์๋์ง๋ฅผ ํ์ธํด๋ณผ ๋ ๊ทธ๋ฅ MemberService๊ฐ ์๋๋ผ ๋ค์ $$EnhancerBySpringCGLB ๊ฐ ๋ค์ ๋ถ์ Proxy Service ๊ฐ์ฒด๊ฐ ์ฃผ์ ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๋ค์ ์ถ๊ฐํด์ ๋งํ์๋ฉด @Configuration์ด ๋ถ์ผ๋ฉด @Bean์ด ๋ถ์ ๊ฒ์ ๋ํด์
์คํ๋ง์ด CGLB ๋ฐ์ดํธ์ฝ๋ ์กฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ํด๋น ํด๋์ค๋ฅผ ์์๋ฐ์ ์์์ Proxy ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ๊ทธ Proxy ํด๋์ค๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ฉด ์ฑ๊ธํค์ ๋ณด์ฅํ์ฌ ์์ ํ๊ฒ ๊ด๋ฆฌ ๊ฐ๋ฅํ๋ค.
(3) AOP ์ ์ฉ ์ ์ ์ฒด ์์กด๊ด๊ณ
(4) AOP ์ ์ฉ ํ ์ ์ฒด ์์กด๊ด๊ณ
์ด๊ฑธ Spring์์๋ Proxy๋ฐฉ์์ AOP๋ผ๊ณ ํ๋ค.
์ง๊ธ๊น์ง ์คํ๋ง ์ ๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ (๊น์ํ) ๊ฐ์๋ฅผ ์๊ฐํ๋ฉด์ Spring ์ ๋ฐ์ ์ธ ๋ด์ฉ์ ์๊ฒ ๋์๋ค.
์ด์ ํ๋ํ๋์ฉ ๋ํ ์ผ์ ์ถ๊ฐํ ์ฐจ๋ก๋ค.
์ด์ด์ ์คํ๋ง ํต์ฌ ์๋ฆฌ - ๊ธฐ๋ณธํธ(๊น์ํ) ๊ฐ์๋ฅผ ๋ค์ผ๋ฉฐ ์คํ๋ง์ ๋ณธ์ง๊ณผ ๊ฐ์ฒด ์งํฅ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ค๊ณ์ ์ํคํ ์ฒ๋ฅผ ์๊ฐํ ์ ์๋ ๋ฅ๋ ฅ์ ํค์ฐ๋ ค๊ณ ํ๋ค.
'๐ Backend > ๐ Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๊ฐ์ฒด์งํฅ ์ค๊ณ์ ์คํ๋ง (0) | 2022.07.02 |
---|---|
SOLID ์์น (0) | 2022.07.02 |
7. Spring DB ์ ๊ทผ ๊ธฐ์ - JPA, Spring Data JPA (0) | 2022.07.02 |
7. Spring DB ์ ๊ทผ ๊ธฐ์ - Spring JdbcTemplate (0) | 2022.07.02 |
7. Spring DB ์ ๊ทผ ๊ธฐ์ - JDBC (0) | 2022.07.02 |