스프링 디스패쳐 서블릿을 생각해보자.
디스패쳐 서블릿은 서블릿이 1개인 것임.
우선 스프링 디스패쳐 서블릿이 아니라 그냥 서블릿을 사용한다고 생각해보자.
그냥 서블릿은 URL의 매핑을 클래스로 해야 하기 때문, 각각에 URL의 그룹핑을 할 수가 없다. = 공통처리 불가능, 예를들어 user/moneyInfo, user/scoreInfo 등을 각각의 url이 매핑되는 2개의 클래스를 만들어야함.
이렇게되면 단점은 user라는 것의 공통처리 로직을 한 곳에 모아둘수가 없음.... (단일책임의 원칙에도 위배될듯 함)
그래서 프론트 뭐시기 패턴으로 공통 관문을 만들어버림. -> 결국 이게 스프링 디스패쳐 서블릿
스프링에서는 @Controller라는 어노테이션을 붙여서 class User라는 컨트롤러를 만들고...
그래서 user로 시작하는 url은 User 클래스를 거치게 되면서 필요한 공통로직을 수행하고
그 안에 @RequestMapping(moneyInfo), @RequestMapping(scoreInfo)메쏘드를 url에 매핑되는 작업을 수행한다.
이때 일반적으로 스프링은 controller -> service(-> repository) 를 통해 Model을 만들고,
결정적으로 어느 View를 return할지 정해주니깐..
Controller의 사전적 의미가 맞다. 제일 핵심은, Controller는 모델(데이터)를 가공하고, 어느 View를 갱신할지 선택해주는 것이다.
(View가 갱신되는 방법으로는 model에서 호출할수도있고, view가 model의 변경을 polling하고 있을수도 있고, Controller또는 다른곳에서 view에게 갱신을 요청할수도 있다. 딱히 정의된건 없는듯하다. 스프링에서는 contrlloer의 메쏘드가 리턴하는 이름을 보고 뷰리졸버가 선택해준다.)
어쨋든 핵심은 Controller는 들어온 요청에 따라 필요한 모델을 가공하고, 어느 View를 갱신해줄지 정하는 녀석이다. 그리고, 요청으로 들어오는 View != 요청처리후 갱신할 뷰 상태인 것이다!
그리고 MVP(presenter) 패턴이란..
요청이 들어오는 UI View == 요청처리후 갱신할 View 이상태이다.
그래도 View의 역할을 단일책임으로 분리하기 위해 view에서 모델을 가공하는게 아니라, view로 요청이오면 모든 데이터를 Presenter로 넘겨버린다.
presenter는 view로부터 넘겨받은 데이터로 필요한 모델을 만들고, view의 화면을 업데이트 시키는 역할을 한다. (presenter가 중간에서 view의 화면갱신을 시켜버리는것!)
당연히 mvp패턴에서 view의 갯수만큼 presenter의 갯수가 증가한다. view갯수 == presenter 갯수
그리고 더 나아가서 MVVM 패턴이란 (View Model)...
위의 mvp의 단점은 view의 갯수가 늘어나는 것만큼 presenter의 갯수도 동일하게 늘어난다.
근데 설계를 하다보니 view는 생김새는 거의 비슷해서 view에 매칭되는 presenter가 하는일이 거의 동일하더라...
불필요하게 presenter를 여러개 만드는것이 소모값이 크다 느껴서..
여러 view들이 단 1개의 viewModel을 이용하게 하는 것임. (추상화를 잘해야함)
이때 핵심은 viewModel은 view를 의존하지 않음. view로부터 전달받은 데이터를 가지고 model에서 데이터 가공만 하는것임. (viewmodel은 커맨드와 데이터바인딩을 가진다고 하는데 무슨말이지)
그렇다면 어떻게 view의 화면이 업뎃이 되냐..? mvp에서는 presenter가 view에게 갱신을 요청했는데..
mvvm에서는 view가 view model에게 데이터를 넘기고, 그 데이터의 변경을 감지하고 있음(polling) viewmodel이 모델을 만들면, view는 이것을 감지하고 화면을 업데이트 하는 방식임.
mvvm 단점은 설계가 좀 빢새짐.
전체 글
- MVC, MVP, MVPP 2022.08.22
- 스프링 프레임워크의 일부기능(IOC와 AOP관련)만 라이브러리처럼 사용하기 2022.07.15
- OSIV 비슷하게 구현하기 2022.07.15
- IOC, DI 2022.07.09
- 인프런-JPA활용1 셋팅법(롬복 등) 2022.06.30
- rdp wrapper 2021.03.25
- 젠킨스 설치시 유저 로그인 권한 주기 2020.12.22
- parallel VS concurrency 용어차이 2020.05.28
MVC, MVP, MVPP
스프링 프레임워크의 일부기능(IOC와 AOP관련)만 라이브러리처럼 사용하기
일반 적인 자바 SE 개발에서, IOC / DI / 컴퍼넌트스캔 등의 기능이 필요로 하다. (스프링부트처럼 프레임워크를 기반으로 동작하는게 아니라)
필요한 이유는 AOP(특히 @Transaction을 통해 JPA를 편하게 쓰기 위해)를 사용하기 위함인데..
AOP에 관련한 어노테이션이 붙어있으면 컴퍼넌트 스캔을 통해 프록시객체를 싱글턴 빈으로 만들고, DI컨테이너에 보관하고 있을테니.. 저 빈을 사용하기 위함임.
현재 다른 프레임워크(RCP)를 사용중이라... RCP에도 DI는 되는것으로 알고있는데 컴퍼넌트 스캔은 잘 모르겠음..(찾아볼 것)
프로그램 흐름 : RCP프레임워크 시작 -> 각종 어노테이션 컴퍼넌트 스캔 -> 빈등록. 객체주입은 DI컨테이너에서 get해올 것.
시도 V1: 일단 스프링 프레임워크를 그대로 가져오는게 아니라, 컴퍼넌트스캔 IOC AOP만 가능하게 라이브러리 형태로 가져와볼 것.
성공함! 성공코드 파일첨부
프로그램 흐름을 보면
main -> AnnotationConfigApplicationContext을 생성(이때 AppConfig설정 참조) -> 설정을 보고 패키지 단위에서 컴퍼넌트 스캔해서 빈 만들고 만들고 의존성 주입해줌, 빈 만드는 과정에서 AOP 관련한 것들 프록시 형태로된 객체가 빈으로 되는 것임 -> 어플리케이션 컨텍스트의 빈은 프록시빈이므로 AOP 동작 잘됨
참조사이트 : https://creamilk88.tistory.com/162
https://hwannny.tistory.com/62
'IT > 트러블슈팅 기록' 카테고리의 다른 글
OSIV 비슷하게 구현하기 (0) | 2022.07.15 |
---|
OSIV 비슷하게 구현하기
스프링이아닌 다른 프레임워크를 사용하는데, OSIV 기능이 꼭 필요하다.
OSIV란? : Open Session In View의 줄임말(JPA에서 엔티티매니저는 하이버네이트에서는 세션이라 부른다.)
직역하면, 세션이 뷰안에서(뷰까지) 존재한다는 것인데..
세션이 뷰까지 살아있으면 좋은점은 Lazy로딩설정된 프록시에 접근해서도 DB에 읽기를 요청할수 있다는 것임.(코드 유지보수 하기에 장점)
(정리 잘된 곳 : https://ykh6242.tistory.com/entry/JPA-OSIVOpen-Session-In-View%EC%99%80-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94 )
일반적으로
컨트롤러 -> 비지니스 서비스 -> 마이크로 서비스(트랜잭션 시작 및 DB접근후 트랜잭션 종료 = 엔티티매니저 close)
이러한 형태를 취한다면, 마이크로 서비스 단에서만 lazy proxy가 초기화가 가능하다.
그러므로, 비지니스 로직에서는 lazy proxy를 초기화 할 수 없으므로.. 트랜잭션은 마이크로 서비스에서 끝나되, 비지니스 서비스 까지 엔티티매니저를 유지시키고 싶은 것임
시도 V1 : 일단 비지니스 서비스 클래스에 @BusinessService라는 어노테이션이 달려있으면 엔티티매니저가 해당 클래스까지는 유지되도록 해보기.
검색결과 V1 :
<property name="hibernate.enable_lazy_load_no_trans" value="true" />
를 해주면 설정 끝. (정리 잘된 곳 : https://suhwan.dev/2019/10/27/hibernate-detached-entity-proxy-initialization/ )
간단하게 엔티티매니저가 종료될때, 초기화 되지 않은 프록시들은 엔티티매니저팩토리의 레퍼런스를 갖고있는다. 엔티티매니저가 종료된 상태에서도 프록시에 접근하게 되면, 엔티티매니저팩토리 래퍼런스에서 다시 엔티티매니저를 생성하여 DB의 읽기가 가능한 것
(proxy객체를 보면 sessionFactoryUuid 속성에 4c383891-83a4-4a5e-98bf-9d5bde66695c 이런식으로 엔티티매니저팩토리의 값을 가지고 있음)
안티패턴이긴 하다. 왜냐하면 계속 다시 엔티티매니저를 만드는 과정이 있고(커넥션 점유), N+1과 같은 문제가 터질수 있으므로 더 로우레벨 단에서 처리하는게 좋긴 한데...
우리도구에서는 크게 영향이 없다. 단일 프로그램에 커넥션은 오직 1개뿐이며, 레이지로 설정된 프록시는 xToOne일 것이고 xToMany관계는 이미 fetch join으로 가져오므로. 그리고 엔티티매니저 생성과 파괴는 리소스점유가 거의 없다고 함.
(OSIV 자체도 안티패턴이라 한다. https://vladmihalcea.com/the-hibernate-enable_lazy_load_no_trans-anti-pattern/ )
'IT > 트러블슈팅 기록' 카테고리의 다른 글
스프링 프레임워크의 일부기능(IOC와 AOP관련)만 라이브러리처럼 사용하기 (0) | 2022.07.15 |
---|
IOC, DI
제어의 역전
스프링에만 해당하는 개념은 아닌듯 하고 모든 프레임워크에 해당하는 개념일 것이다.
모든 프레임워크는 프레임워크내에서 나의 코드가 돌아가기 때문 제어가 역전되었다.
(프레임워크 vs 라이브러리
프레임워크가 내가 작성한 코드를 제어하고, 대신실행해서 프레임워크를 기반으로 돌아간다면 프레임워크다.(Junit)
내가 작성한 코드가 직접 제어의 흐름을 담당하면 라이브러리 이다.)
제어의 역전은 프레임워크 같은게 호출을 대신 해주는것을 말함.
그런것들 제어권이 뒤바뀐다 해서 제어의 역전이라고 함.
(원래 객체 자체에서 필요한 의존객체를 new로 생성해서 사용하는데, 이런것들을 밖에서 해줌)
의존관계를 외부에서 주입시키면, 클라이언트의 코드를 변경하지 않아도 된다는 것이 큰 강점임.
특히, 이미 정적으로 의존관계를 맺어놓은 것이 있다고 해도, 이것들의 변경이 전혀 필요하지 않은게 장점이다.
쉽게 생각해서 그냥 정적인 의존관계가 모두 인터페이스 타입이고, 실객체를 생성자를 통해 외부에서 주입받으면 설계가 아주 잘된 코드라고 보면 된다.
(클라이언트 코드에서 import해놓은 정적 의존관계 클래스 들(서버)이 모두 인터페이스 타입일거고, 실 객체는 생성자를 통해 동적으로 외부에서 주입될테니 정적코드가 변경될 일이 없음)
IOC 컨테이너 Inversion of Control 제어의 역전
DI 컨테이너 Dependency Injection 의존관계 주입
IOC컨테이너는 쉽게말해서 객체의 생성을 담당하고,
DI컨테이너는 생성한 객체를 주입하는것을 담당
EX) 드라이버 클래스에서 실제 자동차 객체를 생성하는게 아니라, IOC컨테이너에서 만들고, DI 컨테이너가 주입한다.
실세계에서는 IOC컨테이너나 DI컨테이너를 비슷한 의미로 언급하는듯 함.( 또는 IOC컨테이너가 DI 를 해준다 라고 생각할수도 있을듯)
정확하게는 IOC컨테이너의 이름이 너무 범용적이라(JUNIT도 IOC가 된것임) 후대에 DI컨테이너라는 용어로 정착된듯 함.
DI가하는일이듯, 필요한 객체들을 조립해 준다고 하여 어셈블러 라기도 하며, 오브젝트를 만들어야 한다고 해서 오브젝트 팩토리 라고도 부름.
담당자 배정과 역할을 매우 명확하게 해야 한다.
예를들어 공연을 한다고치면 공연 주체자(main)이 모두 하는게 아니라,
- 배역(인터페이스, Interface)
- 배우(실구체. Impl)
- 기획자(배우를 실제 캐스팅하고 배역 관계에 따라 실제 배우를 설정하는 일, AppConfig)
등으로 일을 관심사를 분리하여 맡은 역할만 담당하게 구성을 해놓아야 한다. 이후에 공연 주체자가 모두 다 알고 있는 상태에서 지휘하는 것임.
인프런-JPA활용1 셋팅법(롬복 등)
기본적으로 git (https://github.com/yyjstudy/SpringBootJpaUse1.git) 에서 받아오고, 인텔리제이에서 임포트 한다.
소스경로에 한글이 포함되지 않도록 할 것!
H2 DB
H2 데이터베이스는 꼭 1.4.199 버전을 설치하고 H2 데이터베이스설치 강의(4분짜리) 보면 됨.
롬복
롬복 깔고, Enable annotation processing 에 체크해야 함.
rdp wrapper
젠킨스 설치시 유저 로그인 권한 주기
젠킨스 설치시 사용자 권한을 입력해도
this account either does not have the privilege to logon as a service
이렇게 나올 것이다.
미리 사용자 로그인 권한을 주어야 한다.
해결방법 : stackoverflow.com/questions/63410442/jenkins-installation-windows-10-service-logon-credentials
제어판 -> 관리 도구 -> 로컬 정책 -> 사용자 권한 할당 -> 서비스로 로그온 -> 사용자 또는 그룹 추가에서 입력할 사용자 추가할 것.
parallel VS concurrency 용어차이
Parallelism 병렬성,(병렬)
Concurrency 동시성, (병행)
'IT > 자바' 카테고리의 다른 글
RMI Registry, 프로세스간 통신 (0) | 2020.05.21 |
---|---|
보일러 플레이트란? (boilerplate ) (0) | 2020.05.19 |
객체, 클래스, 인스턴스 용어 구분 (0) | 2020.05.18 |
자료구조 정리 잘된 곳 (0) | 2020.05.13 |
해쉬코드, 이퀄스 (0) | 2020.05.08 |