문제상황

서비스에 멤버필드를 넣었고 해당 필드를 immutable 하게 만들기위해 final로 선언했고, @value로 값을 주입했다.

아래 그림처럼->

아래그림처럼 바로 "String이라는 빈이 없는데?" 라며 에러가 터져버린다.

음... @RequiredArgsConstructor를 통해서 생성자를 만들때 final이 잘 초기화 될거라 생각했는데.. 갑자기 String을 빈으로 인식해버리네..?

 

그럼 직접 생성자를 만들어서, 초기화를 시켜주는 방법을 고안해보았다. 먼저 아래그림처럼 생성자를 만들었다. 

생성자만 만들면 @RequiredArgsConstructor 때와 동일하게 String을 빈으로 인식해서 빈객체로 만들려한다.

 

그럼 결론적으로 빈이 아닌 멤버필드를 @value를 사용해서 immutable 하게  어떻게 쓸수있을까!?

아래그림처럼 선언하면 가능해진다.

정리

1. @RequiredArgsConstructor 는 생성자 파라미터가 무조건 빈이라고 보기때문에 생성자를 통해 객체를 만들때 에러가 나는거라 유추된다.

2. 직접 생성자를 만들어서 생성자를 통해 객체를 만들때 @Value를 통하여 이 파라미터가 빈이 아니라는걸 명시 가능!

와일드 카드 제네릭이란?

레퍼런스 타입의 제네릭을 좀더 넓게! 제한 하는것.

제한을 런타임 시점에 강제하는것.

 

이 두가지가 키포인트라 생각된다.

 

 

 

"레퍼런스 타입의 제네릭을 좀더 넓게! 제한하는것" 의미

일반적으로 List<Number> 이 되면 Number타입에 정확히 맞춰야한다.(자바의 강력한 타입 체킹)

그러나 제네릭 와일드 카드를 사용하게 되면 List<? extends Number> 처럼 쓸수 있고

이는 String 을 상속받는 하위 클래스들을 모두~유연~하게 사용할수 있다는 장점을 갖게 된다.!

 

"제한을 런타임 시점에 강제하는것" 의미

 

일반 제네릭은 <T extends Number> 처럼 제한을 무엇으로 할지를 컴파일 타임에 강제한다

그러나, 와일드카드 제네릭은 <? extends T> 처럼  제한을 런타임 시점에 강제한다.

 

 

결론

제네릭의 제한을 넓게, 런타임시점에 입맛에 맞게 하고 싶을때 쓰면 좋을듯 하다.

그런데 제네릭이란 본래 타입제한을 통한 에러를 걸러내는 역할도 하느것인데,, 너무 넓게 제한을 잡아버리면

그 본래 기능이 퇴색? 될수있기때문에 상황에 따라 잘써야겠다..!  

 

 

  • SAGA  패턴 : 보상 트랜잭션을 사용한 해결방법
    • 이벤트 드리븐 방식 :

      • 각 서비스의 트랜잭션에서 이벤트를 발생시킴.
      • 이벤트가 성공이면  다른 서비스의 트랜잭션을 수행시킨다. .

      • 이벤트가 실패면 다른 서비스에게 보상 트랜잭션을 수행시킨다.

      • 각 서비스들은 어떤 이벤트를 받아야하는지 알기가 쉽지않아..

       

    • Orderchestration 방식

      • 하나의 Orchstration 서비스에서 트랜잭션을 관리한다.
      • 결제 완료 프로세스 ( pg사 결제완료(pay) -> 포인트/쿠폰 소멸(member))

      • 이 결제 완료 서비스를 총괄하는 하나의 서비스가 있어야함. 그 어느 한서비스에서 뻑나면 롤백 프로세스를 태우면됨
      • 서비스간 종속이 없어져서 좋긴한데, orchestration 서비스 생성 리소스가 크게듬 

 

  • TCC( Try-cancle-comfirm ) : rest호출로 해결방법
    • staging repository와 실제 repository를 나눠 놓는것이 핵심 포인트!
    • try 단계에서는 staging repository에 작업을 함.
    • 한 프로세스가 문제없이 끝나면 그제서야, 실제 repository에 작업을함.
    • 한 프로세스에서 문제가 생기면 cancle api를 호출하여 staging repository에 저장된 data 상태를 "cancle"이나 지워놓으면 그만
 

