
스프링 부트에 내장되어있는 서블릿 컨테이너(Tomcat)에서 다중요청을 처리한다. 스프링과 스프링부트의 주요한 차이점 중 하나는, 스프링 부트에서 내장 서블릿 컨테이너(Tomcat)를 지원한다는 것이다. 톰캣은 다중 요청을 처리하기 위해서 부팅할 때, 스레드풀을 생성함 - 모든 요청에 대해 스레드를 생성하고 소멸하는 것은 OS이나 JVM에 대해 많은 부담을 안겨줄 수 있고, 동시에 일정 이상의 다수 요청이 들어올 경우 리소스(CPU와 메모리 자원) 소모에 대한 억제가 어렵다! HttpServletRequest가 들어오면, 스래드풀에서 하나씩 스레드를 할당 - 해당 스레드에서 스프링부트에서 작성한 Dispatcher Servlet을 거쳐 유저의 요청을 처리함 작업을 모두 수행하고 나면 스레드는 스레드풀로 ..

Architecture JUnit4는 all in one으로, JUnit 라이브러리만 정의해주면 된다 JUnit5는 모듈이 3개(JUnit Platform, JUnit Jupiter, JUnit Vintage)로 나누어져 있다. (+) 테스트 작성자를 위한 API 모듈과 테스트 실행을 위한 API가 분리되어 있다. JUnit Jupiter를 예로 들면, 테스트 코드 작성에 필요한 junit-jupiter-api 모듈과 테스트 실행을 위한 junit-jupiter-engine 모듈로 분리된다. JUnit Platform은 JVM에서 테스트 프레임 워크를 시작하기 위한 기반 역할을 수행한다. TestEngine API가 정의되어 있다. JUnit Jupiter는 new asserts, new annotati..

영속성 컨텍스트란? Entity를 영구 저장하는 환경 애플리케이션과 DB 사이에서 객체를 보관하는 가상의 DB 같은 역할 EntityManager를 통해 영속성 컨텍스트에 접근하고 관리할 수 있음 EntityManager를 통해 Entity를 저장하거나 조회하면, EntityManager는 영속성 컨텍스트에 Entity를 보관하고 관리함 → persist 메서드를 통해 영속성 컨텍스트에 저장 EntityManager는 여러 Thread가 동시에 접근하면 동시성 문제가 발생할 수 있음 영속성 컨텍스트의 장점 동일성(identity) 보장 마치 자바 컬랙션에서 조회하듯이, JPA가 영속 Entity의 동일성을 보장해줌 Entity를 조회해올 때 1차 캐시부터 뒤져서 해당되는 Key값을 가진 Entity가 있..
Redisson이란? Java용 Redis Client 중 하나로, Netty를 사용하여 non-blocking I/O를 사용 Bucket이나 Map 같은 자료구조나 Lock 같은 특정한 구현체의 형태로 레디스의 명령어를 제공 (참고) Lettuce, Jedis과의 비교 redisson vs jedis redisson vs lettuce 분산락이란? 공통된 저장소를 사용하여, 자원의 사용 여부를 체크 - 획득 - 반납하여 분산된 서버의 동기화된 처리를 지원 여러 프로세스가 동시에 공유되는 하나의 자원을 다루는데, 이를 상호 배타적으로 처리해야하는 경우 사용 특정 순간에 한 클라이언트에게만 락 권한을 주고, 다른 클라이언트의 접근은 락을 반환할 때 까지 막음 Lock을 획득하고 어떠한 문제로 인해 애플리케..

컴포넌트 스캔 (의존관계 자동 주입) @Component, @Autowired 어노테이션을 달아서 자동으로 Bean을 생성하고 의존관계 주입 권장 사용처 업무 로직 Bean - Controller, Service, Repository 등 보통 비즈니스 요구사항을 개발할 때 추가되거나 변경되는 로직 - 유사한 패턴을 지니고 있어서 보통 문제가 발생해도 어떤 곳에서 문제가 발생했는지 명확히 파악 가능 수동 Bean 등록 (의존관계 수동 주입) @Configuration 설정 정보에 @Bean을 적고, 객체를 생성하고, 주입할 대상을 일일히 적어줌 권장 사용처 기술 지원 Bean - 공통 관심사(AOP)를 처리할 때 주로 사용 (DB 연결, 공통 로그 처리 등 업무 로직을 지원하기 위한 하부로직/공통 기술) ..

