Backend/Spring

[Spring] Spring MVC์—์„œ AOP ์„ค์ • (feat. ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์™€ ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ)

mirae.kwak 2023. 10. 24. 11:56
728x90

๐Ÿฅ‘ AOP

  • ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Aspect Oriented Programming)
  • ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ๊ณผ ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์„ ๋ถ„๋ฆฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹
  • ํ•ต์‹ฌ ๊ด€์‹ฌ ์‚ฌํ•ญ์— ์ ์šฉ๋˜๋Š” ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ๋ชจ๋“ˆ๋กœ ๋งŒ๋“ค์–ด ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ด๊ณ  ํ•ต์‹ฌ ๋กœ์ง์— ์ง‘์ค‘ํ•œ๋‹ค.
  • ์Šคํ”„๋ง์—์„œ AOP
    • target์— ๋Œ€ํ•ด ํ”„๋ก์‹œ๋กœ ๊ฐ์‹ธ๊ณ 
    • ํ”„๋ก์‹œ๊ฐ€ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ์ด๋‚˜ ๋ฐ˜ํ™˜ ์‹œ์— ์ด๋ฅผ ๊ฐ€๋กœ์ฑ„์„œ
    • advice์— ๋”ฐ๋ผ Aspect์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ target ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

 

๐Ÿ“ Spring MVC์— AOP ์ ์šฉํ•˜๊ธฐ

๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ (Aspect)

  • ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ๋ชจ๋“ˆ ์ƒ์„ฑ
  • @Aspect ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๊ณตํ†ต ๊ด€์‹ฌ ์‚ฌํ•ญ์ž„์„ ์„ค์ •
  • @Pointcut ์• ๋…ธํ…Œ์ด์…˜๊ณผ, ์‹œ์ (@Before, @AfterReturning, @AfterThrowing, @After, @Around)์„ ์„ค์ •ํ•˜์—ฌ Advice ์ƒ์„ฑ

 

Controller, Service, Repository ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๋งˆ๋‹ค ๋กœ๊ทธ๋ฅผ ์ฐ๋Š” Aspect

@Component
@Aspect
public class LoggingAspect {
	
	private final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
	
	@Pointcut("execution(* com..*.controller.*.*(..)) || execution(* com..*.model..*.*(..))")
	public void allMethod() {};
	
	@Before("allMethod()")
	public void debug(JoinPoint jp) {
		logger.debug("{} ๋ฉ”์†Œ๋“œ ์‹คํ–‰ - ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ {}",
				jp.getSignature(),
				jp.getArgs());
	}
}

 

xml ์„ค์ •

root-contex.xml

  • ์›น๊ณผ ๊ด€๋ จ๋œ ์„ค์ •์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ์„ค์ •์„ ํ•˜๋Š” xml
  • controller๋ฅผ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ๋นˆ ๋“ฑ๋ก
  • aop๋ฅผ ์œ„ํ•œ auto-proxy ์„ค์ •
<context:component-scan base-package="com..model, com..util, com..aop"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

servlet-contex.xml

  • ์›น๊ณผ ๊ด€๋ จ๋œ ์„ค์ •์„ ํ•˜๋Š” xml
  • controller ๋นˆ ๋“ฑ๋ก
  • controller์— ๋Œ€ํ•ด aop๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ auto-proxy ์„ค์ •
<context:component-scan base-package="com.*.controller" />
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

 

๐Ÿ“‘ AOP ์„ค์ •์— ๋”ฐ๋ฅธ ์ž‘๋™ ๋ฐฉ์‹

์ค‘๋ณต๋œ ๋นˆ์— ๋Œ€ํ•œ Spring MVC์˜ ๋นˆ ์„ ํƒ

  • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์™€ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์— ๋นˆ์„ ์ค‘๋ณต์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋•Œ ์„œ๋ธ”๋ฆฟ ์ปจํ…์Šค์˜ ๋นˆ์ด ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ๊ฐ€๋ฆฐ๋‹ค.
    • ์ฆ‰ ๋™์ผํ•œ ์ด๋ฆ„์˜ ๋นˆ์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค๋ฉด ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ์šฐ์„ ์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์—์„œ ๋นˆ์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋ฉด ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ์‚ฌ์šฉํ•œ๋‹ค.
    • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์— ํ•ด๋‹น ์ด๋ฆ„์˜ ๋นˆ์ด ์—†๋‹ค๋ฉด, ์Šคํ”„๋ง์€ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์—์„œ ํ•ด๋‹น ์ด๋ฆ„์˜ ๋นˆ์„ ๊ฒ€์ƒ‰ํ•œ๋‹ค.
  • ๋นˆ์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์™€ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ๊ตฌ์„ฑํ•  ๋•Œ ์ค‘๋ณต ์ •์˜์— ์ฃผ์˜ํ•ด์•ผํ•œ๋‹ค.
    • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํŠนํ™”๋œ ๋นˆ(ex controller)๋ฅผ ์ •์˜ํ•˜๊ณ , 
    • ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ๊ณต์œ ํ•ด์•ผํ•˜๋Š” ๋นˆ(ex service, repository)๋ฅผ ์ •์˜ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

 

 

