스터디/블랙커피 블로그 스터디

블랙커피 스터디 2주차 학습 방법에 대한 고민

TheWing 2021. 2. 1. 02:45

블랙커피 스터디 2주차

1주차 회고 때 최근 가지고 있는 고민을 털어놓았었다.

나의 고민

나의 고민은 공부하는 학습 방법이다. 학습 방법에 대해 고민을 하고 있다고 회고때 말씀드렸는데 스터디장님께서 학습 방법을 한번 포스팅해보라고 말씀하셔서 올려보려 한다

올해부터 공부하면서 머릿속에 새길 때 "왜?"라는 의문을 가지고 공부해야겠다고 마음을 먹었다. 공부를 하는데도 나중에 잊게 되고 공부를 깊게 하더라도 엉뚱하고 이상하게 깊게 공부하고 있었다. 엉뚱하다고 느낀 건 내가 느낀 적이 없었고 같이 공부하는 주변 분들이 말씀해주셨다. 이번 포스팅은 나의 공부 방식을 포스팅해보겠다.

주제

주제는 @Configuration(proxyBeanMethod)과 REST API를 공부하면서 했던 것을 올려보도록 하겠다.

공부 계기

@Configuration(proxyBeanMethod), Jdk Dynamic Proxy, CGLIB Proxy

  • Spring AutoConfiguration을 공부하면서 메서드들이 @Configuration(proxyBeanMethods = false) 로 되어있어서 무슨 기능을 하는지 궁금해서 찾아보게 되었다. 프록시를 생성해서 사용하지 않는다?.. 왜 사용하는 걸까?라는 의문을 가지고 접근하였다.

REST API

  • 프로젝트를 하면서 REST API를 조사 해보았었다.

@Configuration(proxyBeanMethod) 접근 방식

먼저 어떻게 찾아볼지 고민을 해보았었다.

1. Java API Docs를 보자

@Configuration

2. 번역을 보자

@Configuration(proxyBeanMethod) 원문

