@MappedSuperClass


 

> 객체의 입장에서 공통된 매핑 정보가 필요할 때 부모 클래스에 선언하고 속성만 사용하고 싶을 때 사용한다.

  1. 자식 클래스만 @Entity로 수식되고 테이블로 전환한다.
  2. 자식클래스는 상속받은 필드까지 테이블에 저장한다.
  3. 부모클래스는 테이블이 생성되지 않으므로 추상 클래스로 구현하면 좋다.
  4. 공통된 정보를 모으는 역할을 한다.

 

 

@MappedSuperClass 사용 예제


공통속성을 부모클래스로 만들고 자식 클래스에게 상속시키면 된다.

CouponBaseEntity.class

Coupon.class

UserCoupon.Class

 

 

@MappedSuperClass 저장


부모클래스에서 생성자를 만들어 주고 생성자를 호출하여 저장한다.

 

1. 인터셉터란


스프링 인터셉터는 디스패처가 컨트롤러에게 요청하기 전 데이터를 가로채는 것이다.

 

 

2. 구성요소

 


핸들러 인터셉터는 세 가지 메서드가 있다.

 

  • preHandle() – 실제 핸들러가 실행되기 전에 호출됨
  • postHandle()  핸들러가 실행된  호출
  • afterCompletion()  전체 요청이 완료되고 뷰가 생성된 후 호출됩니다.

 

2-1 preHandle() 메서드

> 인터셉터가 요청을 처리하기 전에 호출합니다. 기본적으로 true를 반환하여 다음 메서드가 실행되지만, false가 실행되면 요청을 중지합니다.

 

2-2 postHandler() 메서드

> 핸들러(Controller) 실행 후 DispatcherServlet이 뷰를 렌더링 하기 전에 이 메서드를 호출합니다.

 

2-3 afterCompletion() 메서드

> 뷰가 렌더링 된 후 이 메서드를 사용하여 요청 및 응답 데이터를 얻을 수 있습니다.

3. 구현


HandlerInterceptor 또는 HandlerInterceptorAdaptor 인터페이스를 상속받고 구현해야 하지만 스프링이 알 수 있도록 등록해줘야 한다.

WebMvcConfigurer에 addInterceptors 메서드를 오버라이드 하여 특정 url이 호출될 때 가로챌 수 있도록 등록해 준다.

커스텀 인터셉터 만들기
Handler 등록

내가 사용하는 것은 spring boot이므로 spring을 사용하면 web.xml에 등록해주자. 또한 spring boot를 사용하는 경우 구성 클래스에 @EnableWebMvc를 달 필요가 없다고 한다.

 

4. 왜 사용하는가?


컨트롤러가 실행되기 전 요청을 가로채므로 추가적인 작업을 요청할 때 사용할 수 있다. 권한 체크라든지 로그인 체크 등을 할 수 있을 것 같다. 사전에 불필요한 요청을 방지하므로 컨트롤러의 역할이 줄일 수 있지 않을까 한다.

스프링을 공부하면서 서버에서 데이터를 받는 방법이 여러 가지 있지만 대표적인 2가지는

@RequestBody 와 @RequestParm이 있다. 이 둘의 차이는 데이터를 어떤 타입으로 받을 것인지를 결정하는 것 같다.

 

여기서 어떻게 사용하는지와 정의하는지는 생각해보지 않을 것이다. FORM 태그에서 보내는 ENCTYPE에 따라 어노테이션이 결정되는 것을 말해보고 싶다.

 

이 ENCTYPE의 속성 값들은 application/x-www-form-urlencoded , multipart/form-data, text/plain 등 있다.

@RequestBody를 사용한다면 스프링이 클라이언트로부터 넘어온 값을 사용자가 정의한 데이터 타입으로 매핑해준다. 그런데 넘어온 타입이 Json 형태이지 않는다면 오류 내보낸다. Content-type을 정해주지 않는다면 default값인 application/x-www-form-urlencoded로 데이터를 보내줄 것이다. 그렇기에 application/json으로 바꿔야 데이터를 보낼 수 있다.

 

@RequestParm을 사용한다면 default값으로 보내도 충분히 매핑될 수 있다.

 

 

 

 

@RequestBody -> application/json 사용

@RequestParm -> application/x-www-form-urlencoded 사용

클라이언트가 서버에 요청을 하게 되면 해당 요청 경로를 찾아 데이터를 받거나 해당 View 페이지를 보여 주어야 한다. 그것을 도와주는 역할이 Controller이다.

@RestController - Data


@RestController는 클라이언트로부터 요청이 오면 적절한 값을 클라이언트에게 보내준다.

 

 

@Controller - View 


@Controller도 마찬가지로 적절한 값을 클라이언트에게 보내주는 역할을 한다.

 

 

@Controller와 @RestController의 차이점


 

