Java & Spring/Spring 6

OSIV · 낙관적 락 · 비관적 락

1. OSIV (Open Session In View)OSIV란?기본적으로 영속성 컨텍스트는 @Transactional 메서드 단위로 살아있다. OSIV가 켜지면 이 생명주기가 HTTP 요청 단위로 확장된다. Filter/Interceptor 레벨에서 영속성 컨텍스트를 열고, HTTP 응답이 클라이언트에게 보내질 때까지 유지한다.Spring Boot는 OSIV를 기본적으로 켜놓는다 (spring.jpa.open-in-view=true).OSIV가 켜져 있을 때HTTP Request 도착 → OpenEntityManagerInViewInterceptor.preHandle() → EntityManager 생성 (영속성 컨텍스트 시작) → Controller → Service (@Transaction..

Spring Batch 개념, 사용

배치(Batch)란?배치는 대량의 데이터를 한 번에 일괄 처리하는 방식을 말한다.실시간으로 요청이 들어올 때마다 처리하는 게 아니라, 데이터를 모아뒀다가 한꺼번에 처리하는 것이다.대표적인 사용 사례는 아래와 같다.일매출 집계 — 하루치 거래 데이터를 새벽에 한 번에 집계구독 메일 발송 — 정해진 시간에 구독자 전체에게 메일 일괄 전송데이터 백업 — 트래픽이 적은 새벽 시간대에 DB 백업Batch vs Scheduler여기서 헷갈릴 수 있는 게 Batch와 Scheduler의 차이다.구분 역할Batch대량 데이터를 일괄 처리하는 것Scheduler정해진 시간에 작업을 실행시키는 것배치는 "대량 처리"를 의미하는 것이지, 주기적으로 실행된다는 뜻이 아니다.Spring Batch는 Quartz 같은 스케줄러와..

페이지네이션의 원리? 필요성?

들어가며Spring으로 목록 API를 만들다 보면 Pageable, Page, Slice를 자연스럽게 쓰게 된다. 근데 막상 "이게 내부적으로 어떻게 동작해?"라고 물어보면 설명을 잘 못했었다. 이 글에서는 페이징이 왜 필요한지부터 OFFSET 방식의 한계, 커서 기반 페이징의 원리까지 차근차근 정리해보자!왜 페이징이 필요할까?SELECT * FROM users;데이터가 100만 건이면 이 쿼리 한 방에 전부 가져온다. 메모리가 터지고 응답도 한없이 느려진다. 잘라서 가져오는 것이 페이징이다.OFFSET 기반 페이징원리DB에서 페이징을 구현하는 가장 기본적인 방법은 LIMIT과 OFFSET을 쓰는 것이다.SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 0; -- ..

[MapStruct] 내부 구현 방식 - 설계 문제 해결

문제 상황BaseEntity에서 @Setter를 제거했더니 MapStruct Mapper에서 컴파일 오류가 발생했다.error: Property "id" has no write accessor in User for target name "user.id". ReadStatus toEntity(ReadStatusCreateRequest request);error: Property "id" has no write accessor in Channel for target name "channel.id". ReadStatus toEntity(ReadStatusCreateRequest request);처음엔 단순히 Setter가 없어서 생긴 오류라고 생각했다.ignore = true를 붙이거나 Setter..

Spring 프록시 원리

Spring의 프록시(Proxy)가 뭔지 제대로 이해해보자스프링을 공부하다 보면 "프록시"라는 말이 자꾸 나온다!@Transactional도 프록시, @Cacheable도 프록시, @Configuration도 프록시...도대체 프록시가 뭔지, 왜 쓰는 건지 알아보자!프록시가 뭘까?프록시를 한 마디로 표현하면 "진짜 객체 앞에 서서 호출을 가로채는 대리인" 이다.일상적인 비유로 설명하면 이렇다.팬 → 매니저(프록시) → 연예인(진짜 객체)팬이 연예인한테 직접 연락하는 게 아니라 매니저를 통해서 연락한다.매니저는 중간에서 "이 스케줄은 안 돼", "이건 전달할게" 같은 처리를 할 수 있다.코드로 보면 이렇다.// 프록시 없이 직접 호출UserService service = new UserService();s..

MapStruct

📌 1. MapStruct란?MapStruct는 객체 간 매핑 코드를 자동으로 생성해주는 라이브러리이다.주로 다음과 같은 상황에서 사용된다.DTO ↔ Entity 변환API 요청/응답 객체 변환계층 간 데이터 전달👉 핵심:반복적인 매핑 코드를 자동화하여 생산성과 안정성을 높인다.❗ 2. 기존 방식의 문제점✔️ 수동 매핑UserDto dto = new UserDto();dto.setName(user.getName());dto.setAge(user.getAge());❌ 문제점코드 반복 많음실수 발생 가능유지보수 어려움✔️ ModelMapper (대안)리플렉션 기반 자동 매핑❌ 문제점성능 저하런타임 에러 발생 가능디버깅 어려움✅ 3. MapStruct의 핵심 특징✔️ 1. 컴파일 시 코드 생성실행 전에 매..