[Springboot] Springboot 개념정리

Springboot with JPA

  • 출처: https://getinthere.tistory.com/9

  • IoC : Singleton으로 bean을 관리하는 Container
  • DI : 인스턴스 생성시 IoC컨테이너에서 singleton으로 관리하는 bean들을 변수에 의존성 주입
  • SPRING : IoC 컨테이너를 통해 bean들을 Singleton으로 관리하고 필요에 따라 DI 해주는 프레임워크

class = 설계도 object= 실체화가 가능한 것 instance = 실체화 된 것.

스프링

스프링은 프레임워크이다. 스프링은 오픈소스이다. 스프링은 IoC 컨테이너를 가진다. 스프링은 DI 를 지원한다. 스프링은 엄청나게 많은 필터를 가지고 있다. 스프링은 엄청나게 많은 어노테이션을 가지고 있다. (리플렉션, 컴파일체킹) 스프링은 MessageConverter를 가지고 있다. 기본값은 현재 Json이다. 스프링은 BufferedReader와 BufferedWriter를 쉽게 사용할 수 있다. 스프링은 계속 발전중이다.

오브젝트를 new 해서 Heap이라는 메모리 공간에 올리게 되면

오브젝트를 의자 S = new 의자 (); 가 되게 되고 S는 new가 만든 스택(메서드)에서 관리하게 된다.

20210625_101552

public void make()라는 함수가 있을떄 의자를 new해서 실체화 시키고 그 메모리에 띄운 주소를 S가 가지고 있다 이 주소는 S가 실행중일 때만 떠있다.

20210625_102615

근데 다른 메서드에서 (use가 쓰고 싶으면)

의자 s=new 의자()로 하면 밑에 새 메모리가 가지고 각각의 메서드가 관리하며 이건 다른 의자가 된다. 그럼 공유해서 쓰기가 되게 어렵다.

근데 이런 오브젝트들과 메서드를 스캔해서 자기가 이 객체들을 직접 이

20210625_102739

이렇게 스프링이 관리하게 되는걸 DI(제어의 역전)이라고 하며

내가 원하는 모든 클래스의 메서드에서 이걸 가져와서 사용이 가능해진다.

만약 의자 또 쓰고싶으면 다른 곳에서 의자 쓰면 된다. 아래 클래스의 의자와 위의 클래스의 의자는 같은거 싱글톤이기 때문.

이렇게 필요한걸 가져가서 쓰는 걸 DI라고 한다.


필터란?

A 성에 왕의 집이 있는데 B성에 전쟁중임. B나라에 스파이들이 A성으로 침입하면 그걸 막아야 한다.

문지기는 못 들어오게 막아야하는데 스프링 자체가 이런 필터 기능을 갖고 있다.

필터 기능 사용 안하는 걸 사용하게 설정 할 수도 있고 직접 필터를 생성할 수도 있다.

20210625_104956

.

스프링 컨테이너가 들고 있는 필터 인터셉터라 부른다.

이 AOP라는 개념이 있는데 아직은 적기 그렇다.

컴파일 체킹에는 어노테이션이 있는데

어노테이션은 (주석+힌트) 이렇게 컴파일러가 무시하지 않음. // 글 (주석) < - 컴파일러 무시

스프링 어노테이션 객체 생성

어노테이션으로 미리 약속을 한다.

  • Component = 클래스 메모리에 로딩
  • Autowired = 로딩된 객체를 해당 변수에 집어넣음. 스프링은 class A가 있는데 이걸 new 하는거 보다 IOC를 사용한다 그래서 이 위에 component라 붙어있으면 스프링이 해당 클래스를 읽음.

힙 메모리 공간에 해당 클래스에 로딩해라.

이렇게 붙이고 스프링이 B클래스 스캔할 때 어떤 거가 있는지 분석하는 걸 리플렉션이라 하고 리플렉션을 통해 메서드, 필드, 어노테이션 등을 체킹할 수 있다.

이게 있다면 무엇을 하라고 설정이 가능하다.

리플렉션을 통해서 @Autowired가 있으면 뭘 하라는지 봤을떄 해당 변수를 집어넣으라 했다.

20210625_111905

스프링이 IOC를 통해 집어넣은게 A뿐 아니라 수많은 게 있을텐데 A와 동일한 타입의 객체가 떠있는지 확인한다.

A가 없다면 null이 들어갈 것 만약 같은 타입의 데이터가 있으면 타입으로 IOC가 읽어들인 객체를 타입을 통해 찾는다.

A가 Autowired된 곳에 들어간다.

