[Spring] 어노테이션(@annotation)

BBANG-JUN·2021년 4월 15일
0

🍃Spring

목록 보기
20/26
post-thumbnail

본 글은 주관적으로 이해하기 위해 작성된 글입니다.
혹시 틀린 부분이 있을 수도 있습니다.
지적해주시거나 남겨주시면 감사히 반영하도록 하겠습니다.

🔹 : JAVA 파일
🔸 : xml 파일
💬 : 멘트


❓ 작성이유

문득 궁금했다.
회사 프로젝트에서 mapper 부분에 @SessionLogin 이라는 어노테이션을 만들어 사용하시는 것을 보고 어떤 원리로 로그인 정보들이 담겨오는지 궁금했다.

@SessionLoginId
public int aaa(VO vo) ;
@SessionLoginId
public int bbb(VO vo ;

어노테이션(@ : annotation)

출처 : 넥스트리.io

  • 과일에 붙는 라벨지와 비슷하다고 예시 글을 본 적 있다.
  • 실행하는 곳에 라벨지를 붙여서 해당 라벨지를 통해 다른 메서드를 실행해서 정보들을 담을 수도 있고 넣어줄 수도 있다.
  • 회사에서는 로그인을 하면 해당 사용자 정보를 불러오는 SET하여 담아주는 어노테이션을 선언했다.

🔹 sessionLogin.class

가장 먼저 @SessionLoginimport해오는 경로를 찾아가 보았다.

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SessionLoginId {

}

💬
??? 진짜 이게 다야?

🔥 여기서 알게된 사실

  • @interface로 어노테이션 클래스를 만들 수 있다.
  • @Target 으로 필드, 메소드, 클래스, 파라미터 등 선언할 수 있는 타입을 설정.
  • @Retention 으로 어느 시점까지 어노테이션의 메모리를 가져갈 지 설정.
  • @Documented는 어노테이션을 사용하는 클래스가 javadoc과 같은 문서화 될 때,
    해당 어노테이션이 적용되었음을 명시함.

💬
해당 어노테이션을 어디서 다루는지 찾아보아야 했는데 어디에도 없었다...
그래서 자문을 구해보니, 해당 @sessionLogin 클래스를 import 해서 사용하는 부분을 알 수 있었다.

🔹 MapperSessionLogin.class

import ...........anotation.SessionLoginId; 

해당 파일에서는 SessionLoginId.class를 import 선언!

...... if( .getAnnotation(SessionLoginId.class) == null ){
	return 종료;
}

로그인이 되어있다면, 정보를 다른 vo객체에 set하여 가져오는 방식이었다.
그렇지 않다면, return으로 해당 메서드를 로그인 정보를 담지 않고 종료시키게 된다.

💬
결국 어노테이션의 역할공통적인 메서드를 실행시켜야 한다면 원하는 곳에 라벨처럼 붙어 해당 메서드를 실행시키게 해주는 역할인가 보다.

그럼 왜 저 메서드는 어떻게 실행되는 거지?
라고 생각했을 때, servlet(서블릿)에서 따로 커스터마이징 하여 동작한다는 주임님의 말씀이 있었다.

servlet(서블릿)

  • 자바 서블릿은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며, 흔히 "서블릿"이라 불린다.
  • 자바 서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종이다.

💬
서블릿을 접근하면 Spring의 실행 순서에 대해서 잘 파악해야한다.

🕛 Spring 실행 순서

사진 출처 : ↗전디버거의 코딩이야기

💬
그림의 구조를 보면 View ➡ DispatcherServlet로 갔다.
DispatcherServlet는 web.xml에 포함되어 있다 하는데
web.xml에는 다음과 같은 코드가 있었다.

🔸 web.xml

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
		classpath*:egovframework/spring/context-*.xml
	</param-value>
  </context-param>

💬
정리하면,
Spring이 실행
➡ web.xml 구동
➡ web.xml의 코드 실행
➡ 위의 코드인 해당 경로의 context-*.xml 이 다 실행 ‼

이거다.
다시 거슬러 올라가 그럼 resources/egoframwork/spring/context-*.xml 파일들을 확인해보았다.

🔸 context-aspect.xml

바로 아까보았던 🔹 MapperSessionLogin.class가 여기 선언되어 있었다.


<aop:config>
		
        // pointcut : mapper에서 pointcut ( mapper에서만 동작하라는 뜻 )
        <aop:pointcut id="mapperMethod" expression="execution(* 경로..mapper.*Mapper.*(..))" />

        // aspect : mapperMethod 전에 실행
	<aop:aspect ref="MapperSessionLogin">
            <aop:around pointcut-ref="mapperMethod" method="before" />
        </aop:aspect>

</aop:config>
    
    // 해당 경로를 bean 설정(import같은?)
    <bean id="MapperSessionLogin" class="경로.MapperSessionLogin" />

💬
간단하게 이해 한것을 주석으로 표현해보았지만, 확답은 아닐 것이다.
이를 이해하려고 하면 aop 라는 것을 알아보아야 했다.

AOP(관점 지향 프로그래밍)

출처: 새로비

어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하겠다는 것이다.

  • Aspect : 위에서 설명한 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화함.
  • Target : Aspect를 적용하는 곳 (클래스, 메서드 .. )
  • Advice : 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체.
  • JointPoint : Advice가 적용될 위치, 끼어들 수 있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능.
  • PointCut : JointPoint의 상세한 스펙을 정의한 것. 구체적으로 Advice가 실행될 지점을 정할 수 있음.

✅ 결론

➡ : 실행 순서
💨 : 명령

Spring 실행
➡ 🔸 web.xml 실행중 (💨 🔸 context-*.xml 모두 실행)
➡ 🔸 context-aspect.xml 실행중 (💨 선언된 aop에 따라 🔹 MapperSessionLogin.class 수행 )
➡ 🔹 MapperSessionLogin.class 실행되게 aop 적용 (🔹 sessionLogin.class 포함)

@sessionLogin 포함된 mapper 실행
➡ aop로 정의되어 🔹 MapperSessionLogin.class 동작
.getAnnotation(sessionLogin.class) == null 로 로그인 유무 체크
➡ 존재하면 로그인 정보가 담긴 VO 객체에 set하여 map형식으로 기존에 담길 vo객체에 합쳐sql로 내려줌

💬
사용방법은 명시되어 있지 않아 이해하기 어렵겠지만
어떤식으로 어노테이션이 활용되는지 간략하게 적어보았습니다.

profile
🔥 머릿속으로 생각하지만 말고, 행동으로 보여줘

0개의 댓글