아자아자~~~으아아악 벌써 2시반이네. 3시에 자겠당ㅠ 아직 더 공부할게 남아서 정리가 빈약할지 모르겠지만, 일단 이정도로 정리를 하고 더 심화된 학습은 남은 강의를 들으면서 더 보완을 할 계획이다.
현재 영속성 컨텍스트에 대해 좀 더 심도있게 공부를 하고 싶지만, 지금 당장 담주까지 만들어서 제출먼저 하고, 그 다음에 이론을 공부하도록 하자.
MVC?
model-view-controller 디자인 패턴.
스프링에서 mvc를 쓴다는 것은 즉, 템플릿엔진을 사용하여 클라이언트한테 파일을 렌더링해서 뿌려준다는 것이다.
컨트롤러가 다음의 일들을 처리.
- Client 의 요청을 Model 로 받아 처리
- Template engine 에게 View, Model 전달
- View: 동적 HTML 파일
- Model: View 에 적용할 정보들
- Template engine
- View 에 Model 을 적용 → 동적 웹페이지 생성
- 예) 로그인 성공 시, "로그인된 사용자의 id" 를 페이지에 추가
- Template engine 종류: 타임리프 (Thymeleaf), Groovy, FreeMarker, Jade 등 (스프링에서 JSP 이용은 추천하지 않고 있음)
- View 에 Model 을 적용 → 동적 웹페이지 생성
- Client 에게 View (동적 웹 페이지, HTML) 를 내려줌
스프링 MVC
- Contrller 와 HTTP Response 메시지
- @ResponseBody도 쓰고 @Controller도 쓰는게 귀찮아서 합친게 @RestController다
- 스프링 MVC 동작원리
- 25) 스프링 MVC 동작원리
- Client → DispatcherServlet
- 가장 앞 단에서 요청을 받아 FrontController 라고도 불림
- DispatcherServlet → Controller
- API 를 처리해 줄 Controller 를 찾아 요청을 전달
- Handler mapping 에는 API path 와 Controller 함수가 매칭되어 있음
GET /hello/html/dynamic* → HomeController 의 helloHtmlFile() 함수 GET /user/login* → UserController 의 login() 함수 GET /user/signup* → UserController 의 signup() 함수 POST /user/signup* → UserController 의 registerUser() 함수
- 함수 이름을 내 마음대로 설정 가능했던 이유!!
- Controller 에서 요청하는 Request 의 정보 ('Model') 전달
-
@Controller public class ItemSearchController { @GetMapping("/api/search") @ResponseBody public List<ItemDto> getItems(@RequestParam String query) { // ... } }
- Controller → DispathcerServlet
- Controller 가 Client 으로 받은 API 요청을 처리
- 'Model' 정보와 'View' 정보를 DispatcherServlet 으로 전달
- DispatcherServlet → Client
- ViewResolver 통해 View 에 Model 을 적용
- View 를 Client 에게 응답으로 전달
- Client → DispatcherServlet
- 25) 스프링 MVC 동작원리
스프링MVC에서의 Request
- 26) Controller 와 HTTP Request 메시지
- @RequestParam은 파라미터로 오는것도 받고, Form data로 오는것도 받는다.
ORM이란
웹서버 언어와 디비언어(sql)가 다르기에 중간에서 통역사 역할을 해주는 것.
ORM이 없어도 그냥 순수 sql문 쳐서 개발할 수 있음
그러나 단점이 너무 명백하다.
- ORM 이 없는 환경에서는 백엔드 개발자가 비즈니스 로직 개발보다 SQL 작성에 더 많은 노력을 들여야 하더라..
- SQL 작성이 단순하고 반복적인데, 실수하기는 쉬움
위 단점을 극복하고자 JPA가 나왔다.
JPA의 등장
jpa는 ORM기술에 대한 표준 명세이다. 모델 클래스에 @Entity를 붙이면 디비에 테이블과 칼럼이 생기는 것이 그 예이다.
과거에는 SQL매퍼(MyBatis, Jdbc Template)을 사용했지만 현재는 세계적으로 jpa가 대세이다
하이버네이트란?
JPA는 표준명세이고, 이를 실제로 구현한 프레임워크이다. 그 중에 사실상 표준이라 할 수 있다.
스프링 부트에서 기본적으로 "하이버네이트" 사용 중.(de facto)
영속성 컨텍스트란?
영속성 컨텐스트란 엔티티를 영구 저장하는 환경이라는 뜻이다. 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스 같은 역할을 한다. 엔티티 매니저를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.
em.persist(member); 를 하면 member엔티티를 영속성 컨텍스트에 저장한다.
- 영속성 컨텍스트의 이점:
- 1차 캐시
- 동일성 보장
- 트랜잭션 지원
- 변경 감지
- 지연로딩
영속성 컨테스트 1차캐시 이해
장점:
- 디비서버에 직접 다녀오는 횟수를 줄임으로써 프로그램속도 매우 효율적으로 관리 가능
- 객체 동일성 보장(1차캐시에 이미 있으면 디비에서 가져오지 않고 1차캐시에 있는걸 반환해주기 때문에 같은 객체가 나온다)
- 조회시. 기본적으로 다음처럼 동작.
- 1차 캐시에 조회하는 Id 가 존재하는 경우
- 1차 캐시에 조회하는 Id 가 존재하지 않은 경우
- 그외 CRUD중에서 업데이트가 특이하다.
- Entity 업데이트 방법 (1)
- userRepository.save() 사용
- [UserService] Entity 업데이트 방법 (1)
-
public User updateUser1() { // 테스트 회원 "user1" 생성 User user = new User("user1", "RM", "고기"); // 회원 "user1" 객체를 영속화 User savedUser1 = userRepository.save(user); // 회원의 nickname 변경 savedUser1.setNickname("남준이"); // 회원의 favoriteFood 변경 savedUser1.setFavoriteFood("육회"); // user1 을 저장 User savedUser2 = userRepository.save(savedUser1); assert(savedUser1 == savedUser2); return savedUser2; }
- Entity 업데이트 방법 (2)
- @Transactional 을 추가
- 굳이 userRepository.save() 함수를 호출하지 않아도, 함수가 끝나는 시점에 변경된 부분을 알아서 업데이트 해 줌 (이를 "Dirty check" 라고 함)
- 간단히 함수가 종료되는 시점에 각 Entity 에 save() 가 호출된다라고 이해
- 정확한 이해 위해 필요한 추가학습 내용
: 쓰기 지연 SQL 저장소, flush, commit 등
-
@Transactional public User updateUser2() { // 테스트 회원 "user1" 생성 // 회원 "user1" 객체 추가 User user = new User("user1", "진", "꽃등심"); // 회원 "user1" 객체를 영속화 User savedUser = userRepository.save(user); // 회원의 nickname 변경 savedUser.setNickname("월드와이드핸섬 진"); // 회원의 favoriteFood 변경 savedUser.setFavoriteFood("까르보나라"); return savedUser; }
아그리고 부끄러워서 공개안하고 싶은데,, 어차피 공개하려고 만든거니까 공개하겠다. 현재 자바스터디와 알고리즘 스터디를 하고 있는데 발표한내용을 정리해서 녹화하려고 한다. 그 외에 공부한 내용관련한 것도 올릴 예정이다. 아 다시 보니까 너무 말 못한다ㅠㅠㅠ계속 하다 보면 잘하겠지ㅠ
댓글