본문 바로가기

Q&A5

스레드 로컬 Thread Local 무엇이고, 언제 쓸까? 동시성 문제를 '공유하지 않는' 방법으로 해결하기 (Spring Security, Log Tracer 예제) 0. 이 글에 대해서멀티스레드 환경에서의 동시성 문제와 전통적 동기화 기법의 한계를 간단히 짚은 뒤,“스레드 간 공유하지 않는다”는 아이디어로 문제를 해결하는 ThreadLocal의 개념과 원리를 살펴봅니다.자바의 ThreadLocalMap 구조와 스레드 풀 재사용 시 라이프사이클 관리(메모리 누수 방지)도 다룹니다.Spring Security와 계층형 로깅(Log Tracer) 사례를 통해 ThreadLocal의 실제 활용법을 예시로 보여줍니다.ThreadLocal 사용 시 주의사항과 향후 대안까지 간략히 살펴보며 마무리합니다.1. ThreadLocal, 알아보자Threadlocal이란?한마디로 ThreadLocal은 “전역 변수처럼 보이지만, 실제로는 스레드마다 따로따로 값을 가지는 특별한 저장소”이.. 2025. 4. 18.
충돌 없는 완벽한 해싱이 존재한다고 ? (퍼펙트 해싱 개념 및 사례, 최적화 방법에 대해서) 이 글의 탄생 배경, 이 글에 대해서코딩 스터디 중 해싱 챕터에서 시간 복잡도를 주제로 이야기할 때였다. 해싱하면 연상되는 이미지는 당연히 "빠르다"였고 나는 당연스럽게 O(1)이지! 라고 생각하며 대화를 이어나갔는데, 한 멤버가 질문했다."어... 해싱도 최악의 경우는 O(n) 아니에요?"어라, 순간 멈칫했다. 사실 해싱에서 최악의 경우는 O(n)이라는 걸 깜빡하고 있었다! 자바에서 해싱을 사용할 때는 충돌 문제를 자동으로 처리해주고, 또 key-value 스토어로서 레디스와 같은 저장소를 사용할 때, 단순히 "빠르다"는 이미지에만 노출되어 있다 보니 당연히 해싱은 O(1)이라고 생각했던 것이다. 문득 기억을 환기시키며 깨달았다. 앗,,, 해싱은 충돌이 없다면 O(1)이지만, 충돌이 발생하면 O(n)이.. 2024. 11. 2.
로깅 추적을 위한 AOP 적용과 이후 성능 차이 그리고 why ?! 개요 사내에서 만든 서비스에 메서드 전후로 AOP를 걸고 쓰레드별로 추적하는 기능을 덧붙여서 사용해볼 기회가 있었다. 성능이 어떻게 달라질 것인지 궁금했다. 이 글은 AOP 적용 이전과 이후 성능 차이를 기록하고 이를 분석해본 글이다. 그리고 이 결과에 대한 피드백으로 들어온 어떤 질문에 대해 고민해 본 내용을 소개한다. 사용한 툴 장비: macbook pro 13` 2020 (m1), 16GB, Ventura 13.5 성능 측정: JMeter, Spring Actuator(Prometheus, Grafana) 개발: Mvc: Springboot 2.6.7, mysql 8.0 테스트의 특성상 많은 더미 데이터를 사용하지는 않았다. 목차 Log Trace AOP 적용 이전 1.1 단건 조회 1.2 검색 조.. 2023. 12. 14.
컴퓨터는 실제로 배열의 데이터에 index로 접근할까? 컴퓨터는 실제로 배열의 데이터에 index로 접근할까? 배열과 인덱스의 기본 이해 배열은 연속적인 메모리 공간에 데이터를 저장하는 구조이다. 각 요소는 인덱스를 통해 접근된다. 메모리 주소와 인덱스의 관계 그러나, 인덱스는 실제 메모리 주소를 직접 나타내지는 않는다. 인덱스는 기본적으로 메모리 주소에 대한 '오프셋'을 의미한다. 실제 메모리 접근 방식 실제 메모리 주소 계산을 예로 들어보자. 배열의 시작 주소가 1000이고, 각 요소가 4바이트를 차지한다면, 인덱스 3의 요소는 어떻게 계산될까? 계산식은 '1000 + (3 * 4)'가 되어, 이 요소의 메모리 주소는 1012가 된다. 이처럼 배열은 실제로는 '기준 주소 + (인덱스 * 요소 크기)'로 계산된 값.. 2023. 11. 24.
왜 int, String 배열은 스트림(Stream)으로 쉽게 변환되는데 char 배열은 안 되는 것일까?! (자바 캐릭터 배열 스트림으로 변환하기) Java.util 패키지의 Arrays 클래스를 이용하면 간단히 Stream으로 변경할 수 있다. 위에서와 int 외에도 다양한 숫자형 strem 변환을 지원한다. public class Example { public static void main(String[] args) { toStream(new int[]{1, 2, 3, 4, 5}); } private static void toStream(int[] array) { IntStream stream = Arrays.stream(array); } } String의 경우 제네릭 T 타입 배열로 인자값이 들어가는 케이스로 변환된다. private static void toStream(String[] array){ Stream stream = Arrays.s.. 2023. 6. 24.