어노테이션은 주석+힌트고 리플렉션은 어떤해당클래스가 어떤 해당 메서드 어떤 어노테이션 갖는지 분석하는 기법-> 런타임시 분석)


MessageConverter

20210625_112204

영어권 국가와 한국권 사람이 있는데 메시지 전달받으면 각 나라는 각 나라 언어밖에 못하니까 서로가 번역해서 보내야한다.

20210625_134421

그래서 중간데이터를 만듬.

한국->영어 , 영어->한국어 둘다 이해하기 힘드므로 둘 다 이해 가능한 중간언어를 만든다.

xml이라는 중간언어를 만드는데 요새는 json을 많이 쓴다.

20210625_135205

메시지 컨버터가 존재하고 jackson은 json데이터로 변경해주는 라이브러리다.

BufferedReader = 가변 길이의 문자를 받을 수 있다.

@ResponseBody = BufferedWriter가 존재 @RequestBody = BufferedReader가 존재.


JPA란

JPA는 Java Persistence API 이다. JPA는 ORM 기술이다. JPA는 반복적인 CRUD 작업을 생략하게 해준다. JPA는 영속성 컨텍스트를 가지고 있다. JPA는 DB와 OOP의 불일치성을 해결하기 위한 방법론을 제공한다. (DB는 객체저장 불가능) JPA는 OOP의 관점에서 모델링을 할 수 있게 해준다. (상속, 콤포지션, 연관관계) 방언 처리가 용이하여 Migration하기 좋음. 유지보수에도 좋음. JPA는 쉽지만 어렵다.

영속성 : 영속성(persistence)은 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성

출처: https://sugerent.tistory.com/587 [MISTERY]

램은 휘발성(전기로 저장) 컴퓨터가 꺼지면 다 사라진다.

영속성은 영구히 저장되게 해준다.

저장시 하드디스크 파일시스템에 저장한다 생각하면 되고 비휘발성이다.

API

  • Application: 프로그램
  • Programming : 프로그래밍
  • Interface : 인터페이스

20210625_141700

프로토콜인터페이스 (1:1로 동등하다)

약속 : 약속

근데 약속의 방식이 조금 다르다.

  • 인터페이스 : 상하관계가 존재하는 약속.

일단 중요한건 JPA에 대해 알아두는 것이다. (Java persistence Application Programming interface)


ORM

-> Object Relational RequestMapping

쉽게 말하면 오브젝트를 디비에 연결하는 방법론.

orm 은 하인같은 존재

클래스를 하나 만들었는데 프로그램을 짜다보면 모델클래스들이 있다.

20210625_142845

순서가 테이블 먼저 먼들고 클래스 만든다.

근데 이 순서를 역으로 바꿀 수가 있다.

역으로 클래스를 기반으로 테이블을 만들 수 이쓴ㄴ데 이때 필요한게 JPA가 가지고 있는 인터페이스가 필요하다.

이 인터페이스 규칙 지키면서 클래스 만들면 테이블에 자동 생성되게 하는게ORM이라 한다.

그리고 JPA는 반복적인 작업을 생략하게 해준다.

20210625_143326

이런 일련의 작업들이 함수로 제공된다.

그럼 왼쪽의 반복적인 작업을(crud)를 하지 않아도 된다.

이 기본적으로 반복되는 작업을 JPA가 처리하도록 도와준다.


영속성 : 데이터 -> 영구적으로 저장

컨텍스트 : context는 대상의 모든 정보를 의미한다 보면 된다.

20210625_144356

영숙이의 모든것들을 다 알고 있다.

컨텍스트는 어떤 대상에 달라붙는 모든 정보를 가지고 있음.

내가 다이렉트하게 디비에 접근해서 저장하는게 아니라 중간에 영속성 컨텍스트가 있다. 영속성 컨텍스트는 디비에 저장해야 되는 모든 정보를 알고 있다.

자바프로그램에서 디비에서 왔다갔다 하는 모든 정보를 알고 있다.

select 하면 디비로 바로 가는게 아니라 영속성 컨텍스트로 가서 요청을 한다. 그럼 영속성 컨텍스트는 정보를 안들고 있어서 디비로 가서 데이터를 가져온다.

그리고 데이터를 돌려준다.

20210625_144356

그럼 이 3개의 과일 데이터는 일치하게 된다.

이 상황에서 1의 과일 데이터를 변경(사과->딸기)하면 2의 영속성 과일데이터가 딸기로 변한다.

이떄 3은 인서트가 아니라 업데이트가 일어남.(업데이트 자동으로 호출),

이런 일을 해주는게 영속성 컨텍스트이다.

자바는 항상 영속성 컨텍스트로 저장하고 데이터도 영속성 컨텍스트로 저장이 된다.

