[JPA] Too many connections... 원인 분석 And 해결 (Feat. 순환참조)

이진경·2025년 5월 22일
0

Spring boot + JPA

목록 보기
1/1

서론

master 브랜치에서는 정상 작동하던 API가 develop 브랜치에서는 오류를 뿜어낸다는 점이었습니다.
처음에는 어디서 문제가 발생했는지 전혀 감을 잡지 못했는데, 그 이유는 바로 JDK 버전이 11에서 17로 업그레이드되며 대대적인 변화가 있었기 때문입니다.
Deprecated된 코드들도 전부 교체되었고, 이로 인해 변경된 코드의 양이 너무 많아 단순히 diff만으로는 원인을 찾기 어려운 상황이었습니다.
그래서 "일단 이 버그부터 해결해보자!"는 마음으로 파고들었고, 결국 원인을 찾아 해결까지 해냈습니다! 😂
yml파일에 connections 수를 늘려보아도 해결이 되지 않았습니다. 결과적으로는 코드내에 버그가 원인이었습니다.

1. 원인: 불필요한 DB 커넥션 증가

처음에는 다른 누군가가 계속... 우리 개발DB에 연결 시도를 하는걸까?? 라는 생각을 했지만 그건 아니었습니다.ㅎ
알고 보니 특정 객체에서 너무 많은 커넥션을 소모하고 있었습니다.

그 중 하나는 바로 @Data 어노테이션이었습니다.

@Data@ToString()도 포함하기 때문에 연관된 객체를 계속 불러오면서 예상보다 많은 쿼리가 실행되는 문제가 있었습니다.

특히 FeedPin 간 양방향 연관관계에서 순환 참조로 인해 디버깅도 느려졌고, 예상치 못한 DB 접근이 생겼습니다.
이 부분을 제가 단번에 캐치해내지 못했었죠..! 🤨

  1. @ToString 같은 메서드에서 무한 루프 발생
    Feed.toString() → Pin.toString() → 다시 Feed.toString()...
  2. 디버깅 시 불필요한 필드 조회로 지연 로딩 발생 가능성 매우 큼
    -> 여기서 엄~청 느린 디버깅 속도를 체감하였습니다. 한줄 내려갈때 약 15초 정도 걸린거같습니다.
    ➡ 해결: @Data 대신 @Getter, @Setter를 명시적으로 사용하고, @ToString은 필요한 곳에만 명시적으로 적용을 하였습니다.

결과적으로 @Data → @ToString() 포함됨 → 불필요한 DB 접근 + 순환참조 -> 지연 로딩 → 성능 저하 또는 예외 발생 Too many Connections........ 로그를 찍게 된 것이었습니다.

이 내용은 실제로 Lombok 공식 홈페이지에 기재되어있는걸 확인하실수 있습니다.

2. 원인: 연관관계 필드 설정 누락

Feed 객체 내부에 setPinList()로 데이터를 주입하는 과정에서 각 Pin 객체에 Feed를 역으로 설정하지 않아 feed_idnull로 남아 있었습니다.
해당 컬럼은 NOT NULL 제약 조건이 있었기 때문에, JPA가 이를 채우기 위해 지속적으로 DB 접근을 시도했던 것으로 추정됩니다.

저 에러로그가 API호출 할때마다 계속 발생했었죠. 😤 어디서 계속 null값을 넣고있을까...

❗ 약식으로 오류가 발생했던 객체의 구조를 명시해보면

Feed {
	...
	Pin: {
    	...
        FeedID: xxx  <- 이게 Not null
	}
	...
}

요런 형식이 됩니다. 여기서 feedService.createFeed()을 호출을 하고
pinService.createPin(pinList, feed)를 호출하게 되는데 이때
PIN객체를 구성하는 코드에서
pin.setFeedId(feed.id) <- 이 코드가 없었던 것이었죠!!

즉, PIN 테이블에 insert 하려는 시점에 feedId가 null이라서 DB에서 NOT NULL 오류가 발생한겁니다.
참 간단한 내용이었지만.. 이 Feed_Id column을 많은 테이블에서 참조하고 있었던것이 문제였네요.

➡ 해결: pin.setFeedId(feed.id) 호출을 추가하여 연관관계를 명확히 하였고 결과적으로는 Too many Connection...에서 벗어나게 되었습니다. 👏


📌 교훈

  • @Data는 편하지만, 연관관계가 많은 엔티티에는 피하자.
  • @ToString은 조심해서 사용하고, 지연 로딩(LAZY) 필드는 절대 포함하지 말자.
  • 연관관계 설정은 양방향일 경우 양쪽 모두 정확히 설정해야 한다.
  • Too many connections는 커넥션 풀 설정 문제가 아닌 코드의 잘못된 DB 접근일 수 있다.

📚 참고사이트

Lombok 공식사이트

profile
기록남기기

0개의 댓글