Spring AOP

AOP란?

  • Aspect Oriented Programming: 관점 지향 프로그래밍
  • OOP 와 분리된 개념이 아니라, OOP에 기초를 두는 프로그래밍 방식
  • 하나의 프로그램을 관점(혹은 관심사)라는 논리적인 다위로 분리하여 관리하는 개념
  • 로깅, 감사, 선언적 트랜젝션, 보안, 캐싱 등 다양한 곳에서 사용된다.
  • 낮은 결합도에 높은 응집도는 기본으로 가지며, DI는 낮은 결합도를 위한 것이라면 AOP는 높은 응집도를 위한 것이다.
  • 엔터프라이즈 어플리케이션들은 보통 핵심 비즈니스 로직은 몇 줄 안되고 주로 로깅이나 예외, 트랜잭션 처리 같은 부가 코드가 대부분이다. 즉 비지니스 메소드의 복잡도는 증가하며 메소드들 마다 매번 반복해야하는 경우가 생긴다.
  • 이를 해결하기 위해서는 단순복사 붙여넣기만으로는 코드중복이 많아지며 유지보수가 힘들어지기 때문에 AOP를 통해 부가적인 공통 코드들을 효율적으로 관리해야한다.
  • 위 내용을 다르게 말하면 기존 OOP에서 공통 관심 기능을 여러 모듈에서 적용하며 발생하는 중복코드 양산의 한계를 극복하기위해 AOP가 탄생했다고 볼 수 있다.
  • 또 이러한 AOP는 흩어진 Aspect들을 모아서 모듈화 하는 기법이다.
    • *Aspect란?
    • 객체지향 언어의 클래스와 비슷한 개념이며 그 자체로 어플리케이션의 도메인 로직을 담은 핵심 기능은 아니지만, 많은 오브젝트의 걸쳐서 필요한 부가기능을 추상화 해놓은 것이다.
  • AOP에서 중요한 점으로는 관심 분리(Separation of Concerns) 가 있습니다.
    • 로깅, 예외, 트랜잭션 처리같은 코드들은 횡단 관심(Crosscutting Concerns) 라고하며, 핵심 비즈니스 로직은 핵심 관심(Core Concerns)라고 합니다.

AOP 용어와 개념

  • AOP는 핵심 로직에서 공통관심기능을 호출하지 않고 위빙(Weaving)이라는 작업을 통해 공통 관심 기능코드를 추가합니다.
  • 이런 위빙을 하기위해서는 언디에, 언제 추가해야할지 알아야 하며 Pointcut(어디에), Advice(언제)라고 합니다.
  • Joint Point : 모듈이 삽입되어 동작하게 되는 특정 위치(메서드 호출 등), 클라이언트가 호출하는 모든 비즈니스 메소드, 모든 메소드를 조이포인트로 생각하면 되고, 이 중에서 포인트컷이 결정된다.
  • Point Cut : 다양한 Joint Point 중에 어떤 것을 사용할지 선택, 즉 필터링된 Joint Point를 의미한다. 하나의 @Aspect class 안에 여러 개의 포인트컷을 선언할 수도 있습니다.
  • //포인트컷 선언의 예 @Pointcut("excution(* hello(...))") // 포인트컷 파라미터는 없으며 표현식으로 정의 "excution ~" private void all() { }
  • Advice : Joint Point에 삽입되어 동작할 수 있는 코드, 어드바이스는 횡단 관심에 해당하는 공통 기능의 코드를 의미하며 독립된 클래스의 메서드로 작성된다. 언제 동작할지는 스프링 설정에서 결정한다.
  • Advice도 Pointcut과 마찬가지로 하나 이상을 정의할 수 있고, Advice의 Annotation에는 이에 적용할 Point cut을 명시해야 한다.
    • @AspectJ에서 5가지의 Advice
      • before : 메서드 호출 전에 동작하는 advice
      • after : 예외 발생 여부와 관계없이 호출된 메서드의 동작이 완료되면 동작하는 Advice
      • after-returning : 예외 없이 호출된 메서드의 동작이 완료되면 동작하는 Advice
      • after-throwing : 호출된 메서드의 동작이 완료되면 동작하는 Advice
      • around : 메서드 호출 전과 후에 동작하는 Advice
  • /* *포인트컷에 이름을 부여해서 따로 정의하는 대신 어드바이스 메소드 어노테이션에 포인트컷 표현식을 넣어서 *적용하는 방법도 있다. */ @Around("excution(* *(...))") public Onject printParametersAAndReturnVal(ProceedingJointPoint pjp) throws Throwable{ return pjp; }
  • //어드바이스 정의 예 @Around("all()") // all() 메소드가 호출되기 전 과정을 모두 담을 수 있다. public Object aroundExample(ProceedingJointPoint pjp) throws Throwable{ //proceed 메서드는 클라이언트가 보낸 파라미터를 그대로 사용해서 타깃 오브젝트의 메소드를 호출하고 그 결과를 돌려줌 Object ret = pjp.proceed(); return ret; }
  • Weaving : Advice를 핵심 로직 코드에 적용하는 것, 위빙을 통해 비지니스 메소드를 수정하지 않고 횡단 관심에 해당하는 기능을 추가하거나 변경 가능.
  • Aspect : Point Cut + Advice, Aspect는 포인트컷과 어드바이스의 결합 => 어떤 포인트컷 메서드에 어떤 어드바이스 메소드를 실행할지 결정한다. 
  • Reference

