Java 애플리케이션을 운영하다 보면 간헐적으로 Connection reset 에러를 만날 때가 있습니다. 단순히 네트워크가 끊겼다고 넘기기 쉽지만, 실제로는 클라이언트, 서버, 프록시, 방화벽, 타임아웃 설정이 함께 얽혀 있는 경우가 많습니다.Java Connection reset 에러는 어떤 상황에서 발생할까Java Connection reset 에러는 이미 연결된 TCP 커넥션이 상대방에 의해 강제로 종료되었을 때 주로 발생합니다. Java 코드 입장에서는 데이터를 읽거나 쓰는 도중 연결이 갑자기 끊긴 상태로 보이기 때문에 java.net.SocketException: Connection reset 형태의 예외가 남습니다.이 에러가 까다로운 이유는 애플리케이션 코드 한 줄만 보고 원인을 단정하기 어..
Java와 Spring Boot로 서비스를 만들다 보면 트랜잭션을 너무 넓게 잡는 코드가 생각보다 쉽게 나옵니다. 처음에는 단순해 보이지만, 외부 API 호출이나 느린 로직이 DB 트랜잭션 안에 들어가면 운영 중 장애로 이어질 수 있습니다. 트랜잭션 분리를 하지 않아 문제가 커졌던 사례를 기준으로, 원인과 개선 방향을 정리해보겠습니다.Java 트랜잭션 장애가 발생한 실제 문제 상황Java 기반의 주문 처리 서비스에서 발생한 문제였습니다. 사용자가 결제를 완료하면 서버는 주문 상태를 변경하고, 결제 승인 결과를 저장한 뒤, 외부 정산 API를 호출하는 흐름을 가지고 있었습니다.처음 코드는 보기에는 단순했습니다. 하나의 서비스 메서드에 @Transactional을 붙이고, 그 안에서 주문 조회, 상태 변경,..
Hibernate flush는 단순히 save를 호출했을 때 DB에 저장되는지 여부만의 문제가 아닙니다. 트랜잭션 안에서 엔티티 변경 내용이 언제 SQL로 변환되고, 어떤 시점에 DB 제약조건이나 쿼리 결과에 영향을 주는지를 이해해야 디버깅 시간을 줄일 수 있습니다.Java Hibernate flush 타이밍은 왜 헷갈릴까?Java 애플리케이션에서 Hibernate flush 문제는 JPA를 어느 정도 사용해본 뒤에 자주 마주칩니다. 처음에는 save()나 persist()를 호출하면 바로 DB에 반영된다고 생각하기 쉽지만, Hibernate는 보통 변경 내용을 영속성 컨텍스트에 모아두었다가 필요한 시점에 SQL을 실행합니다.이 차이 때문에 코드상으로는 저장한 것처럼 보이는데 실제 DB에는 아직 SQL이..