Controller

  1.  클라이언트가 url로 요청을 보내온다면 
  2.  디스패쳐가 적절한 hadler를 Mapping 하여 컨트롤러에게 요청을 보내고 
  3.  Controller는 요청받은 정보를 토대로 View(페이지) 또는 Data( DB로부터 값을 받아온다 )를 요청한 클라이언트에게 보내준다. 

 

@Controller는 주로 View를 반환하기 위해 사용된다. 클라이언트로부터 요청이 오면 적절한 주소를 매핑하여 클라이언트에게 페이지를 보여주는 역할을 한다.

 

@RestController는 주로 Data를 반환하는 경우도 있다. @ResponseBody가 자동으로 붙어서 반환된다.

 

 

컨트롤러를 구분짓는 이유에 대한 나의 생각


이 두개의 컨트롤러가 하는 역할은 같지만 결과 값은 완전히 다른 모습을 보여준다.

굳이 왜 이렇게 만들었을까 생각해 보자면 데이터 값과 페이지를 구분하기 위해서이지 않을까 싶다.

홈페이지를 만들게 된다면 무수히 많은 URL 요청이 있을 것이며 데이터 요청도 많이 이루어질 것이다.

이 두개의 컨트롤러를 구분하지 않는다면 개발자가 어떤 것이 View를 띄우는 컨트롤러이고 Data를 보내는 컨트롤러인지 헷갈리게 될 것이다. 그렇기에 구분을 하여 가독성이나 유지보수를 높여주기 위함이지 않을까 생각한다.

 

이미지 출처: https://www.genuitec.com/spring-frameworkrestcontroller-vs-controller/

계속해서 Spring boot를 연습하기 위해서 홈페이지를 만들고 있는데 로그인 페이지가 여러 번 호출된다..

왜 이러는 걸까? spring security를 더 공부해야 할듯하다...

 

프록시 객체란

데이터베이스를 조회하지 않고 가짜 객체를 생성하여 조회하는 객체를 반환하는 것을 말한다.

 

ex) 유저 테이블에는 많은 정보들이 들어가 있을 것이다. 유저 객체가 필요할 때 주소, 작성 글등을 전부 불러온다면 데이터베이스에 많은 쿼리문을 날리게 될 것이다. 이것을 최소화 하기위해 사용한다.

 

 

프록시 특징

  • 프록시 클래스는 실제 클래스를 상속 받아서 만들어지므로 실제 클래스와 겉 모양이 같다.
  • 프록시 객체는 실제 객체에 대한 참조를 보관한다.
  • 프록시 객체는 처음 사용할 때 한 번만 초기화 한다.
  • 프록시 객체를 초기화한다고 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 프록시 객체가 초기화 되면 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다.
  • 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 데이터베이스를 조회할 필요가 없으므로, entityManager()를 호출해도 프록시가 아닌 실제 엔티티를 반환한다.
  • 초기화는 영속성 컨텍스트의 도움을 받아야 가능하다. 따라서 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태의 프록시를 최기화하면 문제가 발생한다.

프록시 객체 초기화

user.getName() 처럼 실제 사용될 때 데이터 베이스를 조회해서 실제 엔티티 객체를 생성하는데 이것을 프록시 객체의 초기화라 한다.

 

 

여기서 지연로딩과 즉시로딩이란 중요한 개념이 있었는데 다음 포스트에 정리하자!

이런 거 궁금해서 사용해보고 싶지만 JPA연결이 안 돼서 못하고 있다... 2시간 동안 도전해봤지만 포기하고 그냥 내용만 정리하려고 한다..  

 

@Transactional : 프록시 객체가 생성되어 자동으로 commit, rollback을 진행해준다.

 

  • isolation : 트랜잭션에서 일관성 없는 데이터 허용 수준을 설정한다
  • propagation : 트랜잭션 동작 도중 다른 트랜잭션을 호출할 때, 어떻게 할 것인지 지정하는 옵션이다
  • noRollbackFor : 특정 예외 발생 시 rollback하지 않는다.
  • rollbackFor : 특정 예외 발생 시 rollback한다.
  • timeout : 지정한 시간 내에 메서드 수행이 완료되지 않으면 rollback 한다. (-1일 경우 timeout을 사용하지 않는다)
  • readOnly : 트랜잭션을 읽기 전용으로 설정한다.

  • DEFAULT : 기본 격리 수준
  • READ_UNCOMMITED (level 0) : 커밋되지 않는 데이터에 대한 읽기를 허용
  • READ_COMMITED (level 1) : 커밋된 데이터에 대해 읽기 허용
  • REPEATEABLE_READ (level 2) : 동일 필드에 대해 다중 접근 시 모두 동일한 결과를 보장
  • SERIALIZABLE (level 3) : 가장 높은 격리, 성능 저하의 우려가 있음

이야;;; @Autowired 너무 편하다..ㅋㅋㅋㅋ 내 기억으로 스프링이 bean을 관리해준다. 싱글톤으로 관리해주기 때문에 몇 개를 생성해도 똑같은 객체가 나와주는 걸로 알고 있다.

+ Recent posts