[Spring] 코드 개선 퀴즈 - @Transactional의 이해

Kim yoon beom·2025년 5월 9일

▶️문제.

  • 에러 로그 원문
jakarta.servlet.ServletException: Request processing failed: org.springframework.orm.jpa.JpaSystemException: could not execute statement [Connection is read-only. Queries leading to data modification are not allowed] [insert into todos (contents,created_at,modified_at,title,user_id,weather) values (?,?,?,?,?,?)]

▶️문제 원인 및 해결.

원인은 todo의 service 클래스

▶️원인.

TodoService 클래스에서 해당 메서드에 @Transactional 이 없거나, 클래스 전체에 @Transactional(readOnly = true)가 선언되어 있기 때문.

🤔@Transactional(readOnly = true)가 왜 문제를 일으키는가?

  • @Transactional(readOnly = true)는 말 그대로 읽기 전용 트랜잭션을 의미한다.
    이 옵션을 사용하면 다음과 같은 제약이 생긴다.

데이터베이스 연결이 읽기 전용 모드로 설정된다.
INSERT, UPDATE, DELETE와 같은 데이터 변경 작업이 허용되지 않는다.

에러 메시지에서 보이는 "Connection is read-only. Queries leading to data modification are not allowed"

-> 읽기 전용 연결에서 데이터 수정 쿼리(INSERT)를 실행할 수 없다는 것을 의미


▶️해결방법.

메서드 레벨에 별도로 @Transactional 어노테이션을 추가하면 클래스 레벨 설정을 오버라이드 해야 한다.

public TodoSaveResponse saveTodo(AuthUser authUser, TodoSaveRequest todoSaveRequest)
  • 위 메서드에서 데이터를 저장하려고 했지만 읽기 전용 트랜잭션에서 실행이 되고 있었다.

따라서, 트랜잭션을 효율적으로 관리하기 위한 권장 사항은 다음과 같다:

  1. 클래스 레벨에 @Transactional(readOnly = true)를 선언하여 기본적으로 모든 메서드를 읽기 전용으로 설정

  2. 데이터 수정이 필요한 메서드(CREATE, UPDATE, DELETE)에만 @Transactional을 선언하여 오버라이드

  3. 이렇게 하면 읽기 작업의 경우 성능 최적화를 유지하면서 필요한 곳에서만 데이터 수정이 가능

이런 방식으로 트랜잭션을 관리하면 성능 최적화와 데이터 무결성을 모두 달성할 수 있다.

profile
나는.원한다.개발자

0개의 댓글