Backend 44

프록시와 지연 로딩

프록시가 필요한 이유 다음 예제는 회원 엔티티를 찾아서 회원과 팀의 이름을 출력한다. Member member = em.find(Member.class, memberId); Team team = member.getTeam(); System.out.println("회원 이름: " + member.getName()); System.out.println("팀 이름: " + team.getName()); 반면 다음 예제는 회원 엔티티를 찾아서 회원의 이름만 출력하고, 회원과 관련된 팀 엔티티는 전혀 사용하지 않는다. Member member = em.find(Member.class, memberId); Team team = member.getTeam(); System.out.println("회원 이름: " + ..

Backend/JPA 2024.01.09

양방향 연관관계 매핑

객체와 테이블의 차이 객체의 양방향 연관관계: 정확히 말하자면 객체에는 양방향 연관관계가 없다. 서로 다른 단방향 연관관계 2개가 양방향처럼 보일 뿐이다. 회원 -> 팀 팀 -> 회원 테이블의 양방향 연관관계: 반면 데이터베이스 테이블은 외래 키 하나로 양쪽에서 서로 조인할 수 있다. 즉 외래 키 하나로 두 테이블은 양방향 연관관계를 맺는다. 회원 팀 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다. 따라서 엔티티를 단방향으로 매핑하면(단방향 연관관계), 참조를 하나만 사용하므로 이 참조로 외래 키를 관리하면 된다. 그런데 엔티티를 양방향으로 매핑하면(양방향 연관관계), '회원 -> 팀', '팀 -> 회원' 두 곳에서 서로를 참조한다. 즉 테이블의 외래 키는 하나인데, 객체에서 연관관계를 관리하..

Backend/JPA 2024.01.09

기본 키 매핑

JPA의 기본 키 매핑 JPA는 엔티티들을 영속성 컨텍스트에서 관리하는데, 영속성 컨텍스트에서 관리되려면 엔티티를 구분할 수 있는 식별자가 반드시 필요하다. 식별자가 되는 필드는 엔티티 클래스에서 @Id 어노테이션을 통해 지정할 수 있다. JPA가 제공하는 기본 키 생성 전략은 다음과 같다. 직접 할당: 기본 키를 애플리케이션에서 직접 할당한다. 자동 생성 IDENTITY: 기본 키 생성을 데이터베이스에 위임한다. SEQUENCE: 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다. TABLE: 키 생성 테이블을 사용한다. 자동 생성 전략이 이렇게 다양한 이유는 데이터베이스 벤더마다 지원하는 방식이 다르기 때문이다. 예를 들어 오라클은 시퀀스를 제공하지만 MySQL은 시퀀스를 제공하지 않고 그 대신에 기..

Backend/JPA 2024.01.09

엔티티 매니저와 영속성 컨텍스트

엔티티 매니저 팩토리(entity manager factory), 엔티티 매니저(entity manager) 엔티티 매니저는 엔티티를 저장, 수정, 삭제, 조회하는 등 엔티티와 관련된 모든 일을 처리한다. 이름 그대로 엔티티를 관리하는 관리자이다. 엔티티 매니저 팩토리는 이름 그대로 엔티티 매니저를 만드는 공장인데, 엔티티 매니저 팩토리를 생성하는 비용은 매우 크다. 따라서 한 개만 생성해서 애플리케이션 전체에서 공유하도록 설계되어 있다. 반면, 공장에서 엔티티 매니저를 생성하는 비용은 거의 들지 않는다. 그리고 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드 간에 공유해도 되지만, 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대..

Backend/JPA 2024.01.05

서블릿의 예외 처리, 스프링의 예외 처리(HandlerExceptionResolver)

서블릿의 예외 처리 서블릿의 예외 처리 흐름 먼저 스프링이 아닌 순수 서블릿 컨테이너는 어떻게 예외 처리를 하는지 알아보자. 서블릿은 다음 2가지 방식의 예외 처리를 지원한다. Exception 순수 자바 프로그램의 경우, 자바의 main 메서드를 직접 실행하면 main이라는 이름의 스레드가 실행된다. 그리고 실행 도중에 발생한 예외를 잡아서 처리하지 않으면 처음에 실행한 main 메서드까지 예외가 넘어가고, 예외 정보를 남기며 해당 스레드는 종료된다. 반면, 웹 애플리케이션은 사용자 요청별로 별도의 스레드가 할당되고 서블릿 컨테이너 안에서 실행된다. 만약 컨트롤러에서 예외가 발생했는데 이를 잡지 못하면 어떻게 될까? 예외 발생시 흐름은 다음과 같다. WAS(여기까지 예외 전파) ⬅️ 필터 ⬅️ 서블릿 ..

Backend/Spring 2024.01.04

Filter, Interceptor

Filter 필터는 서블릿이 지원하는 기능이다. 필터는 다음과 같은 특징을 갖는다. 필터의 흐름: HTTP 요청 ➡️ WAS ➡️ 필터 ➡️ 서블릿(디스패처 서블릿) ➡️ 컨트롤러 즉, 디스패처 서블릿의 앞 단에서 필터가 동작하기 때문에, 필터는 스프림 범위 밖에서 처리되는 것이다. (스프링의 시작이 디스패처 서블릿이라고 이해하면 된다.) 즉, 스프링 컨테이너가 아닌 톰캣과 같은 서블릿 컨테이너에 의해 관리된다. Filter 등록 필터를 사용하려면 Filter 인터페이스를 구현하고, 해당 객체를 필터로 등록해야 한다. 그러면 서블릿 컨테이너가 필터를 싱글톤으로 생성하고 관리한다. Filter 인터페이스 public interface Filter { default void init(FilterConfig ..

Backend/Spring 2024.01.04

Spring MVC의 구조(DispatcherServlet, HandlerMapping, HandlerAdapter)

DispatcherServlet public class DispatcherServlet extends FrameworkServlet {} DispatcherServlet은 표현 계층 전면에서 HTTP 프로토콜을 통해 들어오는 모든 요청을 가장 먼저 받아 공통 작업을 처리하고, 적합한 컨트롤러에게 요청을 위임해주는 프론트 컨트롤러이다. 즉, 클라이언트로부터 어떠한 요청이 오면 톰캣과 같은 서블릿 컨테이너가 요청을 받는다. 그리고 이 모든 요청을 프론트 컨트롤러인 디스패처 서블릿에게 보낸다. 그러면 디스패처 서블릿은 공통적인 작업을 처리한 후에 해당 요청을 처리해야 하는 컨트롤러를 찾아서 요청을 위임한다. DispatcherServlet의 상속 관계는 다음과 같다. 즉, DispatcherServlet도 결..

Backend/Spring 2024.01.03

Web Server, WAS, Servlet

Web Server 웹 서버는 클라이언트가 웹 브라우저에서 어떠한 페이지 요청을 하면 웹 서버에서 그 요청을 받아 정적 컨텐츠를 제공하는 서버이다. 여기서 정적 컨텐츠란 html 문서, css, 자바스크립트, 이미지, 영상 등 즉시 응답 가능한 컨텐츠이다. 동적인 컨텐츠 요청시에는 WAS에게 클라이언트의 요청을 전달하고, WAS가 처리한 결과를 클라이언트에게 전달한다. WAS(Web Application Server) WAS는 웹 서버의 기능을 포함하여 정적 컨텐츠를 제공할 뿐만 아니라, DB 조회나 비즈니스 로직 처리 등을 요구하는 동적 컨텐츠도 제공하는 애플리케이션 서버이다. 즉 WAS는 "Web Server + Web Container(Servlet Container)"라고 정의하기도 한다. 그래서..

Backend/Spring 2024.01.02

빈 스코프

빈 스코프는 빈이 존재할 수 있는 범위를 뜻한다. 스프링은 다음과 같은 스코프를 지원한다. 싱글톤: 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다. 프로토타입: 스프링 컨테이너가 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는, 매우 짧은 범위의 스코프이다. 웹 관련 스코프: request: HTTP 요청 하나가 들어오고 나갈 때까지 유지된다. 각각의 HTTP 요청마다 별도로 빈 객체가 생성되고 관리된다. session: HTTP Session과 동일한 생명주기를 갖는다. application: 웹의 서블릿 컨텍스트와 동일한 생명주기를 갖는다. websocket: 웹 소켓과 동일한 생명주기를 갖는다. 싱글톤 스코프 싱글톤 빈은 스프링 컨테이너 생성 시점에 ..

Backend/Spring 2023.12.30

빈 생명주기 콜백을 통한 스프링 빈 객체의 초기화/종료 작업

데이터베이스 커넥션 풀이나 네트워크 소켓처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고 애플리케이션 종료 시점에 연결을 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요하다. 객체의 초기화는 스프링 컨테이너에 해당 객체가 스프링 빈으로 생성되고 의존관계 주입이 완료된 후에 진행해야 하고, 객체의 종료는 해당 객체의 빈이 소멸되기 직전에 진행해야 한다. 참고로 객체가 스프링 빈으로 생성된 후에 객체의 초기화 작업을 해야 하는 이유는 다음과 같다. 생성자는 필수 정보를 파라미터로 받고 메모리를 할당해서 객체를 생성하는 책임을 가진다. 반면 초기화는 이렇게 생성된 객체를 외부 커넥션과 연결하는 등 무거운 동작을 수행한다. 따라서 생성자 안에서 무거운 초기화 작업까지 함께 하는 것보다는 객..

Backend/Spring 2023.12.29