ChatGPT가 "fetch join 쓰세요"라고 했다. 그대로 했더니 더 깊은 에러가 나왔다.
— 학습 맥락을 아는 AI는 같은 질문에 어떻게 다르게 답하는가. 직접 비교해본 기록.
주니어 백엔드라면 한 번쯤 밟는 길이다.
게시판 프로젝트. Post 하나에 댓글(comments)과 태그(tags)가 달려 있다. 목록 10개를 불러왔더니 쿼리가 100개 넘게 나간다. 전형적인 N+1.
검색하거나 ChatGPT에 물어보면 답은 거의 똑같다. "fetch join을 쓰세요."
java
@Query("select p from Post p " +
"join fetch p.comments " +
"join fetch p.tags")
List<Post> findAllWithDetails();그래서 그대로 했다. 그랬더니:
org.hibernate.loader.MultipleBagFetchException:
cannot simultaneously fetch multiple bagsN+1은 사라졌는데, 더 낯선 에러가 그 자리를 채웠다. 많은 주니어가 정확히 여기서 멈춘다. 조언대로 했는데 한 칸 더 깊은 구덩이에 빠진 셈이다.
이 지점에서 두 종류의 AI에게 똑같은 질문을 던졌다. 하나는 내 맥락을 모르는 일반 AI, 하나는 내가 그동안 뭘 했는지 아는 AI다.
질문: "MultipleBagFetchException 떴어요. 어떻게 고치죠?"
🅰️ 맥락 없는 일반 답변
MultipleBagFetchException은 두 개 이상의 컬렉션(Bag)을 동시에 fetch join할 때 발생합니다. 해결 방법은 다음과 같습니다.
List를Set으로 변경한다.
@BatchSize또는default_batch_fetch_size를 사용한다.컬렉션 하나만 fetch join하고 나머지는 별도로 조회한다.
상황에 맞는 방법을 선택하세요.
틀린 말은 하나도 없다. 그런데 이 답을 받은 주니어는 여전히 막혀 있다. 세 가지 중 내 상황에서 뭘 골라야 하는지를 모르기 때문이다. 그리고 이 답은, 내가 방금 N+1을 어떻게 처리하려다 여기까지 왔는지를 전혀 모른다.
🅱️ 학습 맥락을 반영한 답변
이틀 전에
Post목록 N+1을 잡으려고comments랑tags에 fetch join을 둘 다 거셨죠. 그게 정확히 이 예외의 원인입니다.
List컬렉션은 Hibernate 내부에서 'Bag'으로 취급되는데, Bag 두 개를 한 번에 fetch join하면 결과가 카테시안 곱(댓글 수 × 태그 수)으로 부풀어요. Hibernate는 이 중복을 정리할 방법이 없어서 아예 예외로 차단합니다.지금 프로젝트가 게시판이고, 한 글에 댓글은 보통 수십 개·태그는 두세 개 수준이죠. 그러면 이 조합이 가장 깔끔합니다.
댓글만 fetch join으로 한 번에 가져오고,
태그는 배치 조회(
default_batch_fetch_size)로 IN 절에 묶어서 한 번에.yaml
spring: jpa: properties: hibernate: default_batch_fetch_size: 100java
@Query("select distinct p from Post p join fetch p.comments") List<Post> findAllWithComments();이러면 댓글은 fetch join 1번, 태그는 배치 IN 조회 1번 — 총 2번으로 끝납니다.
Set으로 바꾸는 방법도 되지만, 댓글에 작성순 정렬이 필요하면Set은 순서 보장이 까다로워서 이 케이스엔 위 조합을 권합니다.
두 답변의 정보량은 사실 비슷하다. 차이는 한 곳에서 갈린다.
🅰️ 맥락 없는 답변 | 🅱️ 맥락 반영 답변 | |
|---|---|---|
알려주는 것 | 선택지 3개 나열 | 선택지 + 내 상황에 맞는 결정 |
전제 | 내가 어떻게 여기 왔는지 모름 | 이틀 전 fetch join 시도를 기억 |
결론 | "알아서 고르세요" | "이거 쓰세요, 왜냐하면" |
주니어 체감 | 여전히 막힘 | 다음 줄을 칠 수 있음 |
🅰️는 "이런 선택지들이 있다"에서 끝난다. 🅱️는 "당신 상황에선 이걸 고르세요, 왜냐하면"까지 간다.
그 '왜냐하면'을 채우는 건 결국 맥락이다. 내가 이틀 전에 뭘 시도했는지, 어떤 에러를 거쳐 여기 왔는지, 내 프로젝트가 뭔지. ChatGPT에 이 맥락을 매번 처음부터 다시 붙여넣어 본 사람은 안다. 그게 얼마나 번거롭고, 또 얼마나 자주 빼먹는지.
그래서 만들고 있는 것
나는 백엔드를 12년 했고, 지금은 주니어 개발자가 막혔을 때 이미 알고 있는 자기 맥락을 매번 다시 설명하지 않아도 되는 학습 AI를 만들고 있다. 위 🅱️ 같은 답변을, 당신 케이스로 직접 받아볼 수 있게 해뒀다.
(위 사례는 자주 반복되는 패턴을 재구성한 대표 케이스다. 특정 개인의 대화를 그대로 옮긴 것이 아니다.)
내가 "이게 더 낫다"고 우기는 건 의미가 없다. 그래서 직접 비교해볼 수 있게 만들었다.
최근에 막혔던 Java/Spring 순간 하나만 들려주면, AI가 그 맥락을 반영한 답변과 일반 답변을 나란히 보여준다. 어느 쪽이 더 쓸모 있는지는 직접 1~5점으로 매겨보면 된다. 5분이면 된다.
👉 당신 케이스로 직접 비교해보기 → https://devpath-landing-page.pages.dev/
(스택이 React·Flutter·Python이어도 대기 신청은 받는다. 다만 지금 비교 데모는 Java/Spring 맥락이 가장 정교해서, 그 스택부터 검증 중이다.)