Spring / / 2024. 6. 9. 16:56

ThreadLocal

ThreadLocal 이란 멀티쓰레드 환경에서 각 쓰레드가 독립저긍로 값을 저장하고 접근할 수 있도록 하는 JAVA 클래스입니다. ThreadLocal을 사용하면 여러 쓰레드가 동시에 실행되는 환경(멀티쓰레드)에서도 안전하게 변수에 접근할 수 있습니다.

ThreadLocal 특징

  1. 쓰레드별 독립 데이터 저장: ThreadLocal을 사용하면 각 쓰레드는 자신의 로컬 변수를 가지고 있기 때문에 다른 쓰레드와 데이터를 공유하지 않습니다.
  2. 쓰레드 안전성: 여러 쓰레드가 동일한 변수를 사용할 때 발생할 수 있는 경쟁 조건을 방지합니다.
  3. 라이프사이클: ThreadLocal에 저장된 데이터는 해당 쓰레드가 종료될 때까지 유지되며, 쓰레드가 종료되면 자동으로 정리됩니다.
public class ThreadLocalExample {
    // ThreadLocal 변수를 선언합니다.
    private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);

    public static void main(String[] args) {
        // 두 개의 쓰레드를 생성합니다.
        Thread thread1 = new Thread(new Task(), "Thread-1");
        Thread thread2 = new Thread(new Task(), "Thread-2");

        // 쓰레드를 시작합니다.
        thread1.start();
        thread2.start();
    }

    // 작업을 수행하는 Task 클래스
    public static class Task implements Runnable {
        @Override
        public void run() {
            // 현재 쓰레드 이름을 출력합니다.
            System.out.println(Thread.currentThread().getName() + " initial value: " + threadLocal.get());

            // ThreadLocal 변수의 값을 증가시킵니다.
            for (int i = 0; i < 5; i++) {
                threadLocal.set(threadLocal.get() + 1);
                System.out.println(Thread.currentThread().getName() + " updated value: " + threadLocal.get());
            }
        }
    }
}

코드1 결과

ThreadLocal 사용처

이러한 ThreadLocal은 과연 어디서 가장 많이 사용될까요?

 

저는 이번에 진행한 사이드 프로젝트에서 SpringSecurity 부분을 맡아서 했는데요, 이떄 아래 코드와 같이 SpringContextHolder에 담아놓은 로그인 유저 정보를 스프링 컨테이너 내에서 사용할 때 주로 사용됩니다.

UsernamePasswordAuthenticationToken(customOAuth2User, null, customOAuth2User.authorities).also {
    SecurityContextHolder.getContext().authentication = it
}
@GetMapping("/user/{userId}")
    fun getUserInfo(@AuthenticationPrincipal userDetails: CustomOAuth2User, @PathVariable userId: String): ResponseEntity<*> {
        return memberService.getUserInfo(userDetails)
    }

위의 두 코드를 보시면 SecurityContextHolder의 authentication에제가 생성한 CustomOAuth2User를 담아두고, 컨트롤러 부분에서 @AuthenticationPrincipal 어노테이션을 활용하여 사용중인 것을 확인할 수 있습니다.

 

이렇듯, 멀티 쓰레드 환경에서 스프링 컨테이너 환경처럼 싱글톤으로 구성된 클래스가 존재할 때, 서로 다른 쓰레드에서 같은 정보를 사용하면 안되는 경우가 존재합니다.

 

위의 경우 userDetails 라는 정보는 로그인한 유저가 ThreadA냐 ThreadB냐에 따라 달라질 수 있기 때문에 Thread 고유의 변수를 보장해주는 ThreadLocal에서 값을 가져와야 안정적으로 정보를 유지할 수 있습니다!

 

SpringSecurity 외에도 저희가 자주 사용하는 HttpServletRequest 등에서도 RequestContextHolder에서 요청 정보를 ThreadLocal을 이용하여 관리합니다!


References

https://catsbi.oopy.io/3ddf4078-55f0-4fde-9d51-907613a44c0d

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유