전체 글 149

Spring Data JPA save() vs saveAll(), 진짜 차이는 SQL 이 아니라 트랜잭션 경계였다

부제 : async-profiler Flame Graph 로 직접 파헤쳐 본 다건 저장 성능 차이 이 글에서 얻어갈 것들saveAll() 이 빠른 진짜 이유를 설명할 수 있게 된다.("INSERT 한 방"이라는 오해를 정확히 깨뜨릴 수 있다)SimpleJpaRepository.saveAll() 내부 코드를 보고, saveAll도 결국 save()를 반복 호출함을 이해한다.트랜잭션 경계가 다건 저장 성능에 미치는 영향을 async-profiler Flame Graph 실측 데이터로 확인한다.서비스 계층 @Transactional의 의미를 성능 관점에서 이해한다.saveAll()과 JDBC Batch insert 를 구분할 수 있게된다.1. 시작 - 흔한 오해처음 saveAll()을 쓸 때 나도 당연하게..

Spring 2026.05.25

질문이 답변을 수정해서는 안 된다 - CQS, 읽히는 코드를 만드는 원칙

코드는 동작하는 것만 봤는데, 이번에 왜 이렇게 설계했는지 보려고 했다. 이 글에서 얻어갈 것들동작은 되는데 찜찜한 코드의 정체명령과 쿼리를 왜 나눠야 하는지에 대한 실무적인 이유메서드 시그니처만 보고 부수효과를 예측하는 방법CQS 를 단순 개념이 아닌 설계 기준으로 사용하는 방법값 객체와 결합해 부수효과 범위를 좁히는 패턴CQS가 오히려 독이 되는 상황과 그 판단 기준개발을 하다 보면 이런 코드를 만나게 된다.boolean result = schedule.includes(day); 겉으로 보면 "값을 반환하는 함수"다.그런데 실행해보면 결과가 달라진다.같은 파라미터인데, 두 번째 호출은 다른 값을 돌려준다. 이런 코드는 처음엔 잘 동작한다.하지만 시간이 지날수록 점점 이해하기 어려워진다. 이 글에서 그..

객체지향 2026.04.21

결제는 중요할까? 주문이 중요할까 - 결제 코드를 읽다가 깨달은 설계의 기준

코드는 동작하는 것만 봤는데, 이번에 왜 이렇게 설계했는지 보려고 했다. 이 글에서 얻어갈 것들결제 vs 주문 - 무엇이 본질인지 판단하는 기준"돈이 빠지는 순간" 을 기준으로 시스템을 나누는 방법요구사항을 기능이 아니라 흐름으로 읽는 시각도메인 객체로 로직을 캡슐화하는 패턴 - PaymentDiscount 설계상태, 이력, 실패를 설계하는 방식핵심 요악결제는 복잡하지만 본질이 아니다. 주문이 본질이고, 결제는 그 주문을 완성시키는 수단이다. 그리고 결제 시스템에서 반드시 새겨야 할 한 가지돈이 빠지기 전과 후는 완전히 다른 세계다. 이 경계를 모르면 시스템은 반드시 깨진다.1. 결제를 공부하면서 처음 든 질문처음 결제 코드를 봤을 때는 API 3개, PG 연동, 할인 계산 정도로 읽혔다. 그냥 외부 A..

카테고리 없음 2026.03.30

좋은 객체는 부끄럼을 탄다

디미터 법칙과 Tell, Don't Ask 로 만드는 자율적인 객체 설계 이 글에서 얻어갈 것들Anemic Domain Model (빈혈 도메인 모델이 무엇인지, 그리고 내 코드가 이미 그 상태인지 알게 된다.디미터 법칙과 Tell, Don't Ask를 추상적 원인이 아니라 코드 한 줄 단위에서 적용할 수 있게 된다.Feature Envy, 열차 충돌 같은 코드 냄새를 감지하는 기준과 코드 패턴을 갖게 된다Spring + JPA 환경에서 이 원칙들이 @Transactional, Dirty Checking과 어떻게 연결되는지 이해하게 된다규칙을 언제 지키고 언제 의도적으로 어겨야 하는지 — 이유를 설명할 수 있는 판단 기준을 얻는다프폴로그 - 이미 짜고 있을지도 모른다Spring 기반 프로젝트에서 아래 패..

객체지향 2026.03.17

테스트가 무거운 건 의지 문제가 아니라 설계 문제다

레이어트 아키텍처의 함정과 도메인 중심 설계로의 탈출 이 글에서 얻어갈 것들테스트가 무거운 이유가 의지 문제가 아니라 설계 문제라는 것레이어드 아키텍처가 Fat Service 와 Anemic Domain Model을 만들기 쉬운 구조적 이유이 문제가 코드 수준을 넘어 팀 협업과 생산성에 어떤 영향을 주는지의존성 역전(DIP)을 통해 외부 기술을 분리하는 실전 흐름Mock과 Fack 테스트의 차이와 언제 무엇을 써야 하는지Spring Context 없이도 가능한 순수 Java 단위 테스트 구조이 내용이 클린 아키텍처, 헥사고날 아키텍처와와 어떻게 연결되는지 큰 그림1. 레이어드 아키텍처는 왜 기본이 되었을까?Sprig 기반 프로젝트를 시작하면 대부분 자연스럽게 다음 구조를 사용한다.Controller ..

객체지향 2026.03.16

HTTP 메서드와 멱등성 - REST API 설계에서 중요한 이유

