[JAVA] 스레드 안전한 공유 객체를 만드는 세 가지 축: 불변, 공개, confinement
·
Language/Java
1. 이 글에서 정리할 것이 글은 공유 객체를 어떻게 설계·공개해야 안전한가를 JMM(Java Memory Model)과 JIT 관점까지 엮어서 정리한 것이다. 핵심 축은 세 가지다.공유 가변 상태를 가능한 줄이고, 불변/결과적 불변으로 최대한 끌어올릴 것객체를 어떻게 공개하느냐(safe publication) 를 설계에 포함할 것아예 공유하지 않을 수 있을 때는 thread confinement로 escape 자체를 막을 것2. 공유 상태의 세 단계: 불변 / 결과적으로 불변 / 가변공유 상태는 다음 세 수준으로 나눠서 보는 게 이해가 쉽다.2.1 완전 불변(Immutable)조건은 세 가지 정도로 정리할 수 있다.생성 이후 상태가 절대 변하지 않는다 (setter 없음, 내부 가변 구조도 변경되지 않..
[배송 권역 시스템 1편] 배송 권역 시각화 시스템을 설계하며 고민한 것들
·
Fun
이 글에서 다루는 데이터와 영상에 등장하는 모든 주소·주문·고객 정보는 실제 서비스와 무관한 더미 데이터입니다. 문 앞까지 가져다주는 새벽배송·문전 서비스에 관심이 많다. 마켓컬리, 런드리고 같은 서비스를 사용하다 보면 “이 많은 주문이 밤사이에 어떻게 공간 상에서 배치되고 움직이는지 ”가 항상 궁금했다. 그래서 수도권을 기준으로, 실제 서비스에서 다루게 될 만한 스케일의 배송 데이터를 지도 위에서 시각화하고, 운영자가 바로 쓸 수 있는 형태로 정리하는 시스템을 개인 프로젝트로 구현해 보았다.이 글은 수도권 66개 권역, 1,187개 행정동, 일 3만 건 규모의 배송 데이터를 지도 위에서 실시간으로 다루는 시스템을 설계하고 구현하면서 내렸던 판단들을 정리한 기록이다. 무엇을 만들었는가보다 왜 그렇게 설..
[JAVA] 자바 synchronized 를 바이트코드로 까보며 이해하기
·
Language/Java
자바에서 synchronized는 모니터 락을 잡는다 정도로 보통 설명하지만, 실제로 JVM 바이트코드 레벨에서는 어떻게 구현되는지 궁금해졌다. 간단한 Account 예제를 작성해서 javap -c -v로 디스어셈블하고, synchronized 블록과 메서드가 어떤 바이트코드로 바뀌는지 직접 확인해 보았다.1. 예제 코드와 디스어셈블 결과이번에 사용한 예제 바이트코드는 대략 다음과 같다.public class Account minor version: 0 major version: 65 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #8 // Account super_class: #2 ..
[JAVA] 자바 동시성 프로그래밍: 기초부터 메모리 모델, 설계 전략까지 한 번에 정리하기
·
Language/Java
1. 왜 이 글을 쓰는가?단일 스레드 환경에서는 코드가 위에서 아래로 순차적으로 실행되기 때문에 상태 변화를 추적하기 쉽다. 하지만 멀티코어 환경에서 여러 스레드가 동시에 실행되면, CPU 캐시와 메인 메모리 사이의 데이터 불일치로 인해 예상치 못한 버그가 발생한다. 단순히 synchronized 를 쓰면 안전하다고 외우기보다, 자바 메모리 모델(JMM)이 어떻게 작동하고 JVM 내부에서 스레드와 모니터 락이 어떤 구조로 관리되는지를 정리하는 것이 목적이다. 이 글은 다음 질문들에 답하는 것을 목표로 한다.왜 스레드를 늘린다고 무조건 성능이 좋아지지 않는가? (암달의 법칙)자바 스레드의 실제 상태는 어떻게 변하며 인터럽트는 왜 중요한가?JMM의 Happens-Before 관계란 무엇인가?synchroni..
[JAVA] JVM Class Loading, Metaspace, 그리고 메서드 바이트코드까지 한 번에 이해하기
·
Language/Java
1. 왜 이 글을 쓰는가? 요즘 JVM의 클래스 로딩, 링킹, 그리고 ClassLoader.defineClass() 구현까지 따라가면서 공부하고 있다. 단순히 클래스 로딩 → 메서드 영역 → 실행 처럼 외워서는 금방 잊어버리게 되어, .class 파일의 바이트코드가 JVM 내부에서 어떤 객체/메모리 구조로 변해서 실제로 실행되는지를 한 번에 정리해 보려고 한다.이 글은 다음 질문에 답하는 것을 목표로 한다..class 파일 안의 메서드 코드는 어떻게 저장돼 있을까?ClassLoader.defineClass(byte[])가 바이트 배열을 받아서 내부에서 무슨 일을 할까?메서드의 바이트코드는 JVM 메모리 어디(Method Area / Metaspace)에 저장될까?인터프리터는 이 메타데이터를 어떻게 읽어서..
[Spring] DB 개인정보 암호화 시스템 구축기: AES‑256‑GCM + Blind Index
·
Spring Framework/Spring & Spring Boot
사이드 프로젝트에서 전화번호, 결제 정보 등 민감 데이터를 다루면서 DB 암호화의 필요성을 느꼈다. 단순히 암호화만 하면 되는 줄 알았는데, 검색은 어떻게 하지? 마이그레이션은? NestJS 서버와 같은 DB를 쓰는데 호환은? 하나씩 해결해 나간 과정을 정리한다. 들어가며개인 프로젝트를 진행하다 보면 전화번호, 빌링키 같은 민감한 데이터를 DB에 저장해야 하는 순간이 온다. 개인정보보호법이나 정보통신망법을 따져보면 양방향 암호화가 필수인 항목들이 꽤 많다. 공부 삼아 직접 암호화 모듈을 설계하고 구현해 봤는데, 생각보다 고려할 것이 많았다.특히 이런 문제들이 까다로웠다:검색 불가: AES-GCM은 랜덤 IV를 사용하므로 WHERE phone = ? 검색이 안 된다기존 데이터 전환: 이미 저장된 평문 데이..
[MySQL] 윈도우 함수 + VIEW 조합의 성능 함정
·
Computer Science/Database
1. 들어가며: "VIEW에 윈도우 함수가 있으면 인덱스가 안 먹힌다?"최근 동료가 특정 기능을 작업하던 중 조회 성능이 급격히 저하되는 문제를 겪었다. 원인은 윈도우 함수가 포함된 VIEW 테이블을 조회할 때 발생한 현상이었으며, 이 조합이 Condition Push-Down을 방해한다는 점을 분석하였다. 평소 뷰를 편리하게 사용해왔으나 이러한 구체적인 성능 제약 사항은 경험해 본 적이 없었다. 이에 해당 지식을 직접 확인하고 이해하기 위해 로컬 환경에서 Docker를 이용해 상황을 재현하고 실험을 진행하였다.2. 이론적 배경: 왜 옵티마이저는 조건을 무시하는가?MySQL 옵티마이저는 뷰를 쿼리할 때 두 가지 실행 전략을 선택한다.Merge: 뷰의 정의와 외부 쿼리를 합쳐 하나의 최적화된 쿼리로 실행한..
[Spring Batch] Spring Batch 6 도입 중 Chunk 기반 처리 버그 디버깅 및 6.0.1 패치 적용
·
Spring Framework/Spring Batch
1. 들어가며배치 서버 신규 이관 작업을 진행하면서 Spring Batch 6 버전을 도입하였다. Spring Boot 3.x, Java 21 환경을 기준으로 배치 서버를 구성하는 상황이었기 때문에, Spring Batch 역시 최신 메이저 버전을 사용하는 것이 자연스러운 선택이었다. 하지만 이관 과정에서 Chunk 기반 Step이 정상적으로 동작하지 않는 문제를 발견하게 되었고, 해당 문제를 디버깅한 결과 애플리케이션 구현이 아닌 프레임워크 버그임을 확인하게 되었다. 이 글은 Spring Batch 6 도입 과정에서 만난 버그를 어떻게 인지하고, 공식 이슈를 통해 확인한 뒤, 최종적으로 패치 버전을 적용하여 해결한 과정을 정리한 기록이다.2. 중점적으로 봐야 하는 내용Spring Batch 6에서 Ch..