
제어의 역전
의존성 주입
@Bean , @Configuration 을 이용해서 직접 등록@Component 어노테이션스프링 IoC 컨테이너 생성 → 스프링 Bean 생성 → 의존성 주입 → 초기화 콜백 메서드 호출 → Bean 사용 → 소멸 전 콜백 메서드 호출 → 스프링 종료
@PostConstruct 로 초기화 / @PreDestory 로 소멸콜백 메서드 : 개발자가 정의한 클래스나 인터페이스에 의해 호출되는 메서드
ex) @PostConstruct - init() / @PreDestroy - destroy()
빈이 언제 생성되고, 언제 소멸되는지 → 싱클톤 / 프로토타입 / Rquest / Session
Spring이 Bean으로 등록된 객체의 라이프 사이클과 의존성을 관리해 주는 컨테이너
애플리케이션 실행 시점에 Bean 객체를 인스턴스화하고, 의존성을 주입한 뒤에 최초로 애플리케이션을 기동 할 빈 하나를 제공해 줍니다.
MVC는 Model, View, Controller의 약자로, 애플리케이션을 구성하는 컴포넌트들의 역할을 크게 3가지로 구분한 것
레어이드 아키텍처는 애플리케이션을 구성하는 컴포넌트를 레이어로 묶어서 수평적으로 구성한 구조
Spring Boot Project를 만들 때 MVC 패턴과 레이어드 아키텍처를 이용하여 프로젝트 구조를 설계
4 계층으로 표현될 경우 인프라 계층(DB)까지 포함한 것

REST 방식의 경우
데이터를 MessageConverter를 통해 JSON 형식으로 변환하고, ResponseBody로 응답
REST 방식이 아닌 경우
View Resolver를 찾아서 실행하고, 이 ViewResolver는 View에 전달할 데이터를 추가하여 클라이언트에게 View를 반환합니다.
ORM이란 ?
Object Relational Mapping으로, 객체 관계 매핑을 의미합니다. 객체지향 언어에서 객체와 RDB의 테이블을 자동으로 매핑해 주는 기술입니다.
DB 테이블을 마치 객체처럼 다룰 수 있게 해 주어서, SQL문 대신 코드로 DB를 다룰 수 있게 도와줍니다.
장점
JPA는 자바 진영에서 표준으로 된 ORM이고, JPA는 인터페이스의 집합이다.
즉 JAVA에서 사용하는 ORM 표준은 JPA이다.
Spring data JPA라는 라이브러리를 주로 사용
JPA는 인터페이스라고 하였는데, JPA의 대표적인 구현체 중 하나인 Hibernate를 개발자가 사용하기 쉽게 모듈화 한 것이 Spring data JPA
영속성 컨텍스트는 트랜잭션 단위로 동작
트랜잭션이 시작될 때 EntityManger가 생성되고, 1대 1로 영속성 컨텍스트가 생성
트랜잭션이 커밋되면 EntityManger와 영속성 컨텍스트 모두 사라지게 된다.
1차 캐시
영속성 컨텍스트 내에 위치하여 캐시와 같은 역할 수행
마찬가지로 저장할 떄도 1차 캐시에 우선 저장되고 트랜잭션 커밋 시에 실제 DB에 저장한다.
동일성 보장
1차 캐시에 의해 엔티티는 영속성 컨텍스트에 관리되고, SELECT 해올 때 1차 캐시에서 데이터를 불러온다. 이 때문에 JPA로 같은 데이터를 두 번 조회하면 두 데이터는 주소까지 일치하게 되어 == 비교가 가능하다.
쓰기 지연
트랜잭션이 커밋되기 전 까지 영속성 컨텍스트 내에 위치한 쓰기 지연 SQL 저장소에 SQL 쿼리를 저장해 뒀다가 트랜잭션이 커밋되는 시점에 모든 SQL을 DB에 전달
변경 감지
엔티티가 변경되면 따로 저장하거나, 수정하는 코드 또는 쿼리를 작성하지 않아도 자동으로 변경
처음 DB에서 데이터를 SELECT 하여 1차 캐시에 데이터를 저장할 때 스냅샷을 저장해 뒀다가 커밋이 일어날 때 이 스냅샷과 비교하여 UPDATE 쿼리를 자동으로 생성하여 DB에 전달
지연 로딩
연관관계가 있는 엔티티가 있을 때, 해당 엔티티를 실제 사용할 때 SELECT 쿼리를 날리는 기능
연관관계의 주인인 Entity를 조회할 때 연관관계 Entity까지 동시에 불러오게 되는 즉시로딩과 대비되는 개념
N + 1 문제란 ?
N + 1 문제는 연관관계 설정된 필드가 있는 Entity를 findAll() 메서드를 이용해서 여러 건의 Entity를 한 번에 조회할 때 발생하는 문제. findAll()로 조회한 Entity의 개수만큼, 연관관계 Entity에 대한 단건 조회 쿼리가 나간다.
findAll() 로 n개의 데이터를 조회했을 때, 연관관계 Entity에 대한 단건 조회 쿼리가 n번 나가게 되어 총 n + 1 개의 쿼리가 나가게 된다.
여기서 단건 조회 쿼리는 findById() 와 같은 쿼리를 말한다.
해결방법
@Query 어노테이션을 이용해서 JPQL을 직접 작성하여 join fetch 구문을 추가하여 연관관계 Entity까지 한번에 조회하는 방법으로 해결할 수 있다.
@Query("SELECT distinct t FROM Team t join fetch t.members")
List<TeamEntity> findAll();
이 문제는 지연 로딩, 즉시 로딩 모두 발생한다.
즉시 로딩 시에는 조회 메서드 사용 시 findAll()을 한 Entity를 불러오는 쿼리가 1번 나가고, 연관 관계 Entity에 대한 단건 조회 쿼리가 n번 나간다.
지연 로딩 시에는 findAll() 메서드 사용 시 1번의 쿼리만 나가지만 마찬가지로 조회한 메서드를 순회하며 연관관계 Entity를 사용한다면 연관관계 Entity에 대한 단건 조회가 n번 나간다.
지연 로딩 시 findAll()로 불러온 List중 하나의 데이터의 연관관계 Entity만 조회한다면 1번만 추가로 쿼리가 나간다.