프로그래밍/Java
💻 [Java] 동시성 제어 - 낙관적 락 vs 비관적 락
2025.08.22
개요실무에서 동시에 여러 요청이 같은 자원을 수정할 때, 데이터 정합성 문제가 발생합니다.대표적으로 쇼핑몰의 상품 재고 차감, 은행의 계좌 이체, 예약 시스템의 좌석 예매 등이 있습니다.단순히 synchronized 같은 자바 키워드만으로는 멀티 인스턴스 환경에서 제어가 불가능합니다. 따라서 DB 차원에서의 동시성 제어가 필요하며, JPA에서는 낙관적 락(Optimistic Lock) 과 비관적 락(Pessimistic Lock) 두 가지 전략을 제공합니다.이번 글에서는 두 방법을 모두 실습하고, 장단점과 실무 적용 시 고려할 점을 정리해보겠습니다.주요 기능 요약✔️ 낙관적 락@Version 필드를 이용해 버전 충돌 감지충돌 발생 시 OptimisticLockException 발생 → 재시도 로직 필요✔..
B2C 플랫폼 설계/트러블슈팅
🛠️ [트러블슈팅] 낙관적 락(Optimistic Lock) 적용기 — 재고 차감 동시성 문제 해결
2025.08.19
개요MSA 환경에서 상품 재고 차감은 흔히 발생하는 동시성 문제입니다.예를 들어, 같은 상품을 동시에 여러 사용자가 구매 요청하면, 재고가 음수로 떨어지거나 중복 차감되는 문제가 생길 수 있습니다.이번 글에서는 제가 실제 Spring Boot + JPA 기반 MSA 프로젝트에서 겪은 문제와, 이를 낙관적 락(Optimistic Lock) 으로 해결한 경험을 공유하려고 합니다.문제 상황상황: order-service에서 주문이 발생할 때, product-service가 재고를 차감하는 구조문제: 동시에 여러 주문 이벤트가 들어오면 update stock 쿼리가 race condition을 일으킴결과: 재고가 잘못 계산되거나 음수가 되는 현상 발생// 단순 재고 차감 로직public void decrease..
프로그래밍/Java
💻 [Java] Lombok vs record 실무 비교 — DTO/VO에 무엇을 쓸까?
2025.08.11
개요실무에서 DTO/VO를 만들 때 전통적으로 Lombok을 사용해 보일러플레이트를 줄였다. 하지만 Java 16+의 record가 등장하면서 불변 데이터 클래스를 언어 차원에서 간단히 정의할 수 있게 됐다. 이 글에서는 두 방식을 역할, 코드, 성능/안정성, 운영성 관점에서 비교했다.한 줄 요약record: 불변 DTO/VO, 의존성 없이 가장 간단하고 안전. (추천: API 응답/조회 전용)Lombok: 다양한 어노테이션 생태계, 가변/불변 모두 가능. (추천: 엔티티, 빌더, 레거시와의 호환)1. 코드 비교 (가장많이 쓰는 DTO 패턴)Lombok 방식import lombok.Data;@Datapublic class LombokUserDto { private final String name; ..
프로그래밍/Java
💻 [Java] Record 완전 정복 — 불변 데이터 클래스를 위한 언어 기능
2025.08.11
개요Java의 record는 "데이터를 담아 전달하는 불변 클래스"를 간단히 선언하기 위한 언어기능반복되는 보일러플레이트(필드, 생성자, getter, equals/hashCode/toString)를 자동 생성도메일 모델이 아닌 값 객체(Value Object)나 DTO에 특히 적합도입 히스토리: Java 14(프리뷰) -> Java 15(2차 프리뷰) -> Java 16(정식) 관련 확장: Recode Patterns(JEP 440)은 Java 21에서 정식으로 포함되어 레코드 분해(deconstruction)와 패턴 매칭에 활용할 수 있음. 1. 핵심 요약목적: 데이터 보유용 불변 클래스(값 객체)를 간결하게 정의자동 생성: private final 필드, 접근자(컴포넌트명과 동일), equals, ..
컴퓨터 과학/데이터베이스
💾 [데이터베이스] DB 인덱스의 모든 것
2025.08.07
개요데이터베이스에서 인덱스(Index)는 책의 목차처럼 특정 데이터를 바르게 조회하기 위한 자료 구조입니다.대량의 데이터 중 원하는 데이터를 바르게 찾기 위해 사용되며, 성능 최적화에 있어서 핵심적인 요소입니다.하지만 무조건 사용하는 게 아니라, 언제, 어떻게 사용하는지를 정확히 이해하고 적용하는 것이 중요합니다.인덱스가 필요한 이유SELECT * FROM users WHERE email = 'ming@example.com';만약 email에 인덱스가 없다면?데이터베이스는 전체 테이블을 처음부터 끝까지 훑는 Full Table Scan을 수행인덱스가 있다면?해당 컬럼을 탐색하여 바로 해당 레코드 위치로 이동 (Random Access)결과적으로 조회 속도는 수십 배에서 수천 배까지 차이 날 수 있습니다...