'Spring, Spring Boot' 카테고리의 다른 글

Spring Web Layer  (0) 2023.01.12
Spring MVC 동작과정  (0) 2023.01.11
SOLID 객체지향 설계의 5가지 원칙  (0) 2022.05.13
Spring 어노테이션(Annotation) 정리  (0) 2021.12.28

Spring Annotation 정리

Annotation 이란 ?

  • Anootation은 사전적 의미로 주석이라는 뜻이다. 자바에서 Annotation은 코드 사이에 주석처럼 쓰이며 특별한 의미, 기능을 수행하도록 제공하는 기술이다. 즉, 프로그램에게 추가적인 정보를 제공해주는 메타데이터 라고 볼 수 있다.
  • Annotation의 사용순서는 다음과 같다.
    1. 어노테이션을 정의한다.
    2. 클래스에 어노테이션을 배치한다.
    3. 코드실행 중 Reflection을 이용하여 추가 정보를 획득하여 기능을 실행한다.

Reflection 이란?

  • Reflection이란 프로그램 실행 중 자신의 구조와 동작을 검사,조사, 수정하는 것이다.

  • Reflection은 프로그래머가 데이터를 보여주고, 다른 포맷의 데이터를 처리,통신하기 위해 serialization(직렬화)를 수행하고, bundling하기 위해 일반 소프트웨어 라이브러리를 만들도록 도와준다.

  • Java와 같은 객체 지향 프로그래밍 언어에서 Reflection을 사용하면 컴파일 타임에 인터페이스, 필드, 메소드의 이름을 몰라도 실행 중 접근할 수 있다.

  • Java와 같은 객체 지향 프로그래밍 언어에서 Reflection을 사용해 멤버 접근 가능성 규칙을 무시할 수 있다. ex) reflection을 사용하면 서드 파티 라이브러리의 클래스에서 private 필드의 값을 변경할 수 있다.

  • Spring에서 BeanFactory라는 Container에서 객체가 호출되면 객체의 인스턴스를 생성하게 되고 이 때 필요하게 된다. 즉, 프레임워크에서 유연성있는 동작을 위해 사용된다.

  • Reflection을 이용하면 Annotation의 적용 여부와 엘리먼트 값을 읽고 처리할 수 있다.

  • 다음 메소드를 통해 정보를 얻을 수 있다.

  • Class.forName(), getName(), getModifier(), getFields(), getPackage()등..

  • Reflection을 이용하면 Annotation지정만으로도 원하는 클래스를 주입할 수 있다.

    //Without reflection
    Foo foo = new Foo();
    foo.hello();
    
    //With Reflection
    Object foo = Class.forName("complete.classpath.and.Foo").newInstance();
    //Alternatively: Object foo = Foo.class.newInstance();
    Method m = foo.getClass().getDeclaredMethod("hello", **new** Class<?>[0]);
    m.invoke(foo);