1. ๋ชจ๋“  ๋นˆ์— aop๋ฅผ ์ ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

# servlet-context.xml
<context:component-scan base-package="com.*.controller" />
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

# root-context.xml
<context:component-scan base-package="com..model, com..util, com..aop"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • ์œ„์˜ ์„ค์ •ํŒŒ์ผ ์ฒ˜๋Ÿผ ์„ค์ •ํ–ˆ์„ ๊ฒฝ์šฐ root, servlet context ๋ชจ๋‘ auto-proxy ์„ค์ •์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—
  • ๋ชจ๋“  ๋นˆ์— ๋Œ€ํ•ด์„œ proxy๋กœ ๊ฐ์‹ธ์ง„๋‹ค.
  • ๋”ฐ๋ผ์„œ ๋ชจ๋“  controller, service, repository ์š”์ฒญ ์‹œ์— ๋กœ๊น… ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
  • ์ด๋•Œ controller๋Š” ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ, ๋‚˜๋จธ์ง€๋Š” ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ์‚ฌ์šฉํ•œ๋‹ค.

 

2. controller ๋นˆ์— aop๋ฅผ ์ ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ

# servlet-context.xml
<context:component-scan base-package="com.*.controller" />

# root-context.xml
<context:component-scan base-package="com..model, com..util, com..aop"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์—์„œ auto-proxy ์„ค์ •์„ ์ œ๊ฑฐํ•œ๋‹ค.
  • ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ์‚ฌ์šฉํ•˜๋Š” controller๋Š” ํ”„๋ก์‹œ๋กœ ๊ฐ์‹ธ์ง€์ง€ ์•Š๊ณ 
  • ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๋‚˜๋จธ์ง€ ๋นˆ๋“ค์— ๋Œ€ํ•ด์„œ๋Š” ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์˜ ์„ค์ •์— ๋”ฐ๋ผ auto-proxy๊ฐ€ ์ ์šฉ๋œ๋‹ค.

 

3. ์„œ๋ธ”๋ฆฟ, ๋ฃจํŠธ ๋ชจ๋‘ controller ๋นˆ์„ ๊ฐ€์งˆ ๋•Œ aop๋ฅผ ์ ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ

# servlet-context.xml
<context:component-scan base-package="com.*.controller" />

# root-context.xml
<context:component-scan base-package="com" />
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ๋นˆ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
  • ์ด๋•Œ ์Šคํ”„๋ง์€ ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์˜ controller ๋นˆ์„ ์„ ํƒํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋นˆ์€ ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์—์„œ ์„ ํƒํ•œ๋‹ค.
  • ๋”ฐ๋ผ์„œ ๋‚˜๋จธ์ง€ ๋นˆ์— ๋Œ€ํ•ด์„œ๋งŒ auto-proxy๊ฐ€ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— controller ๋นˆ์— ๋Œ€ํ•ด์„œ๋Š” aop๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.
    • controller์˜ ๋นˆ์ด ๋ฃจํŠธ ์ปจํ…์ŠคํŠธ์—๋„ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— auto-proxy ์„ค์ •์ด ์ ์šฉ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ
    • ์Šคํ”„๋ง์ด ์‚ฌ์šฉํ•˜๋Š” controller ๋นˆ์€ ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์˜ ๋นˆ์ด๊ธฐ ๋•Œ๋ฌธ์— aop๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค

 

๐Ÿ’ก ๊ฒฐ๋ก 

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ž‘๋™ ๋ฐฉ์‹์— ๋”ฐ๋ผ aop ์„ค์ •์„ ์œ ์˜
  • ์ค‘๋ณต๋œ ๋นˆ ์„ค์ •์„ ํ”ผํ•˜๊ณ , aop๋ฅผ ์ ์šฉํ•  ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•ด auto-proxy ์„ค์ •
728x90