20210625_162147

team을 DB에 따르지 않고 int로 만들지 않고 오브젝트로 만들었다? 이 경우가 OOP 모델 만들때 자바가 주도권을 쥐고 있는 모델을 만들 수 있다.

ORM을 통해 OOP의 불일치성을 해결할 수 있으며 디비는 객체 저장이 불가능 하지만 자바는 가능하며 JPA가 자동으로 해준다.


OOP 관점에서의 모델링이란.

  1. JPA로 클래스 먼저 만들고 디비 테이블을 만들게 된다.(자동생성)

20210625_163350

20210625_164315

무슨 디비를 쓰던 인식하고 가능하다


HTTP란

  • 소켓: 운영체제가 가지고 있는 것.

소켓통신 : time slice 동시동작

20210625_171523

5000 소켓에 5001이라는 새로운 스레드를 만들었다.

5001은 B와 통신 그럼 C가 5000번과 통신하는데 이 경우에도 소켓이 만들어진다. 5002가 새로운 스레드가 만들어진다.

소켓통신의 장점은 계속 되있음. 연결이 끊어지지 않음. 부하가 올라서 느려질 수 있음.

http 통신(문서를 전달하는 통신) - Stateless 방식


20210625_173604

20210625_173615

아파치는 요청한 파일을 응답해주고 톰캣은 요청한 파일 중에 자바코드가 요청되면 그것을 컴파일해서 html로 번역해서 돌려주는게 톰캣이다.


서블릿 생명주기

20210625_181319

요청이 왔을떄 서블릿 컨텍스트가 객체를 생성하는 방식이 자바 관련된 요청들이 오면 서블릿이 만들어진다.

자바 코드로 웹을 할 수 있는 게 서블릿이다.

그걸 모아서 컨테이너로 만들어 둔게 서블릿 컨테이너(톰캣)이다.

스레드 생성하고 서블릿 객체에서 수많은 일들을 한다.

이 서블릿 객체에서 db에 연결해서하고 무한정 만들어지는 건 아님.


Web.xml이란

web.xml

-ServletContext의 초기 파라미터 -Session의 유효시간 설정 -Servlet/JSP에 대한 정의 -Servlet/JSP 매핑 -Mime Type 매핑 -Welcome File list -Error Pages 처리 -리스너/필터 설정 -보안

성에 입구가 있다. 이 입구에는 문지기가 있다. 이 문지기는 스스로 일을 할 수 없다. 문지기에게 관리자가 문서를 던진다. 그리고 그 문서대로 일을 하게 한다.

이 일은 관리자에 따라 달라질 수 있다.

20210625_213126

근데 우리는 web.xml인데 이게 달라질 일은 없다.

a라는 사람이 들어오는데 암구호로 넣고 돌아다니다 물어본다 맞으면 정상이고 어떤 사람은 문으로 들어온게 아니라 벽으로 들어온 사람은 암구호를 모른다.

초기파라미터는 설정하면 어디에서든 동작이 가능하다.

세션의 유효기간 설정은

집이 하나 있는데 어떤 사람이 들어오는데 인증을 통해 들어오는게 세션이다. 중요한 어떤 확인하는 게 있다. 은행이나 웹에서 공인인증서라던가 등

세션이 3일로 설정되었다 하면 3일간 막 돌아다닐수 있다. 3일이 지나면 추방당한다. 3일이 지나도 더 있고 싶으면? 세션을 초기화 해야한다. 문지기한테 가서 3일 더 있다고 얘기를 하면 된다.

며칠 있을 수 있는지가 세션이다.

servlet/jsp 에 대한 정의는

a가 가고자 하는 목적지가 있는데 어디로 들어가냐 물어보니까 다라는 곳으로 간다한다. 그럼 얘가 다를 들고 온다. 이 다라는 곳을 찾아서 여기라고 가게 알려준다.

a가 나라는 곳으로 간다하면 문지기인 web.xml에게 말하고 가게 된다.

a라는 사람이 들어올 때 쌀을 들고온다. 그럼 mime타입이 뭔지 물어본다. 그럼 쌀이라고 대답하는데 마임타입은 들고온 데이터의 타입을 의미한다.

그러면 어떤건 아무것도 안들고 올수도 있고 뭐 들고 올 수도 있다. 아무거도 안 들고 온 사람은 서어에 와서 뭘 보기 위함(뭘 주기 위한게 아니라 뭘 보기 위함) 그럼 get 방식을 쓴다.(select)

20210625_214350

