Home IoC, DI, AOP
Post
Cancel

IoC, DI, AOP

DI(Dependency Injection)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base64Encoder{

    public String encode(String message){
        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}
    
class UrlEncoder{
    
    public String encode(String message){
        return URLEncoder.encode(message, "UTF-8");
    }
}
    
public static void main(String args[]){

    String url = "www.naver.com/books/it?page=12&size=20&name=spring";
    		
    Encoder encoder = new Base64Encoder();
    //Encoder encoder = new UrlEncoder();
    String result = encoder.encode(url);
}

위와 같은 코드를 작성하면 인코딩 방법이 바뀔 때마다 객체를 새로 생성하고 컴파일해야한다. encode라는 같은 동작의 메서드들이 있으므로 이를 Interface로 만들어 처리 하는 것이 좋다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface IEncoder{

    String encode(String message);
}
    
class Base64Encoder implements IEncoder{

    public String encode(String message){
        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}
    
class UrlEncoder implements IEncoder{

    public String encode(String message){
        return URLEncoder.encode(message, "UTF-8");
    }
}
    
public static void main(String args[]){
    
    String url = "www.naver.com/books/it?page=12&size=20&name=spring";
   
    IEncoder encoder = new Base64Encoder();
    //IEncoder encoder = new UrlEncoder();
    String result = encoder.encode(url);
}

하지만 위와 같이 인터페이스를 추가해도 main문에서는 큰 변화를 찾을 수 없다. 여기에 DI를 추가하면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public interface IEncoder{

    String encode(String message);
}
    
class Base64Encoder implements{

    public String encode(String message){
        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}
    
class UrlEncoder implements{
    
    public String encode(String message){
        return URLEncoder.encode(message, "UTF-8");
    }
}
    
class Encoder{
    
    private IEncoder iEncoder;

    public Encoder(IEncoder encoder){
        this.iEncoder = encoder;
    }

    public String encode(String message){
        return iEncoder.encode(message);
    }
}
    
public static void main(String args[]){

    String url = "www.naver.com/books/it?page=12&size=20&name=spring";
    		
    Encoder encoder = new Encoder(new Base64Encoder());
    //Encoder encoder = new Encoder(new UrlEncoder());
    String result = encoder.encode(url);
}

위의 코드처럼 외부로부터 사용할 객체를 주입 받는것이 DI이다. Encoder 클래스의 입장에서는 iEncoder를 외부로부터 받아서 사용하므로(의존성을 가지고 있는것을 주입 받았다) DI라고 부른다. DI의 장점은 아래와 같다.

  • 의존성으로 부터 격리시켜 코드 테스트에 용이하다.
  • DI를 통해 불가능한 상황을 Mock와 같은 기술을 통해 안정적으로 테스트 가능하다.
  • 코드를 확장하거나 변경 할 때 영향을 최소화 한다.(추상화)
  • 순환 참조를 막을 수 있다.

    IoC(Inversion Of Control) _ 제어의 역전

  • DI의 마지막 코드를 보면 여전히 객체를 개발자가 관리한다.(직접 new) Spring에서 객체를 관리하게 하기 위해 Component Annotation을 사용할 수 있다.
  • Component Annotation을 작성하면 해당 클래스는 Spring bean으로 만들어 Spring이 관리하게 된다. Spring이 실행 될 때 Component Annotation이 붙은 클래스를 찾아 직접 객체를 singleton형태로 만들어 Spring container에서 관리한다.
  • Configuration Annotation과 Bean Annotation으로 직접 bean으로 등록할 수 있다.
    • Bean Annotation의 경우 메서드에만 사용 가능하며 Configuration은 여러개의 Bean을 관리한다.
  • 만약 Spring이 Bean을 구분하지 못하는 경우 Qualifier를 사용해 이름을 명시해 줘야한다.
  • 스프링에서는 일반적인 JAVA객체를 new로 생성해 개발자가 관리 하는 것이 아닌 Spring container에게 모두 맡긴다.
  • 즉, 개발자에서 프레임워크로 제어의 객체 관리의 권한이 넘어갔으므로 제어의 역전 이라고 한다.

    AOP(Aspect Oriented Programming) _ 관점지향 프로그래밍

  • AOP를 사용해 로깅, 트랜잭션 관리, 시큐리티에서 적용 등 AspectJ와 같이 완벽하게 구현된 AOP와 통합하여 사용 가능하다.
  • 스프링 어플리케이션은 대부분 특별한 경우를 제외하고는 MVC웹 어플리케이션에서 Web Layer, Business Layer, Data Layer로 정의한다.
    • Web Layer : REST API를 제공하며, Client 중심의 로직 적용
    • Business Layer : 내부 정책에 따른 logic을 개발하며, 주로 해당 부분을 개발
    • Data Layer : 데이터 베이스 및 외부와의 연동을 처리
  • 특정 구역의 반복되는 로직을 한 곳에 몰아서 개발할 수 있게 해준다.
  • 주요 Annotation
    • Aspect : 자바에서 널리 사용하는 AOP 프레임워크에 포함되며, AOP를 정의하는 Class에 할당
    • Pointcut : 기능을 어디에 적용시킬지, 메소드 Annotation 등 AOP를 적용 시킬 지점 설정
    • Before : 메소드 실행하기 이전
    • After : 메소드가 성공적으로 실행 후, 예외가 발생 되더라도 실행
    • AfterReturing : 메소드 호출 성공 실행 시(Not Throws)
    • AfterThrowing : 메소드 호출 실패 예외 발생(Throws)
    • Around : Before/ After 모두 제어
This post is licensed under CC BY 4.0 by the author.