request 요청이 들어오기 전의 스프링은 이런 구조의 모양을 가진다.
단일 책임의 원칙(SRP)에 의해 Controller와 Repository를 분리한다.
분리해두면 재사용이 가능해서
PostController에서도 UserRepository 사용이 가능해진다.
클라이언트가 request 요청이 들어오면 성의 문앞에서
문지기가 web.xml에 따라 필터링을 거친다.
그리고 8080번 포트 문을 지나 컨텍스트 패스를 거쳐
디스패쳐 서블릿의 바로 직전에
클라이언트만의 request와 connection 객체를 생성한다.
정확히 말하면 풀링 기술로 이미 만들어져있는 객체를
가지고 오는 것이다.
톰캣이 가지고 있는 풀링공간의 request,
DBCP에 conn 객체가 만들어져 있는 공간을
가리키는 주소를 가지고 오는 것이다.
DB에 접근이 필요하지 않은 CV 패턴을 사용하는 요청의 경우에도
conn 객체를 가지고온다.
프레임워크의 설계가 그렇게 되어있어서 깰 수 없다!
컨트롤러와 레파지토리에 어노테이션을 붙이면
서버가 실행될 때 IoC에 new된다.
IoC 컨테이너는 DI시에 타입으로 스캔하여 서칭하기 때문에
1개만 new되어 메모리에 뜰 수 있다.
싱글톤 패턴으로 관리되고 있는 것이다.
IoC 컨테이너에 떠있으면 공유해서 사용이 가능해져 DI 받을 수 있고,
컨트롤러의 메서드에 매개변수로 넣어주는 것은
공유되지 않아서 DS가 가진 것을 직접 전달해주는 것이다.
공유되지 않는 것에는 request와 같은 것이 있는데
model 또한 그렇다.
메모리에 하나만 뜨는게 아니라 클라이언트마다 있는 공간이기 때문에
DS가 직접 전달해준다.
model에 담으면 request를 덮어씌우는 기술까지 가지고 있기 때문에 편하다.
세션은 request를 통해 접근이 가능했는데
이 세션은 하나의 공간이기 때문에 또한 IoC 컨테이너에 등록이 가능하다.
그 말은 DI가 가능하다는 말이다.
request가 100개여도 request.getSession( )을 했을 때 하나의 공간을 가리키기 때문이다.
세션은 공유 저장소니까!
세션을 전역변수로 선언하여 DI를 받아주자!
이때 request는 전역으로 선언하면 안된다!!
전역변수는 모든 스레드가 공유하기 때문에 request를 전역으로 선언하면
동시에 여러명의 클라이언트가 요청할 때 충돌이 난다.
1번 클라이언트는 괜찮지만 2번 클라이언트가 요청할 때
2번의 request로 덮어씌워져서
1번과 2번 모두 2번의 request를 바라보고 있기 때문이다.
id가 1인 유저 정보 Get 요청이 들어왔다.
DS는 UserController의 유저 상세 페이지를 보여주는 메서드를 때려준다.
컨트롤러에서는 Repository의 findById( ) 메서드를 때려준다.
연결되어있는 영속성 컨텍스트에서 알아서 쿼리를 만들어 명령해주면
DB가 하나의 행을 리턴해준다.
DB와 동기화된 테이블을 영속성 컨텍스트가 가지게 되는데
이를 Entity라고 한다.
userEntity를 차례대로 리턴해준다.
컨트롤러까지 리턴해주면 컨트롤러가 userEntity를 model 박스에 넣어
View(.mustache)를 때려줄것이다.
그러고나면 자바 코드를 해석한 후 나오게되는
순수한 html 파일을 클라이언트에게 리턴해준다.
리턴해주기 전 디스패쳐 서블릿에서 나오면
가지고있던 request, conn 객체를 반납한다.
반납하지 않고 없애버리면 풀링기술을 사용할 수 없기 때문에 반납해준다!
한번 더 id가 1인 유저 정보 Get 요청이 들어왔다.
이때는 영속성 컨텍스트에서 DB까지 가지 않는다.
영속성 컨텍스트에 찾는 유저의 정보가 있는지 먼저 찾기 때문에
가지고 있다면 캐싱한다.
응답이 끝난 후 연결이 끊어지면 stateless 서버인데 이를 무상태 서버라고 한다.
세션을 이용해 stateful한 척이 가능하다.
로그인을 하면 username과 password로 SELECT한 결과를
난수의 해시값과 함께 세션에 저장하는 것이다.
세션을 사용하면 하나의 공간에서 사용자의 세션을 찾느라고
시간은 좀 더 걸리지만
서버의 부하가 훨씬 적어진다.
난수 7839를 받은 클라이언트는
http 헤더의 쿠키라는 영역에 난수를 저장하고
바디에 html 코드를 저장한다.
이 쿠키는 브라우저가 가지고 다녀서
서버는 세션에 7839 영역이 있으면
아, 한번 왔던 사람이네? 라고 인증하는 것이다.
서버 입장에서는 처음 온 사람이 아닌걸 기억하고 있는것을 인증이라고 생각하지만
개발자 입장에서는 인증이라고 생각하기 어렵다.
세션은 인증의 개념이 아닌 stateless한 연결을 stateful하게 쓰려고 사용한다.
직접 코드를 짜서 인증과 권한 처리를 해주어야 한다.
세션을 종료시키는 방법은 3가지가 있다.
1. 30분동안 세션 영역의 user 오브젝트에 접근이 없으면
(= 7839로 request 요청이 없으면) 세션이 종료된다.
30분 시간은 web.xml 파일에서 변경이 가능하다.
스프링에서는 application.yml 파일에서 변경한다.
2. 세션의 7839 영역을 직접, 강제로 삭제한다. -> 로그아웃
3. 브라우저의 쿠키를 삭제한다.
[출처]
https://cafe.naver.com/metacoding
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9