REST 기반의 간단한 분산 트랜잭션 구현 - 1편 | Popit

REST 기반의 간단한 분산 트랜잭션 구현 -1편 TCC 개관 REST 기반의 간단한 분산 트랜잭션 구현 - 2편 TCC Cancel, Timeout REST 기반의 간단한 분산 트랜잭션 구현 - 3편 TCC Confirm(Eventual Consistency) REST 기반의

www.popit.kr

 

두가지 책으로 간단하게 정리했다.

 

- 디자인패턴입문 핵심내용

  • observer 패턴은 subject(피 관찰자)와 observer(관찰자)로 나뉜다

  • observer는 실제로 관찰자라는 의미지만 실제로 observer 패턴에서는 능동적인 관찰이라기 보다는 subject 로부터 상태가 바뀜?을 전달되는것을 기다립니다.  즉 Publish-Subscribe 패턴이라하는게 더 적당함.

 

 

- 헤드퍼스트 핵심내용

  • subject:obsever가 다대다가 될수 있음.

    • 예를들면 subject에 서울기상청, 부산기상청, 대전기상청은  한국기상청꺼를 사용하여 implement함,,  근데 나는 현재 서울기상청한테 publishing을 받아서 서울기상어플을만들었는데, 이제 부산기상어플로 바꾸려할때

  • subject가 observer에게 전달할때 본 객체자체를 넘기도록 하는게 좋다(푸시방식이 아닌 풀방식)

    • 옵저버들은 각자가 필요한 데이터들이 다를수있다. subject가 그 모두 다른 옵저버의 입맛을 챙겨주기엔 무리다.
    • 만약 subject가 확장되면서 정보들이 늘었다고치자, 그럼 퍼블릭 게터하나만 뚫어주면된다.   안그러면 메소드를 수정하는일이 생길거다.

       

'개발 > 디자인패턴' 카테고리의 다른 글

프록시 패턴 정리  (0) 2020.07.03

두가지 책에서 프록시 패턴을 정리해보았다.

 

- java 언어로 배우는 디자인 패턴 입문

    • Proxy의 뜻 "대리인"

    • 대리인이 본인을 대신해 대부분의 업무를 하다가, 중요하거나, 무거운 업무만 본인이 하게끔 하는 방식

    • 가상 프록시 패턴을 쓰는이유?

      • 속도 올리기: 인스턴스 생성이 불필요한 작업을 할때는 인스턴스를 초기화 안함으로써 그 리소스를 절약한다. lazy init!(가상프록시)

    • 등장주제는 주체 클래스, 프록시 클래스, 본인과 프록시가 구현하는 인터페이스 정도로 나뉨

    • 프록시 클래스, 본인 클래스는 강한결합이다.

      • 왜냐면 프록시 클래스가 본인클래스 필드 자체를 들고있기 떄문에..

      • 그런데 (Prinatable) Class.forName(className).newInstance() 처럼 리플렉션을 사용하면 Pritanble 구현한 본인 객체가 무엇이던간에  프록시 클래스는 영향을 안받을수있다..!  

- 헤드퍼스트

  • 프록시 패턴이란?

    • 어떤 객체에 대한 접근을 제어하기 위한 용도로 대리인에게 해당하는 객체를 제공하는 패턴

  • 프록시 패턴의 종류! 주요 3가지
    1. 원격 프록시  : 원격객체에 대한 프록시, 원격객체에 대한 접근을 마치 로컬에서 하듯이 한다.

      • 예 : 구글 docs..

    2. 가상 프록시 :  생성하는데 비용이 많이드는 객체에 대한 프록시. 생성비용이 많이드는 객체대신에 라이트한 프록시 객체가 대부분의 일을 대신하다가, 직접적 업무는 주체클래스가.

      • 예 : 배틀그라운드 초기 그래픽 초기화가 오래걸린다. 그렇기 때문에 프록시를 이용해서 게임이 시작되기전(비행기가 착륙하기전)까지 한정된공간에서 놀수있게했는데, 그게 프록시 패턴이다.
      • 예 : 여러명이 협업하는 상황에서 어떤 객체에 대한 구현이 완벽하게 되지않았다. 근데 해당 객체는 프로세스상 호출은 하니깐 일단은 프록시 객체를 호출하게 해놓고, 주체 객체가 구현이 완료되면 주체객체로 대체하는 방법도 있다. 실제 객체를 붙여보기전에 미리 프로세스를 진행할수있다는 장점이 있겠다.
    3. 보호 프록시 :  접근에 제한이 필요한 객체에 대한 프록시출처: https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4#/media/%ED%8C%8C%EC%9D%BC:Proxy_pattern_diagram.svg

 

