๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

WINK-(Web & App)/Spring Boot ์Šคํ„ฐ๋””

[2025 1ํ•™๊ธฐ ์Šคํ”„๋ง ๋ถ€ํŠธ ์Šคํ„ฐ๋””] ์ด์ƒ๋ž˜ #7์ฃผ์ฐจ

๋ฐ˜์‘ํ˜•

๐Ÿ”  AOP

๐Ÿ‘€ AOP๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ

  • ๋ชจ๋“  ๋ฉ”์†Œ๋“œ์˜ ํ˜ธ์ถœ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?
  • ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ(cross-cutting concern) vs ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ(core concern)
  • ํšŒ์› ๊ฐ€์ž… ์‹œ๊ฐ„, ํšŒ์› ์กฐํšŒ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

์ด๋Ÿฐ์‹์œผ๋กœ ์ž‘๋™ ๋ฉ๋‹ˆ๋‹ค

package hello.hellospring.service;
@Transactional
public class MemberService {
/**
* ํšŒ์›๊ฐ€์ž…
*/
public Long join(Member member) {
long start = System.currentTimeMillis();
try {
validateDuplicateMember(member); //์ค‘๋ณต ํšŒ์› ๊ฒ€์ฆ
memberRepository.save(member);
return member.getId();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("join " + timeMs + "ms");
}
}
/**
* ์ „์ฒด ํšŒ์› ์กฐํšŒ
*/
public List<Member> findMembers() {
long start = System.currentTimeMillis();
try {
return memberRepository.findAll();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("findMembers " + timeMs + "ms");
}
}
}
    • long start = System.currentTimeMillis(); : ์‹œ๊ฐ„ ํ•จ์ˆ˜ (์‹œ์ž‘ ์ง€์ )
    • long finish = System.currentTimeMillis(); : ์‹œ๊ฐ„ ํ•จ์ˆ˜ ( ์ข…๋ฃŒ ์ง€์ )
    • long timeMs = finish - start; : ๊ฑธ๋ฆฐ์‹œ๊ฐ„

๐Ÿ‘€  ๋ฌธ์ œ์ 

  1. ํšŒ์›๊ฐ€์ž…, ํšŒ์› ์กฐํšŒ์— ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์€ ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ์ด ์•„๋‹ˆ๋‹ค.
  2. ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์€ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์ด๋‹ค.
  3. ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง๊ณผ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค์˜ ๋กœ์ง์ด ์„ž์—ฌ์„œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๋‹ค.
  4. ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋ณ„๋„์˜ ๊ณตํ†ต ๋กœ์ง์œผ๋กœ ๋งŒ๋“ค๊ธฐ ๋งค์šฐ ์–ด๋ ต๋‹ค.
  5. ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋ณ€๊ฒฝํ•  ๋•Œ ๋ชจ๋“  ๋กœ์ง์„ ์ฐพ์•„๊ฐ€๋ฉด์„œ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

 

๐Ÿ‘€  AOP ์ ์šฉ

AOP : Aspect Oriented Programming

 

๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ(cross-cutting concern) vs ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ(core concern) ๋ถ„๋ฆฌ

package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@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");
}
}
}

์ด๋Ÿฐ์‹์œผ๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด

  • ํšŒ์›๊ฐ€์ž…, ํšŒ์› ์กฐํšŒ๋“ฑ ํ•ต์‹ฌ ๊ด€์‹ฌ์‚ฌํ•ญ๊ณผ ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ ๋ถ„๋ฆฌ
  • ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š” ๋กœ์ง์„ ๋ณ„๋„์˜ ๊ณตํ†ต ๋กœ์ง์œผ๋กœ 
  • ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ๊น”๋”ํ•˜๊ฒŒ ์œ ์ง€
  • ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜๋ฉด ์ด ๋กœ์ง๋งŒ ๋ณ€๊ฒฝ
  • ์›ํ•˜๋Š” ์ ์šฉ ๋Œ€์ƒ ์„ ํƒ ๊ฐ€๋Šฅ

๐Ÿ‘€  ์Šคํ”„๋ง์˜ AOP ๋™์ž‘ ๋ฐฉ์‹

-AOP ์ ์šฉ ์ „ ์˜์กด๊ด€๊ณ„

-AOP ์ ์šฉ ์ „ ์ „์ฒด ๊ทธ๋ฆผ

 

-AOP ์ ์šฉ ํ›„ ์˜์กด๊ด€๊ณ„

-AOP ์ ์šฉ ํ›„ ์ „์ฒด ๊ทธ๋ฆผ

๋ฐ˜์‘ํ˜•