이 글에서 얻어갈 것들HTTP 메서드(GET, POST, PUT, PATCH, DELETE) 의 역할과 차이를 명확히 이해할 수 있다.멱등성(Idempotency)이 무엇인지, 왜 실무에서 중요한지 체감할 수 있다.결제 시스템 등에서 Idempotency Key 전략이 왜 필요한지 이해할 수 있다.REST API 설계에서 흔히 발생하는 실수 TOP 7 을 점검할 수 있다.Spring 기반 Java 백엔드에서 HTTP 메서드를 어떻게 적용하는지 코드로 확인할 수 있다.왜 HTTP 메서드를 제대로 알아야 할까?REST API를 설계할 때 단순히 CRUD 에 맞춰 HTTP 메서드를 선택하는 것만으로는 충분하지 않습니다.실제 서비스에서는 언제든 다음과 같은 상황이 발생할 수 있습니다.네트워크 타임아웃으로 인한 ..

Network 2026.03.14

왜 모든 데이터 처리에는 map 이 존재할까?

Java Stream, Spark, Reactive가 공유하는 하나의 아이디어.map을 직접 구현하면서 람다, 제네릭, 선언형 프로그래밍의 본질을 이해한다.개발을 하다보면 어떤 API는 너무 자연스럽게 사용하게 된다.그 중 하나가 바로 Java의 map() 이다. 그런데 왜 존재하는지 깊게 생각해본 적 있는가?단순히 "있으니까 쓰는" API가 아니다. map 의 본질은 데이터 변환이다.이 글에서 얻어갈 것들map의 본질 을 개념이 아닌 코드 수준에서 직접 이해할 수 있다,람다와 Function 인터페이스 가 왜 등장했는지 그 필연성을 이해하게 된다,제네릭 을 활용해 어떤 타입에도 동작하는 범용 map을 직접 만들어 볼 수 있다.명령형 vs 선언형 프로그래밍 의 차이를 코드로 직접 체감한다,Java St..

JAVA 2026.03.12

테스트가 어렵다면 코드 탓이 아니라 설계 탓이다 - 숨겨진 의존성의 진실

이 글에서 얻어갈 것들이 글을 다 읽고 나면 다음 질문들에 스스로 답할 수 있게 된다."테스트 짜기 어렵다"는 느낌이 사실은 무엇을 의미하는가?외부 연동 (I/O, DB, 네트워크) 을 왜 도메인 로직과 받드시 분리해야 하는가?분리했을 때 의존성 방향은 어느 쪽이어야 하며, 외 그 방향이어야한 하는가?의존성 역전 원칙(DIP) 이 이론이 아니라 생존 전략인 이유는 무엇인가?패키지로 분리하는 것만으로 충분한가? 의존성 방향까지 확인해야 하는 이유프롤로그: 수동 테스트를 반복하는 개발자의 하루아마 이런 경험이 있을 것이다. 코드를 수정했다. 프로그램을 직접 실행하고, 키보드로 명령어를 입력하고, 눈으로 결과를 확인한다. 또 수정했다. 또 실행한다. 또 확인한다.자동화 테스트를 작성하려고 시도해봤지만 뭔가 이..

JAVA 2026.03.08

왜 실무에서는 Criteria를 안 쓰고 QueryDSL을 선택할까? (JPA 쿼리 선택 기준 정리)

JPA 가 지원하는 다양한 쿼리 방법 - JPQL부터 QueryDSL까지JPA를 처음 배우면 em.find() 로 단건 조회하는 것부터 시작한다. 엔티티를 조회하고 연관관계를 따라 객체 그래프 탐색하는 방식은 매우 직관적이다. 하지만 실무로 넘어가면 상황이 완전히 달라진다. 다양한 검색 조건, 동적필터, 조인, 정렬, 페이징, 집계까지 단순 조회만으로 해결할 수 없는 복잡한 쿼리가 필수적으로 등장한다. 이 글을 읽고 나면 네 가지를 명확히 판단할 수 있게 된다.JPA 가 지원하는 쿼리 방법의 종류와 각각의 실무 활용도를 이해하게 된다.JPQL이 왜 "객체 지향 SQL"이라고 불리는지 본질적인 의미를 알게 된다.Criteria 가 이론적으로 좋지만 실무에서 외면받는 이유를 납득하게 된다.QueryDSL..

JPA 2026.03.01

JPQL이 있는데 왜 Querydsl을 쓸까?

같은 쿼리로 비교하며 이해하는 Querydsl 의 진짜 가치Querydsl 을 접하면 이런 의문이 든다.JPQL도 있는데 왜 또 다른 쿼리 도구를 써야 하지? 겉으로 보면 JPQL과 Querydsl 은 결국 같은 JPQL을 실행한다. 하지만 실무에서의 차이는 문법이 아니라 오류를 발견하는 시점과 안전성에 갈린다. 이 글에서는 동일한 쿼리를 JPQL과 Querydsl로 각각 작성해보면서 두 방식의 차이를 코드와 동작 관점에서 직접 비교해본다. 이 글을 읽고 나면 네 가지를 명확히 이해하게 된다.JPQL과 Querydsl의 차이를 단순 문법이 아닌 안전성 관점에서 비교할 수 있다.Q 타입이 왜 존재하는지, 컴파일 타임 검증 구조를 이해하게 된다.Querydsl 의 자동 파라미터 바인딩이 보안과 성능에 주는..

JPA 2026.02.25