'개발 > 디자인패턴' 카테고리의 다른 글

옵저버 패턴 정리  (0) 2020.07.03

두개의 entity(ordergood, order_refund_detail)가 oneToMany 관계로 걸려있었다. 

엔드포인트를 테스트 코드에서 똑같이 재구현해서 테스트를 해봤는데, layzyInitialLazyInitializationException 이 발생을했다.

테스트 코드는 아래 그림과 같다.

 

원인은!

테스트코드는 시작시 영속성컨텍스트 안만들어준다..
지금의 스프링 OSIV에서는 필터단 부터 영속성컨텍스트가 시작되기때문에 그 하위 메소드들은 영속성 컨텍스트가 유지된다.
테스트코드에서는 필터,인터셉터를 지나치지 않았기때문에 영속성 컨텍스트를 안만들어 주는것이다. 후 삽질..


아래그림과같이 @Transactional을 테스트메소드에 추가해주면 해결 끝!



  

위 그림처럼 JPA Repository는 분명 interface만 정의해줬다. 구현체를 내가 따로 만든게 없다.

그런데 위 그림처럼 사용하는쪽에서 해당 Repository를 D.I를해서 사용할 수 있다. 구현체를 알아서 스프링에서 만들어주니, 쓸수 있는거일텐데..

도대체 Repository 구현체는 어떤과정에 의해서 만들어지는것인가..?

 

디버깅을 통한 결과이다.

 

JpaRepositoryFactoryBean -> JpaRepositoryFactory -> interface (ex.PaymentRepository)를 가지고 reflection implement를 실행 -> SimpleJpaRepositoryImpl

그리고 Repository가 저렇게 JpaRepositoryFactory에서 생성이 되는 전제조건은 Repository를 스캔하는 base package를 설정해놔야 한다.
이전에 @Component, @Service , @Bean 들은 두개의 스캔과정을 가지고 있다는것을 알게 됐다.

1) @ComponentScan 2) EnableAutoConfigureScan 

@Repository는 위 2가지 스캔 과정과 별개로 다른 스캔 과정, 어노테이션이 필요하다! 

@SpringBootApplication이 붙은 메인클래스에 Repository는 @EnableJpaRepositories 어노테이션으로 설정이 가능하다. 저렇게 하면 basepackage가 com.waug.auth.common.rememberme.repository가 된다. 설정을 안하면 디폴트로 main 아래 java 패키지이다.

 

 

 

일단 크게 2가지가 있다.

1. @HandlerException, @ControllerAdvice를 이용하는 방안

2. BasicErrorController를 이용하는 방안

 

이 두 사용방안은 실행되는 위치가 다르다. 

1은 Interceptor, 2는 Filter

그림으로 보면,

1 에서 처리된 exception은 2까지 전파되지 않는다. 그래서 중복설정하게되면 basicErrorController가 왜 먹히지?하는 상황이 올수있다. 1과 2의 공통기능은 결국 Exception을 핸들링해주는 것이기 때문에 각 특징을 알고 써먹으면 될거같다.

 

@HandlerException와 BasicErrorController의 각각의 특징을 정리해보면,,

 

- HandlerException

 Exception을 미리 메소드별로 나눠서 처리가능하다. 반대로 말하면 BasicErrorController는 모든 exception을 메소드별로 나눠서 처리하는게 불가능(error(), errorHtml()이란 메소드로만 분리됨)

 

- BasicErrorController

Exception을 html로 주는 경우(errorHtml), 그 외의 경우로 나눌수(error) 있음

 

 

 

 

'개발 > Spring' 카테고리의 다른 글

JPA Repository의 D.I 과정  (0) 2020.06.25
Transaction & 영속성 컨텍스트 이야기  (0) 2020.06.23

+ Recent posts