Backend 44

JPA의 낙관적 락과 비관적 락

JPA의 낙관적 락과 비관적 락 JPA에서 @Transactional(isolation = Isolation.DEFAULT) 로 설정하면 DBMS에 설정한 격리 수준을 따른다. MySQL은 REPEATABLE READ가 기본 설정이다. 그리고 JPA는 영속성 컨텍스트와 1차 캐시를 통해 REPEATABLE READ 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다. 그런데 일부 로직에서 더 높은 격리 수준이 필요할 때가 있다. 따라서 이때 JPA가 제공하는 낙관적 락과 비관적 락 옵션을 사용하면 된다. 낙관적 락: 대부분의 트랜잭션이 충돌이 발생하지 않을 것이라고 낙관적으로 가정하는 방법이다. 따라서 데이터베이스가 제공하는 락 기능을 사용하지 않고, JPA가 제공하는 버전 관리 기능을 사용한..

Backend/JPA 2024.02.07

준영속 상태에서의 지연 로딩 문제와 그 해결법인 OSIV

트랜잭션 범위의 영속성 컨텍스트 전략 스프링 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용한다. 이름 그대로 트랜잭션의 범위와 영속성 컨텍스트의 생존 범위가 같다는 뜻이다. 즉, 트랜잭션을 시작할 때 영속성 컨텍스트를 생성하고 트랜잭션이 끝날 때 영속성 컨텍스트를 종료한다. 그리고 같은 트랜잭션 안에서는 항상 같은 영속성 컨텍스트에 접근한다. 스프링 프레임워크를 사용하면 보통 비즈니스 로직을 시작하는 서비스 계층에서 @Transactional 어노테이션을 선언해서 트랜잭션을 시작한다. @Transactional 어노테이션이 있으면 해당 클래스의 메소드 호출시 메소드 실행 직전에 스프링의 트랜잭션 AOP가 먼저 동작한다. 트랜잭션 AOP는 대상 메소드를 호출하기 직전에 트랜잭션을 시작한다..

Backend/JPA 2024.02.04

엔티티 조회 성능 최적화

