본문 바로가기

프로젝트 기록

Thread Local이란?

  • 자바의 class 중 하나.
  • 오직 한 쓰레드에 의해서 읽고 쓰여질 수 있는 변수
  • 두개 이상의 쓰레드가 같은 코드를 실행하고 이 코드가 하나의 ThreadLocal 변수를 참조 하더라도 서로의 ThreadLocal 변수를 볼 수 없음
  • 👉멀티 쓰레드 환경에서 각 스레드마다 독립적인 변수를 가지고 접근할 수 있음.

 

 

사용 방법

  1. Context 클래스에서 ThreadLocal 객체를 생성한다.
  2. ThreadLocal.set() 메서드를 이용해서 현재 쓰레드의 로컬 변수에 값을 저장한다.
  3. ThreadLocal.get() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 읽어온다.
  4. ThreadLocal.remove() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 삭제한다.

자세한 내용 : https://javacan.tistory.com/entry/ThreadLocalUsage 참고

 

 

활용 방법

 

한 쓰레드에서 실행되는 코드가 동일한 객체를 사용할 수 있도록 해주기 때문에, 관련된 코드에서 메소드 파라미터를 사용하지 않고 객체를 각자가 가져다 쓸 때 사용 가능

  • 사용자 인증 정보 Spring Security에서 사용자마다 다른 인증 정보를 사용할 때 & Session 정보
  • 쓰레드에 안전해야 하는 데이터를 보관 할 때
  • Spring Security 사용 시, SecurityContextHolder.getContext().getAuthentication() 을 통해 메소드의 파라미터나 클래스의 변수 없이도 현재 인증된 유저에 대한 정보를 가져올 수 있음.
    • SecurityContextHolder가 기본적으로 ThreadLocal 전략을 사용하고 있기에 가능.

 

예제

// UserAccount를 ThreadLocal에 저장해 사용하는 Custom한 UserContext
public class UserContext {
 
        // UserAccount를 담는 ThreadLocal 정의
    private static ThreadLocal<UserAccount> THREAD_LOCAL_ACCOUNT = new ThreadLocal<UserAccount>();
 
    public static UserAccount getUserAccount() {
        return THREAD_LOCAL_ACCOUNT.get();
    }
 
        // 인증된 유저를 ThreadLocal에 담기.
    public static void setUserAccount(UserAccount userAccount) {
        THREAD_LOCAL_ACCOUNT.set(userAccount);;
    }
}

@PostMapping("/info/delete")
    public ModelAndView registrationInfo(ModelAndView mv) {
        //파라미터 없이도 현재 UserContext에 저장된 인증 처리된 UserAccount를 가져와 사용 가능
        UserAccount user = UserContext.getUserAccount();
        registrationClientInfoService.delete(user.getUsername);
 
        mv.setViewName("client/info");
        return mv;
    }

 

주의할 점

  • Thread pool 환경에서 ThreadLocal을 사용하므로, 데이터 사용이 끝나면 반드시 .remove()를 통해 데이터를 삭젷줘야 함
  • ThreadLocal은 static으로 정의해야 함. 그렇지 않으면, 하나의 Thread 안에서 값이 다르게 나옴.

 


참고 : https://nathanh.tistory.com/131

 

ThreadLocal 이란?

Intro Spring Security를 사용하다 보면, 인증이 된 유저는 UsetDetailsService 에서 리턴을 한 후 UserDetails 타입의 객체가 바로 Principal 로 변환되어 사용하게 된다. 즉 인증이 된 유저는 Principal이 되고..

nathanh.tistory.com

 

'프로젝트 기록' 카테고리의 다른 글

Entity type으로 Wrapper class를 사용하는 이유  (0) 2022.02.23
정적 팩토리 메서드  (0) 2022.02.23
기타 에러 해결 기록들  (0) 2022.02.23
JPA N+1 문제 해결  (0) 2022.02.23
REST API 가이드  (0) 2022.02.23