JPA에서는 Open EntityManager(=하이버네이트의 Session) In View 하이버네이트에서는 Open Session(=JPA의 EntityManager) In View 라고 불리우는 OSIV `spring.jpa.open-in-view` 스프링에서는 기본값으로 true가 되어있다. 이처럼 애플리케이션 시작 시점에 warn 로그를 남긴다. 왜일까? OSIV 전략을 살펴보자. 최초 DB Connection 시작 시점(트랜젝션 시작 등)부터 API 응답이 끝날 때까지 영속성 컨텍스트와 DB Connection을 유지한다. 따라서 View Templete이나 API Controller 단에서도 (DB Connection이 유지되므로) 지연 로딩이 가능하다. * 지연 로딩 → 영속성 컨텍스트가 ..
N+1이란? 조회 시 1개의 쿼리만을 생각하고 설계했지만, 추가로 N개의 쿼리가 발생하는 문제를 일컫는다. 즉시로딩(EAGER)의 경우: User 전체를 조회할 때, 각 User의 필드를 채우기 위해 즉시 조회하여 N+1 발생 지연로딩(LAZY)의 경우: User 조회 후 필드에 접근할 때, N+1 발생 fetch join으로 해결하기 즉시로딩에서는 커스텀할 수 있는 부분이 존재하지 않기 때문에, 지연로딩 과정에서 바로 사용을 할 객체에 대해서는 조정이 필요한데, 이때 해결책으로 fetch join을 사용한다. fetch join의 한계점 fetch join은 ~ToMany 관계(컬렉션)가 1개 이하일 때만 가능하며, 이 때 페이징이 가능하지만(distinct 키워드를 사용).. 권장하지 않는다. 일반적..

예시 상황 > form을 통해 받아온 상품 정보로 DB값을 업데이트 하려고 한다 먼저 병합(merge) 기능을 사용한 케이스를 확인해보자. Book 엔티티를 새로 생성해서 form에 받아온 값을 세팅한 후 해당 객체를 서비스 계층의 saveItem 함수의 인자로 넘긴다. ItemController에서 Book 엔티티에 id 값을 세팅한 채로 인자로 넘겼기 때문에, merge 함수를 타게된다. 이 때, 이 Book 엔티티는 트랜잭션 바깥에서 임의로 생성하여 영속성 컨텍스트가 관리하지는 않지만, 유효한 식별자 값을 가지고 있다. 이러한 엔티티를 준영속 엔티티라고 한다. → 준영속 엔티티를 영속 상태로 변경할 때 사용하는 기능이 병합(merge)이다. 여기서는, em.merge(item)의 반환 값이 영속 상..

도메인 모델 패턴 비즈니스 로직 대부분이 entity 내부에 위치하여 각 객체에 객체가 수행해야 하는 업무를 분담 (객체 지향의 특성을 적극 활용) Service 계층은 단순히 entity에 필요한 요청을 위임하는 역할 (예시) 주문 취소 시 배송 상태 유효성 체크 및 상품 재고 원복이 필요할 때 위 예시 처럼 데이터를 가지고 있는 entity 안에서 관련 핵심 비즈니스 로직이 붙는게 응집력 있음 재사용성이 뛰어나지만, entity간의 설계가 수반되어야하기 때문에 모델 구축 시, 객체 간의 관계를 잘 풀어야 함 → 특히 객체 사이의 dependency는 제약사항이 되기 때문에 설계가 매우 중요 트랜잭션 스크립트 패턴 entity에는 비즈니스 로직이 거의 없고(getter/setter 정도만 구현) Ser..

1. 필드 주입 (Field injection) 필드에 바로 주입 코드가 간결해지지만 외부에서 memberRepository 변경이 불가능하여서 테스트가 어려울 수 있음 DI 프레임워크에 의존적 2. 수정자 주입 (Setter injection) setter 메서드를 통해 주입 변경이 가능하기 때문에, 선택이나 변경 가능성이 있는 의존 관계일 때 사용 -> 런타임 시점에도 변경이 가능하다.. -> 필수 값이 아닌 경우에 수정자 주입 방식을 옵션으로 부여하는 것이 바람직 3. 생성자 주입 (Constructor Injection) ★ constructor를 통해 생성자 호출 시점에 단 한 번 주입 (스프링 bean 기준, 생성자가 하나 뿐이면 @Autowired 생략 가능함) 중간에 변경될 일이 없기 때문..