본문 바로가기

분류 전체보기193

[Spring DB] Connection Pool 도입애플리케이션이 데이터베이스에 쿼리를 보내려면 반드시 DB 연결이 필요합니다.이 연결은 생각보다 많은 단계와 시간이 소요됩니다. 예를 들어, 사용자가 웹에서 버튼 하나만 눌러도, 아래와 같은 절차를 거쳐야 DB에 접근할 수 있습니다.애플리케이션 로직은 DB 드라이버에게 커넥션을 요청합니다.DB 드라이버는 TCP/IP 네트워크 연결을 시도합니다.TCP 연결이 완료되면, ID, PW, 부가 정보를 DB에 전달합니다.DB는 전달받은 정보로 내부 인증 및 세션 생성을 합니다.커넥션이 생성이 완료되었음을 애플리케이션에 응답합니다.드라이버는 커넥션 객체를 만들어 반환합니다.이 모든 작업은 매우 비싼 비용을 수반합니다. 특히 네트워크 지연, DB 세션 생성 등의 부하는 실시간 사용자 요청이 몰리는 환경에서 병목이.. 2025. 4. 25.
B-Tree 인덱스,구조 및 성능 고려사항 B-TreeB-Tree는 인덱싱 알고리즘 중 가장 보편적으로 사용되고, 가장 먼저 도입된 알고리즘이면서 여전히 가장 범용적인 목적으로 사용되는 인덱스 알고리즘 입니다. 그리고 B-Tree의 B는 Binary(이진)이 아닌, Balanced를 의미합니다. B-Tree는 칼럼의 원래 값을 변형시키지 않고 인덱스 구조체 내에서는 항상 정렬된 상태로 유지합니다.특별한 검색 조건이 없는 경우엔 대부분 B-Tree 또는 B+Tree를 사용합니다. B-Tree 인덱스 구조인덱스는 트리 구조로 되어 있으며, 루트 노드 → 브랜치 노드 → 리프 노드 순으로 구성됩니다. 리프 노드에는 실제 데이터를 가리키는 프라이머리 키 주소를 가지고 있습니다. 인덱스 자체는 데이터 테이블의 키 컬럼만을 포함하고, 실제 데이터는 별도로 .. 2025. 4. 25.
[운영체제] 캐시 일관성과 MESI 프로토콜 캐시 일관성이 필요한 이유멀티코어 시스템에서는 각 CPU 코어마다 자체 캐시(L1, L2 등)을 갖고 있습니다.이 캐시들은 공유 메모리(RAM)의 일부 데이터를 복사해서 로컬하게 저장하고 사용합니다. 그런데 여러 CPU가 동일한 메모리 주소를 읽고 쓰게 되면 문제가 발생합니다.int x = 0; // 공유 변수// (CPU1) x = 1; // (CPU2) printf("%d\n",x); // 0이 출력될 수 있습니다. 위 코드처럼 CPU1이 x = 1로 값을 바꿨지만, CPU2는 여전히 이전 값 0을 자신의 캐시에서 읽어올 수 있습니다. 즉, CPU 간 캐시가 일관되지 않은 상태가 되는 거죠. 이러한 문제를 해결하기 위해 캐시 일관성 프로토콜이 필요합니다. MESI 프로토콜현대 CPU는 대부분 MES.. 2025. 4. 25.
[운영체제] 락 TAS vs CAS 병행성 문제와 락의 필요성병행 프로그래밍에서는 여러 명령어를 동시에 실행하고 싶지만, 단일 프로세서의 인터럽트나 멀티 스레드 환경에서도 자원 공유로 인해 의도한 대로 병행 실행이 어려운 경우가 발생합니다. 이를 해결하기 위해서 락을 사용해 임계 영역을 보호하고, 해당 영역 내에서는 명령어들이 원자적으로 실행되도록 합니다.즉, 개ㅁ발자는 동시 접근이 발생할 수 있는 코드 영역을 락을 감싸서, 하나의 스레드만 해당 영역을 실행할 수 있게 해야 합니다. 임계 영역 예제 코드간단한 임계 영역의 예제를 통해서 락을 적용하는 과정을 확인해보겠습니다.임계 영역의 코드는 다음과 같습니다.(코드는 C++을 기준으로 작성합니다.)balance = balance + 1; 락을 사용하기 위해서 락으로 감싼 임계 영역의 코드는.. 2025. 4. 25.
DP DP의 유래동적 계획법(dynamic programming)이라는 말은 최적화 문제을 연구하는 수학 이론에서 왔고, 전산학 전반에서 일반적으로 사용하는 동적, 혹은 프로그래밍이란 단어와는 아무련 관련이 없습니다. 즉, dynamic programming은 동적 프로그래밍이 아닌, 동적 계획법입니다. 중복되는 부분 문제동적 계획법은 큰 의미에서 분할 정복과 같은 접근 방식을 의미합니다.이 방식도 처음 주어진 문제들을 더 작은 문제들로 나눈 뒤 조각의 답을 계산하고, 이 답들로부터 원래 문제에 대한 답을 계산해 내기 때문입니다. 동적 계획법과 분할 정복의 차이가 발생하는 부분은 문제를 나누는 방식입니다.동적 계획법에서는 어떤 부분 문제는 2개 이상의 문제를 푸는 데 사용될 수 있기 때문에, 이 문제의 답을 .. 2025. 4. 25.
[Toss Tech] Java Native Memory Leak 원인을 찾아서 이번 글은 Toss Slash 22에서 발표한 "Java Natvie Memory Leak 원인 찾아서"를 정리했습니다. 도입 토스 페이먼츠에서는 시스템에서 오류 가능성이 있어 보이는 항목들을 모니터링하고 있으며 Slack으로 메시지 연동을 하고 있습니다.OOM Killer가 발동하면 system log에 로그가 남게 되고 이를 Slack으로 연동해둔 방식입니다. OOM Killer서버 내의 특정 프로세스가 과도하게 메모리를 사용하여, 시스템의 여유 메모리가 없는 상황을 가정합니다.이때, OS에서 무언가의 연산을 할 때, 메모리가 필요할 수 있습니다. OS에서 더 이상 할당받을 메모리가 없다면, OS는 불안해질 수 있습니다. 이럴 경우 Linux OS에서는 시스템에서 과도하게 메모리를 사용하고 있는 프.. 2025. 4. 25.
[Spring Docs] Hibernate 이번글은 공식 문서에서 소개하는 Hibernate에 대해 정리했습니다. We start with a coverage of Hibernate 5 in a Spring environment, using it to demonstrate the approach that Spring takes towards integrating OR mappers. This section covers many issues in detail and shows different variations of DAO implementations and transaction demarcation. Most of these patterns can be directly translated to all other supported ORM tool.. 2025. 4. 25.
Redis 다중 명령 원자성 보장 방법 Redis는 싱글 스레드 기반의 구조 덕분에 단일 명령어는 원자성을 보장합니다. 하지만 여러 개의 명령어를 연속으로 실행할 경우, 명령 사이에 다른 클라이언트의 명령이 끼어들 수 있어 경합이 발생합니다. 이 문제를 방지하고자 Redis는 다음 세 가지 방법으로 다중 명령에 대한 원자성을 제공합니다.Redis Transaction낙관적 락(WATCH)Lua Script예를 들어, 다음과 같은 코드가 있다고 가정합니다.Long stock = redisTemplate.opsForValue().get("stock:1");if(stock > 0) { redisTemplate.opsForValue().decrement("stock:1");} 이 코드는 2개의 명령(GET, DECR)로 구성되어 있습니다. 만약.. 2025. 4. 23.
Index 인덱스란데이터베이스에서 데이터를 조회하려면, 기본적으로 테이블 전체를 훑는 전체 검색(Full Scan)을 수행해야 합니다.이는 시간이 오래 걸릴 수 있습니다. 그래서 등장한 것이 바로 인덱스입니다. 인덱스는 값(Key)과 데이터 주소(Value)의 쌍 (Key-Value Pair)로 구성되어 있으며, 원하는 데이터를 더 빠르게 찾을 수 있도록 돕는 구조입니다. 즉, 인덱스는 정렬된 찾아보기로 생각하면 됩니다. 인덱스 핵심 구조DB 인덱스는 보통 항상 정렬된 상태를 유지합니다.이를 위해 SortedList와 같은 자료구조가 활용되며, 이는 값을 삽입할 때마다 정렬을 유지하는 구조입니다.이 구조 덕분에 SELECT는 빠르지만, INSERT/UPDATE/DELETE는 느릴 수 있습니다. 인덱스의 장점과 단점.. 2025. 4. 23.