You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
처음에 에러가 발생하는데, 부모에서 기본생성자가 아닌 생성자가 있는 경우 발생.
생성자가 있어야하고, super() 가 포함되어야함.(코드에 없으면 자동으로 super() 를 포함시키고 이러면 Service 의 경우 기본 생성자가 없어 에러 발생)
클래스 기반 프록시의 단점
super(null) : OrderServiceV2 : 자바 기본 문법에 의해 자식 클래스를 생성할 때는 항상 super()로 부모 클래스의 생성자를 호출해야 한다. 이 부분을 생략하면 기본 생성자가 호출된다. 그런데 부모 클래스인 OrderServiceV2 는 기본 생성자가 없고, 생성자에서 파라미터 1개를 필수로 받는다. 따라서 파라미터를 넣어서 super(..) 를 호출해야 한다.
프록시는 부모 객체의 기능을 사용하지 않기 때문에 super(null) 을 입력해도 된다.
프록시를 사용한 덕분에 원본 코드를 전혀 변경하지 않고, V1, V2 애플리케이션에 LogTrace 기능을 적용할 수 있었다.
인터페이스 기반 프록시 vs 클래스 기반 프록시
인터페이스가 없어도 클래스 기반으로 프록시를 생성할 수 있다.
클래스 기반 프록시는 해당 클래스에만 적용할 수 있다. 인터페이스 기반 프록시는 인터페이스만 같으면 모든 곳에 적용할 수 있다.
클래스 기반 프록시는 상속을 사용하기 때문에 몇가지 제약이 있다.
부모 클래스의 생성자를 호출해야 한다.(앞서 본 예제)
클래스에 final 키워드가 붙으면 상속이 불가능하다.
메서드에 final 키워드가 붙으면 해당 메서드를 오버라이딩 할 수 없다.
이렇게 보면 인터페이스 기반 프록시가 더 좋아보임.
인터페이스 기반 프록시는 상속이라는 제약에서 자유로움. 프로그래밍 관점에서도 인터페이스를 사용하는 것이 역할과 구현을 명확하게 나누기 때문에 더 좋다.
인터페이스 기반 프록시의 단점은 인터페이스가 필요하다는 그 자체이다.
참고: 인터페이스 기반 프록시는 캐스팅 관련해서 단점이 있는데, 이 내용은 강의 뒷부문에서 설명한다.
이론적으로는 모든 객체에 인터페이스를 도입해서 역할과 구현을 나누는 것이 좋다. 이렇게 하면 역할과 구현을 나누어서 구현체를 매우 편리하게 변경할 수 있다. 하지만 실제로는 구현을 거의 변경할 일이 없는 클래스도 많다.
인터페이스를 도입하는 것은 구현을 변경할 가능성이 있을 때 효과적인데, 구현을 변경할 가능성이 거의 없는 코드에 무작정 인터페이스를 사용하는 것은 번거롭고 그렇게 실용적이지 않다. 이런곳에는 실용적인 관점에서 인터페이스를 사용하지 않고 구체 클래스를 바로 사용하는 것이 좋다 생각한다.
(물론 인터페이스를 도입하는 다양한 이유가 있다. 여기서 핵심은 인터페이스가 항상 필요하지는 않다는 것이다.)
결론
실무에서는 프록시를 적용할 때 V1처럼 인터페이스도 있고, V2처럼 구체 클래스도 있다. 따라서 2가지 상황을 모두 대응할 수 있어야 한다.
그런데 지금 프록시는, 기존 코드를 변경하지 않고 로그남기는 기능을 적용할 수 있으나,
문제는 프록시 클래스가 너무 많이 들어간다.
프록시 클래스가 하는 일은 LogTrace를 사용하고 로그를 남기는것. 로직이 모두 똑같다.
적용하는 클래스가 100개라면 클래스도 100개를 만들어야한다.
프록시 클래스를 하나만 만들어서 모든 곳에 적용하는 방법은 없을까?
바로 다음에 설명할 동적 프록시 기술이 이 문제를 해결해준다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
구체 클래스 기반 프록시 - 적용
현재 v2 는 인터페이스 없이 구체 클래스로 구현
여기에 프록시를 넣어보자.
Repository 프록시 적용
Service 프록시 적용
처음에 에러가 발생하는데, 부모에서 기본생성자가 아닌 생성자가 있는 경우 발생.
생성자가 있어야하고, super() 가 포함되어야함.(코드에 없으면 자동으로 super() 를 포함시키고 이러면 Service 의 경우 기본 생성자가 없어 에러 발생)
클래스 기반 프록시의 단점
super(null):OrderServiceV2: 자바 기본 문법에 의해 자식 클래스를 생성할 때는 항상super()로 부모 클래스의 생성자를 호출해야 한다. 이 부분을 생략하면 기본 생성자가 호출된다. 그런데 부모 클래스인OrderServiceV2는 기본 생성자가 없고, 생성자에서 파라미터 1개를 필수로 받는다. 따라서 파라미터를 넣어서super(..)를 호출해야 한다.super(null)을 입력해도 된다.컨트롤러 프록시 적용
이제 컨피그로 만들어보자
인터페이스 기반 프록시와 클래스 기반 프록시
프록시를 사용한 덕분에 원본 코드를 전혀 변경하지 않고, V1, V2 애플리케이션에
LogTrace기능을 적용할 수 있었다.인터페이스 기반 프록시 vs 클래스 기반 프록시
이렇게 보면 인터페이스 기반 프록시가 더 좋아보임.
인터페이스 기반 프록시는 상속이라는 제약에서 자유로움. 프로그래밍 관점에서도 인터페이스를 사용하는 것이 역할과 구현을 명확하게 나누기 때문에 더 좋다.
인터페이스 기반 프록시의 단점은 인터페이스가 필요하다는 그 자체이다.
참고: 인터페이스 기반 프록시는 캐스팅 관련해서 단점이 있는데, 이 내용은 강의 뒷부문에서 설명한다.
이론적으로는 모든 객체에 인터페이스를 도입해서 역할과 구현을 나누는 것이 좋다. 이렇게 하면 역할과 구현을 나누어서 구현체를 매우 편리하게 변경할 수 있다. 하지만 실제로는 구현을 거의 변경할 일이 없는 클래스도 많다.
인터페이스를 도입하는 것은 구현을 변경할 가능성이 있을 때 효과적인데, 구현을 변경할 가능성이 거의 없는 코드에 무작정 인터페이스를 사용하는 것은 번거롭고 그렇게 실용적이지 않다. 이런곳에는 실용적인 관점에서 인터페이스를 사용하지 않고 구체 클래스를 바로 사용하는 것이 좋다 생각한다.
(물론 인터페이스를 도입하는 다양한 이유가 있다. 여기서 핵심은 인터페이스가 항상 필요하지는 않다는 것이다.)
결론
실무에서는 프록시를 적용할 때 V1처럼 인터페이스도 있고, V2처럼 구체 클래스도 있다. 따라서 2가지 상황을 모두 대응할 수 있어야 한다.
그런데 지금 프록시는, 기존 코드를 변경하지 않고 로그남기는 기능을 적용할 수 있으나,
문제는 프록시 클래스가 너무 많이 들어간다.
프록시 클래스가 하는 일은 LogTrace를 사용하고 로그를 남기는것. 로직이 모두 똑같다.
적용하는 클래스가 100개라면 클래스도 100개를 만들어야한다.
프록시 클래스를 하나만 만들어서 모든 곳에 적용하는 방법은 없을까?
바로 다음에 설명할 동적 프록시 기술이 이 문제를 해결해준다.
All reactions