Specify whether @Bean methods should get proxied in order to enforce bean lifecycle behavior, e.g. to return shared singleton bean instances even in case of direct @Bean method calls in user code. This feature requires method interception, implemented through a runtime-generated CGLIB subclass which comes with limitations such as the configuration class and its methods not being allowed to declare final.
The default is true, allowing for 'inter-bean references' via direct method calls within the configuration class as well as for external calls to this configuration's @Bean methods, e.g. from another configuration class. If this is not needed since each of this particular configuration's @Bean methods is self-contained and designed as a plain factory method for container use, switch this flag to false in order to avoid CGLIB subclass processing.
Turning off bean method interception effectively processes @Bean methods individually like when declared on non-@Configuration classes, a.k.a. "@Bean Lite Mode" (see @Bean's javadoc). It is therefore behaviorally equivalent to removing the @Configuration stereotype

번역

bean 라이프사이클 동작을 적용하기 위해 @Bean 메서드가 프락시 되어야 하는지 여부를 지정합니다. 예를 들어 사용자 코드에서 직접 @Bean 메서드를 호출한 경우에도 공유된 singletonbean 인스턴스를 반환해야 합니다. 이 기능은 런타임 생성 CGLIB 하위 클래스를 통해 구현되는 메서드 가로채기를 요구한다. 이 하위 클래스는 구성 클래스 및 최종 선언이 허용되지 않는 메소드와 같은 제한을 수반한다.
기본값은 true이며, 구성 클래스 내의 직접 메서드 호출을 통해 'bean 간 참조'를 허용하고 이 구성의 @Bean 메서드(예: 다른 구성 클래스)에 대한 외부 호출을 허용합니다. 이 특정 구성의 @Bean 메서드는 컨테이너 사용을 위한 일반 공장 방법으로 설계되었으며 자체 포함되므로 필요하지 않은 경우 CGLIB 하위 클래스 처리를 방지하려면 이 플래그를 false로 전환하십시오.
bean 메서드 가로채기를 해제하면 @Bean 메서드가 비@Configuration 클래스, 예: "@Bean Lite Mode"에서 선언될 때와 같이 개별적으로 @Bean 메서드를 처리합니다(@Bean's javadoc 참조). 따라서 @Configuration 고정관념을 제거하는 것과 같은 행동이다.

3. 애매하거나 모르는 단어 찾기

  1. 메서드 가로채기??
  2. bean 간 참조 허용?
  3. Lite Mode

Lite Mode

  • @Component 어노테이션을 작성하면 lite mode가 된다 lite 모드로 설정하면 @Configuration으로 설정하는 것보다 빠르지만 많은 차이는 없다.
  • 차이는 CGLIB 프록시를 사용하냐 안 하냐 차이이다
  • @Configuration
    • CGLIB 사용
  • @Component
    • CGLIB 사용하지 않음

4. CGLIB , JdkDynamic Proxy 다시 한번 알아보기

https://sujl95.tistory.com/65 포스팅했던 글과 내용이 비슷하다

JdkDynamic Proxy

Dynamic Proxy 활용 시 사용하는 JdkDynamicAopProxy 클래스의 주석엔 이 방식의 특징이 적혀있다.

  1. java.lang.reflect.Proxy 를 기반으로 하는 AOP
  2. 인터페이스 및 인터페이스가 구현된 클래스에만 사용할 수 있다.(인터페이스 하나 이상 구현 시)
  3. 대상 클래스가 thread-safe 한 경우 생성된 프록시도 thread-safe 하다.
  4. Advice/Pointcut 및 TargetSource가 직렬화 가능하다면 프록시도 직렬화가 가능하다.
  5. Java reflection을 사용해 메소드를 invoke 한다. reflection을 하기 때문에 성능이 저하될 수 있다
  6. target class의 모든 메소드가 advice 되지 않을지라도 , JDK Dynamic Proxy는 일단 invoke 하고 이후에 Advice 되는 메소드인지 판단하기 때문에 더욱 성능이 저하된다
  7. 프록시 패턴을 직접 구현해야 하고 코드량이 많아진다, Proxy 클래스를 사용하고 런타임 시 동적으로 기능을 추가할 수 있다

CGLIB Proxy

스프링에서 CGLIB 기반 프록시를 수행하는 클래스는 CglibAopProxy 이다.

  1. CGLIB도 Dynamic Proxy와 마찬가지로 원본 클래스의 thread-safe 특징을 따른다.
  2. 부모 인터페이스가 없는 클래스에도 적용할 수 있다. (인터페이스 구현체가 아닌 것)
  3. 상속을 활용한다. (상속이 불가능한 final/private 키워드는 aspect가 적용되지 않는다)
  4. CGLIB는 byte code를 조작하여 target class의 메소드를 호출한다. 이러한 방식은 한 번의 메소드 호출 후에는 생성된 bytecode를 재사용할 수 있어 실행 속도가 향상된다. CGLib library가 Spring framework에 포함되면서 별도의 라이브러리 설정 없이도 사용 가능하게 되었다.

5. Reflection 다시 알아보기

Java reflection

  • 구체적인 class type을 몰라도 그 class의 method, type, variable에 접근할 수 있게 해주는 기능이며 private에도 접근이 가능하다.
  • 구체적인 class type을 알지 못하지만 동적으로 instance를 생성해야 할 때가 있다.
    • 예를 들어 매개변수에 class name을 넘겨서 받는 경우가 있다
  • java class file 들은 binary code로 컴파일되어 static영역에 존재하게 된다
  • 따라서 class type을 모르더라도 class 명만 알면 class를 알 수 있다.

6. @Configuration(proxyBeanMethods = false) 찾아보기

  • Spring FrameWork 5.2에 추가됐다
  • Spring FrameWork 5.2 , Spring Boot 2.2 기준 AutoConfiguration Class에 주로 사용되고 많은 설정이 필요할 때 사용한다
  • @Configuration 속성 proxyBeanMethods를 이용하면 구동 시간과 메모리 사용량을 줄일 수 있다.
    • 구동 시간, 메모리 사용량 줄일 수 있는 이유
      • 리플렉션을 하지 않고 프록시를 생성하지 않기 때문에 성능적인 이점이 있다.
    • 인스턴스를 호출시마다 생성하므로 싱글톤으로 생성하지 않아서 여러 번 호출한다
    • @Configuration(proxyBeanMethod = false)이라고 해당 클래스의 @Bean 메서드를 호출할 때 메서드로 인식해서 등록

7. @Configuration(proxyBeanMethods = true) 찾아보기

  • CGLIB Proxy를 사용한다.
  • Bean 간의 참조를 허용한다.
  • 인스턴스 호출 시 메서드를 가로채서 한번 호출되고 싱글톤으로 인스턴스를 생성한다. 이것이 핵심이다.

REST API

궁금했던 것

HTTP Method의 GET의 길이 제한이 있다는 것을 알고 있었다. 255자라길래 이게 맞나??라는 의문이 들었다.

그러나 이것에 대해 궁금해서 찾아봤는데... 주변 분들이 왜 알아보냐고 말씀하셨다.. 그런 생각이 들었다. 이것도 중요한 내용이 아닌가...?

GET의 길이 제한

  • 글자 수 제한이 대부분의 블로그들이 255 자라 고한다. 그러나 이것은 잘못된 사실이다 결과적으로는 브라우저마다 다르다
  • IE를 제외한 다른 브라우저들은 GET URL에 길이 제한이 없다

브라우저

  • 인터넷 익스플로러(2084자)
  • 크롬, 사파리 (100만여자)
  • 모질라 파이어폭스(100만여자)
  • 오페라 (200만여자)

출처

작성 후 느낀 점

처음으로 이렇게 공부 학습 방법에 대해 포스팅을 해보았는다

이번 주에도 중요하지 않은 부분(GET 길이 제한)을 공부했는 것 같다. 그래서 더욱 고민이 된다.

"왜"에 대한 의문을 가지고 조금 더 신경 써서 공부하자

코드 한 줄을 작성하더라도 이것이 무엇을 의미하고 장단점이 무엇인지에 대해 명확하게 알고 작성해야겠다는 생각이 든다

이번 주 포스팅한 글

백기선님 LiveStudy

REST API 정리

Be-Docs 스터디 TDD 발표 후기

Reference