Annotation 종류

  • Component

    • @Component은 개발자가 직접 작성한 Class를 Bean으로 등록하기 위한 Annotation이다.

    • @Component
      public class Student{
        public Student() {
          System.out.println("hi");
        }
      }
      
      @Component(value="mystudent")
      public class Student{
        public Student() {
          System.out.println("hi");
        }
      }
    • Component에 대한 추가 정보가 없으면 class의 이름을 camelCase로 변경한 것이 Bean ID로 사용된다.

    • 하지만 @Bean 과 다르게 @Component 는 name 이 아닌 value를 이용해 Bean의 이름을 지정한다.

  • Autowired

    • @Autowired는 type에 따라 알아서 Bean을 주입한다. 한 객체에 대하여 의존성을 주입할 때 사용된다.

    • 스프링이 자동적으로 값을 할당하며 DAO나 Service에 관한 객체들을 주입 시킬 때 많이 사용한다.

    • 만약 필드, 생성자, 입력 파라미터가 여러개인 메소드일 경우 @Qualifier를 활용해 적용할 수 있다.

    • 만약 Autowired를 interface class에 사용했고 그 interface class를 상속받은 class가 여러개일 경우에는 에러가 발생하기 때문에 다음과같이 @Qualifier를 같이 명시해줘야한다.

      @Component("tv9")
      public class ssTV09 implements iTV
      {
        @Autowired //단일로 사용될 경우 여러개의 스피커가 존재하기 때문에 오류 발생.
        @Qualifier("enc") // encSpeaker를 사용하기위해 명시.
        private iSpeaker05 speaker;
      
        public ssTV09(iSpeaker05 speaker)
        {
          ...
        }
      }
  • Controller

    • Spring의 Controller를 의미한다. Spring MVC에서 Controller class에 쓰인다.

    • @Controller Annotation을 붙이면 핸들러가 스캔할 수 있는 Bean객체가 되 서블릿용 컨테이너에 생성된다. 마찬가지로 @Repository, @Service Annotation은 해당 class를 루트 컨테이너에 Bean객체로 생성해주는 Annotation이다.

    • 컨트롤러 : @Controller (프레젠테이션 레이어, 웹 요청과 응답을 처리)

    • 로직 처리 : @Service (서비스 레이어, 내부에서 자바 로직을 처리)

    • 외부I/O 처리 : @Repository (퍼시스턴스 레이어, DB나 파일같은 외부 I/O 작업을 처리)

    • 참고로 객체 내에서 데이터 변경 작업이 있는 VO(DTO) 객체와 같은 경우 동기화 문제로 인해 Bean객체로 사용하지 않는다. Bean 객체는 항상 데이터 변경이 없는 객체에 한해 사용하는 점에 유의해야 한다.

    • 연관지어 @WebServlet과 @Controller 의 차이에 대해 알아보자.

      • WebServlet과 Spring MVC Controller는 같은 일을 하는데 사용된다.

      • WebServlet은 서블릿을 선언할 때 사용되는 Annotation이며 이 Annotation이 사용된 클래스는 Servlet Container에 의해 처리된다. 사용시 속성 값을 통해 해당 Servlet과 매핑될 URL패턴을 지정한다.

      • @Target(value=TYPE)
        @Retention(value=RUNTIME)
        @Documented
        public @interface WebServlet
      • Controller는 @Component의 구체화된 역할을 한다. classpath scanning을 통해 구현 클래스를 자동으로 감지할 수 있도록 해준다. 일반적으로 RequestMapping Annotation을 기반으로 한 handler method와 함께 사용한다.

      • @Target(value=TYPE)
        @Retention(value=RUNTIME)
        @Documented
        @Component
        public @interface Controller
  • Repository, Service

    • @Repository는 간단하게 데이터베이스에 접근하는 method를 가진 class에 사용된다.

    • @Repository("userDAO")
      public class UserDAO {
          ...
      }
    • 다음과같이 DAO클래스를 명시해주면 루트 컨테이너에 Bean 객체로 생성되고 이 "userDAO"는 new를 이용해 생성하는게 아닌 컨테이너에서 받아와야 한다. 루트컨테이너는 어디서든 공유가능하기 때문에, 다음과같은 의존성 주입(DI)(@Resource, @Inject, @Autowired) Annotation을 이용해 객체를 받아올 수 있다.

    • Annotation들은 같은 Bean 객체에서만 작동하기 때문에 Bean으로 만들지 않은 일반 클래스에서는 사용해봤자 아무 소용 없다. 하지만 일부 DTO객체 등 데이터 변경 작업을 동반하는 클래스 외, 로직을 가진 클래스들은 대부분 @Service Annotation을 통해 Bean객체로 등록해주기 때문에 크게 문제되진 않는다.

    • 즉 @Repository는 DB접근과 관련된 코드가 모여있는 곳이고, @Service는 패키지를 확인하고 DB접근 외에 비즈니스 로직관련 코드가 모여있는 곳이라 생각하면 된다.