xToOne 관계의 엔티티 조회 성능 최적화 Order를 조회할 때 연관된 Member와 Delivery를 함께 조회한다고 가정하자. 이때 Order와 Member는 다대일 관계이고, Order와 Delivery는 일대일 관계이다. 지연 로딩 사용으로 인한 N+1 문제 지연 로딩으로 설정해두면, Order를 조회할 때 Member와 Delivery 테이블에는 조회 쿼리가 나가지 않고, 연관된 엔티티인 Member와 Delivery는 프록시 객체가 된다. 그리고 member.getUsername()과 같이 엔티티에 접근할 때, Member 테이블에 조회 쿼리가 나가게 되고, 해당 프록시 객체가 초기화된다. 따라서 만약 주문 정보(Order)를 조회하면서 회원 정보(Member)와 배송 정보(Delivery..

Backend/JPA 2024.02.02

Redis에 토큰 저장하기

Redis Redis는 디스크가 아닌 메모리에 데이터를 저장하는 인메모리 방식의 데이터베이스이다. * 메모리(RAM, Random Access Memory): 빠른 액세스를 위해 데이터를 임시로 저장하는 저장소이다. 메모리에 올라간 데이터는 컴퓨터 전원이 꺼지면 휘발된다. * 디스크(HDD, SSD): 데이터를 영구적으로 저장하는 저장소이다. 디스크에 저장되어 있는 데이터는 CPU가 처리하는 속도가 메모리보다 느리다. 그러나 저장할 수 있는 용량이 메모리보다 훨씬 크고, 전원이 꺼지더라도 저장된 데이터가 휘발되지 않는다. * 인메모리 데이터베이스: 디스크가 아닌 메모리에 데이터를 저장하는 데이터베이스이다. IMDB(In-Memory Database) 또는 MMDB(Main Memory DBMS)라고 한다..

Backend/Redis 2024.01.29

OAuth를 통한 인증

OAuth의 정의 OAuth는 사용자가 특정 서비스를 사용할 때 아이디, 패스워드 등의 사용자 정보를 입력하며 회원가입을 할 필요 없이, 신뢰할 수 있는 외부 어플리케이션(ex, 카카오, 네이버, 구글)에 등록된 사용자 정보를 통해 외부 어플리케이션에서 대신 인증을 처리해주는 방식이다. 만약 OAuth를 사용하지 않으면, 사용자가 매 사이트마다 회원가입을 진행하며 사용자 정보를 노출해야 한다. 그러나 OAuth를 사용하면 사용자 정보를 특정 외부 어플리케이션에서만 관리하고 인증을 처리해준다. 따라서 사용자가 사용자 정보를 다른 서비스에 노출하지 않아도 된다. 동작 원리 용어는 다음과 같다. Resource Owner: 인증을 수행하는 주체(Resource Sercer의 계정을 소유하고 있는 사용자) Cl..

SecurityFilterChain에 필터를 등록할 때 주의할 점(WAS의 FilterChain과 Spring Security의 SecurityFilterChain의 차이)

SecurityFilterChain은 여러 개 존재할 수 있다. 그리고 경로에 따라 다른 SecurityFilterChain을 거치도록 할 수 있다. 예를 들어 위의 그림처럼 /api/** 경로에 대한 SecurityFilterChain과 나머지 경로(/**) 에 대한 SecurityFilterChain을 다르게 설정하면, 각 경로에 따라 서로 다른 필터 체인을 통과하게 된다. WAS의 FilterChain에 필터를 등록하는 방법 필터를 스프링 빈으로 등록하는 방법은 여러가지가 있는데 대표적으로 다음 두 방법이 있다. Filter 인터페이스를 구현하고, @Component를 붙여서 필터를 등록하는 방법 @Configuration을 붙인 설정 정보 클래스를 만들고, 내부에 FilterRegistration..

permitAll 설정의 의미

우리는 다음과 같이 permitAll을 통해 인증 정보 없이 누구나 접근 가능한 리소스를 지정할 수 있다. @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(authHttp -> authHttp.requestMatchers(POST, "/join", "/login").permitAll()) ... return http.build(); } 그러나 커스텀 필터와 함께 permitAll을 사용할 때는 주의할 점이 있다. permitAll() 설정 유무에 대한 차이를 명확히 알아야 하는데, permitAll에 대해 공식 문서에는 다음과 같이 나와있다. ..

Spring Security의 예외 처리 방식

ExceptionTranslationFilter Spring Security는 ExceptionTranslationFilter를 통해 인증 예외(AuthenticationException)와 인가 예외(AccessDeniedException)를 적절하게 처리하고 원하는 형태의 HTTP 응답을 줄 수 있다. ExceptionTranslationFilter는 다음과 같이 SecurityFilterChain에 속해 있는 필터 중 하나로, 실행 흐름은 다음과 같다. ExceptionTranslationFilter는 FilterChain.doFilter(request, response)를 통해 이어진 필터들을 호출한다. 만약 AuthenticationException이 발생한 경우, 다음을 실행한다. Securi..

Spring Security의 인가(Authorization)

Spring Security의 인가 인가는 인증된 사용자가 특정 리소스에 접근이 가능한지를 결정하는 과정이다. Spring Security에서의 인가는 인증 정보를 담은 Authentication의 authorities(역할)을 통해 접근이 가능한지를 결정한다. Spring Security는 인증을 위한 필터로 AuthorizationFilter를 제공한다. AuthorizationFilter를 사용하려면, 다음과 같이 authorizeHttpRequests() 메소드를 통해 등록하면 된다. @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(au..

Spring Security의 인증(Authentication)

Spring Security의 인증 Spring Security는 기본적으로 인증 절차를 거친 후에 인가 절차를 진행한다. 인증은 사용자의 신원을 증명하는 과정으로, 인증된 Authentication을 만드는 과정이다. Authentication은 pricipal, credentials, authorities로 구성되어 있으며, 인증된 Authentication은 SecurityContextHolder에 저장된다. 인증 흐름 사용자가 로그인 정보와 함께 인증 요청을 한다(Http Request). AuthenticationFilter가 요청을 가로채고, 가로챈 정보를 통해 인증용 객체인 UsernamePasswordAuthenticationToken을 생성한다. 생성된 UsernamePasswordAut..