반대로 위처럼 쌀을 들고 쌀창고로 보내게 된다. 먹을수 있는지 쌀을 확인 하고 가공을 하게 된다. 이걸 마임타입이라 한다.(Mime Type).

마임타입을 알아야 문지기가 어떤 곳으로 보내야 할지 알게 된다. MimeType 이 틀리게 되면 에러가 난다(쌀창고가 아니라 물창고로 가면 에러나듯)

결론은 들고온 데이터가 뭔지 알려주는게 MimeType이다.

Welcome fileList도 있는데 어디로 갈지 모르고 데이터도 안들고왔다. 그럼 문지기는 어디로 보내야하나 그거에 대한 정의가 있어야한다. 아무 정의 없이 온 애들은 광장으로 보낸다(일거리가 많은) 관리자에 따라 설정하기 나름이다.

그리고 에러페이지 처리도 한다.

파라는 데이터를 가져왔는데 문지기는 파를 저장할 곳이 없다. 이상한 주소로 가져오면 에러페이지로 던지게 web.xml에서 설정하고 그곳으로 보낸다.

리스너/필터는 a가 들어왔을 떄 이 사람의 나라가 b나라면 아예 못 들어오게 하는게 필터, 그리고 총을 가져왔는데 총 소지가 불가하면 못들어오게하는 것도 필터다.

리스너는 고급 관리자 실이있다하면 높은 양반이 거기 있다 치면 거기에서 술은 잘 먹는데 술친구가 없어서 리스너로 술 잘먹는 사람을 찾아내라고 web.xml이 시켰는데 이걸 web.xml이 할 일이 너무 많아서 리스너에게 시킨다. 리스너는 이 경우 술 잘먹는 사람을 확인하는 문지기와 같이 일을 하지만 동시에 지켜보는거 술 잘먹는 사람이 들어오는지만. 그리고 술 잘먹는지 먹여봐서 확인 시켜본다. 그리고 관리자에게 데려간다. 이게 리스너다.

보안은 그냥 보안이다. 이상한 사람 들어오면 쫒아보내는거. 불법 체류자 오면 쫓아보내는거 이런게 보안이다.

여기에서 Servlet/JSP 매핑시(web.xml에 직접 매핑 or @WebServlet 어노테이션 사용)에 모든 클래스에 매핑을 적용시키기에는 코드가 너무 복잡해지기 때문에 FrontController 패턴을 이용함.

문지기(Web.xml)이 할 일이 너무 많아서 이걸 줄여주는게 FrontController이다.


DispatcherServlet이란

FrontController 패턴

.do라는 요청이 들어오면(특정주소) 프런트 컨트롤러로 보내게 된다.
최청의 요청이 왔을 떄

20210625_215126

톰캣으로 가고 response,response 객체를 만든다. 어떤 데이터를 만들고 어떤 데이터를 요청하는지

리퀘스트는 나한테 요청하는 정보가 들어가있고 리스폰스는 응답해줘야 하는 객체이다. web.xml에 특정요소가 들어오면 .do 형식으로 끝나는 주소들을 FrontController에서 낚아챈다.

낚아채서 .do가 들어오면 자원 찾아가게 request한다.

request와 response요청이 들어오는 최총에 요청 request정보를 들고 있으면 a.do를 통해 다시 리퀘스트하게 되면 자원 입장하게 되면 response할 곳은 a.do가 된다.

재요청시에 리퀘스트 했을떄 새로 만드는 게 아니라 덮어 씌우는 방법이 있다.


ApplicationContext란

request와 web.xml -> DispatchServlet(컴포넌트 스캐너)

디스패쳐 서블릿은 주소분배 하고 얘가 요청 들어왔을 떄 어디로 가게 하려면 클래스 여러개 있는데 주소 분배하기 전에 src라는 폴더 안에 (소스폴더) 자바파일이 모여있다.

컴포넌트 스캐너가 자동으로 com.cos.blog 파일에 들어간다.

20210625_233154

DispatchServlet이 읽는 컨트롤러가 몇 있는데 @Controller는 컨트롤러 역할 할거라 알려주는 어노테이션이고 @RestController도 메모리에 띄워놓고 관리해 @Configuration 도 다 메모리에 띄워라 @Repository도 다 메모리에 띄워라 @Service도 다 메모리에 띄워라 @Bean 은 생략 특정 목정이 있으니까 메모리에 띄우라고 어노테이션 쓴다.

@Hello 이런거도 만들 수는 있다.

컨트롤러라는게 있네? 이걸 누가 정해뒀나 메모리가 정해뒀다. 어떤 어노테이션으로 메모리에 띄울 수 있는지 알아놔야 한다.