Reference

- https://www.inflearn.com/questions/77417 (Repository, Service 차이)

'Spring, Spring Boot' 카테고리의 다른 글

Spring Web Layer  (0) 2023.01.12
Spring MVC 동작과정  (0) 2023.01.11
SOLID 객체지향 설계의 5가지 원칙  (0) 2022.05.13
Spring AOP 정리  (0) 2022.01.01

액션태그(Action Tag)란?

- 액션태그란 JSP페이지 내에서 어떤 동작을 하도록 지시하는 태그 입니다. 예를 들어 페이지 이동, 페이지 include, 자바 빈 생성 등이 있다.

대표적인 액션 태그로는 다음 3가지가 있다.

1. forward

- forward는 현재 페이지를 다른 페이지로 전환할 때 사용한다.

- JSP컨테이너는 현재 JSP페이지에서 forward 액션 태그를 만나면 그 전까지 출력 버퍼에 저장되어 있던 내용을 폐기하고 forward 액션 태그에 명시된 페이지로 제어권이 넘어간다.

forward를 사용하는 방법은 다음과 같다.

<jsp:forward page="파일명"/> <!-- 파일명에 명시된 곳으로 포워딩이 이루어진다 -->
OR
<jsp:forward page="파일명"></jsp:forward>

2. include

- include Action Tag는 jsp페이지의 특정 영역에 외부 파일의 내용을 포함하는 태그이다.

- 현재 JSP페이지에 포함할 수 있는 외부파일은 HTML, JSP, Servlet 등이 있다.

다음과 같은 흐름에서 First.jsp파일 내부 jsp include Action Tag 를 이용해 다른 jsp 페이지를 요청한다.

 

3. param

- param Action Tag는 위 include Action Tag와 함께 사용되며 다른 페이지를 include 를 통해 호출 하는 시점에 넘겨주고 싶은 값을 명시할 때 쓰입니다.

- param Action Tag는 단독 사용이 불가능하며, forward, include Tag내부에 사용됩니다.

- 만약 전달해야하는 정보가 많다면 여러번의 param Tag를 포함하여 정보를 전달할 수 있습니다.

<jsp:forward page="파일명">
	<!-- forward Tag 내부 전달할 정보를 표기한다. -->
	<jsp:param name="변수이름" value="변수값"/>
    <jsp:param name="변수이름2" value="변수값2"/>
</jsp:forward>

 

 

- DAO(Data Access Object)

DAO란 데이터베이스의 데이터에 접근하기 위한 객체로 데이터의 삭제, 삽입, 조회 등의 기능만 수행하도록 만들어진 오브젝트를 의미합니다. 즉 DB와 연결하기 위해 커넥션 객체가 필요하고 이 커넥션 객체 한 개를 가지고 사용자의 접속이 종료될 때까지 모든 DB와 연결하는 객체를 의미합니다. 일반 객체와 다르게 반환 값이 존재하지 않고 커넥션 풀이 일어나지 않습니다.

 

-DTO(Data Transfer Object), VO(Value Object)

DTO란 VO로 바꿔말할 수 있습니다. 계층 간 데이터 교환을 위한 자바 빈즈를 말하며, 각 계층 컨트롤러, 뷰, 비즈니스, 퍼시스턴스 계층 간 데이터 교환을 위한 오브젝트로 VO도 역시나 역할은 동일하지만 Read-Only라는 특성을 가지고 있습니다.

 

'JAVA' 카테고리의 다른 글

Java - Logging 이란?  (1) 2024.11.12
[JAVA & Database] JDBC, MyBatis, JPA 의 차이점  (1) 2022.09.26
[Java] 언어의 특징  (2) 2022.09.09
[JAVA]직렬화 - Serializable란?  (0) 2022.05.16

+ Recent posts