이거 말고 여기 진입하기 전에 하는일 있는데 contextLoaderListenr가 있다. 요청한 사람에 따라 스레드를 20개 만들면 20개가 만들어진다. 첫번쨰 스레드가 만들어지고 새로운 스레드 만들어지고 충돌날 일이 없다.

이렇게 띄우는 거보다 모든 요청하는게 공통적으로 쓸 수 있는게 있다.

디비에 관련된 것. 혹은 모든 스레드가 공통으로 사용해도 되는건 contextloaderlistner를 통해 띄운다.

root_ApplicationContext파일을 읽는데 xml파일로 커스터마이징 하거나 자바파일로 커스터마이징 가능하다.

20210625_235720

중요한건 컨텍스트 로더 리스너가 루트어플리케이션 컨텍스트 파일을 읽는다 그럼 스레드마다 따로 관리해야되는 거 말고 공통적으로 관리해야 되는 걸 메모리에 띄운다.

DB에선 디스패쳐서블릿이 띄운 애들한테 접근을 못한다. 반대로 디스패쳐서블릿으로 메모리 띄운건 DB에 접근이 가능하다.

디비 접근은 루트 띄워서 가져와서 쓴다.

20210625_235832

(6) DispatcherServlet FrontController 패턴을 직접짜거나 RequestDispatcher를 직접구현할 필요가 없다. 왜냐하면 스프링에는 DispatcherServlet이 있기 때문이다. DispatcherServlet은 FrontController 패턴 + RequestDispatcher이다.

DispatcherServlet이 자동생성되어 질 때 수 많은 객체가 생성(IoC)된다. 보통 필터들이다. 해당 필터들은 내가 직접 등록할 수 도 있고 기본적으로 필요한 필터들은 자동 등록 되어진다.

(7) 스프링 컨테이너 DispatcherServlet에 의해 생성되어지는 수 많은 객체들은 ApplicationContext에서 관리된다. 이것을 IoC라고 한다.

ApplicationContext

IoC란 제어의 역전을 의미한다. 개발자가 직접 new를 통해 객체를 생성하게 된다면 해당 객체를 가르키는 레퍼런스 변수를 관리하기 어렵다. 그래서 스프링이 직접 해당 객체를 관리한다. 이때 우리는 주소를 몰라도 된다. 왜냐하면 필요할 때 DI하면 되기 때문이다.

DI를 의존성 주입이라고 한다. 필요한 곳에서 ApplicationContext에 접근하여 필요한 객체를 가져올 수 있다. ApplicationContext는 싱글톤으로 관리되기 때문에 어디에서 접근하든 동일한 객체라는 것을 보장해준다.

ApplicationContext의 종류에는 두가지가 있는데 (root-applicationContext와 servlet-applicationContext) 이다.

a. servlet-applicationContext

servlet-applicationContext는 ViewResolver, Interceptor, MultipartResolver 객체를 생성하고 웹과 관련된 어노테이션 Controller, RestController를 스캔 한다.

============> 해당 파일은 DispatcherServlet에 의해 실행된다.

b. root-applicationContext

root-applicationContext는 해당 어노테이션을 제외한 어노테이션 Service, Repository등을 스캔하고 DB관련 객체를 생성한다. (스캔이란 : 메모리에 로딩한다는 뜻)

============> 해당 파일은 ContextLoaderListener에 의해 실행된다. ContextLoaderListener를 실행해주는 녀석은 web.xml이기 때문에 root-applicationContext는 servlet-applicationContext보다 먼저 로드 된다.

당연히 servlet-applicationContext에서는 root-applicationContext가 로드한 객체를 참조할 수 있지만 그 반대는 불가능하다. 생성 시점이 다르기 때문이다.

20210626_001130

Bean Factory

필요한 객체를 Bean Factory에 등록할 수 도 있다. 여기에 등록하면 초기에 메모리에 로드되지 않고 필요할 때 getBean()이라는 메소드를 통하여 호출하여 메모리에 로드할 수 있다. 이것 또한 IoC이다. 그리고 필요할 때 DI하여 사용할 수 있다. ApplicationContext와 다른 점은 Bean Factory에 로드되는 객체들은 미리 로드되지 않고 필요할 때 호출하여 로드하기 때문에 lazy-loading이 된다는 점이다.


적절한 응답을 찾는 법

HandlerMapping 이 적절한 함수를 찾음

이 return이 response될때 hello 요청한 쪽으로 흐른다.

web.xml이 자기가 할 일을 기억하고 DispatchServlet에 넘겨서 일감도 주고 디비 관련 작업을 한다. 일단 추상적인 개념을 잡아두자.






© 2021.03. by yacho

Powered by github