카테고리 없음

@Transactional과 @Transactional(readonly = true)를 어떤 목적으로 설정하나요?

소프 2024. 4. 12.

 

면접에서 아래 코드에 대한 구조 리뷰를 요청 받았습니다.

 

@Service
@Transactional(readOnly = true)
public class StationService {
    private StationRepository stationRepository;

    public StationService(StationRepository stationRepository) {
        this.stationRepository = stationRepository;
    }

    @Transactional
    public StationResponse saveStation(StationRequest stationRequest) {
        Station station = stationRepository.save(new Station(stationRequest.getName()));
        return createStationResponse(station);
    }

    public List<StationResponse> findAllStations() {
        return stationRepository.findAll().stream()
                .map(this::createStationResponse)
                .collect(Collectors.toList());
    }

    @Transactional
    public void deleteStationById(Long id) {
        stationRepository.deleteById(id);
    }

    private StationResponse createStationResponse(Station station) {
        return new StationResponse(
                station.getId(),
                station.getName()
        );
    }
}

 nextstep의 atdd 과정에서 작성한 코드 입니다. 링크

 

JpaRepository를 이용해서 저장, 전체 조회, 삭제 기능이 전부인 특별한 기능이 없는 코드입니다.

면접 당시에는 코드를 있는 그대로 세세하게 설명 했습니다. 하지만 돌이켜 생각해보면 면접관님들이 코드에서 어떤 부분을 중점적으로 듣고 싶으셨던건지 먼저 파악을 했었어야 했습니다. 기능 자체를 궁금해 하시진 않을테니까요..!!

 

질문의 목적은 @Transactional(readOnly = true)과 @Transactional이 필요하지 않아 보이는 코드에서 선행에서 달은 이유였습니다.

 

의도는 읽기역할을 하는 메서드들과 아닌 것들을 구분하기 위해 클래스 단에 @Transactional(readOnly = true)를 달고, 조회기능이 아닌 CUD 역할을 하는 메서드에 @Transactional를 달았습니다. 

면접에서 더티체킹을 위해 달았다고 말했는데 막상 로직에선 수정 로직이 없었다는... 😭

 

하지만 현재 코드에서는 @Transactional(readOnly = true)과 @Transactional를 달지 않아도 기능이 정상적으로 동작합니다.

 

1. saveStation()

  • 구현체인 SimpleJpaRepository안의 save() 메서드에 @Transactional이 달려있고,
  • 더티체킹 같은 영속성 컨텍스트가 필요한 로직이 없기 때문에 @Transactional 불필요

2. deleteStationById()

  • 구현체인 SimpleJpaRepository안의 deleById() 메서드에 @Transactional이 달려있고,
  • 더티체킹 같은 영속성 컨텍스트가 필요한 로직이 없기 때문에  @Transactional 불필요

3. findAllStations

  • 지연로딩 처리같이 트랜잭션이 필요한 작업을 하지 않기 때문에 @Transactional 불필요

 

불필요하게 @Transactional을 걸면 리소스가 낭비됩니다.

여기서 말하는 리소스는 디비 커넥션을 의미합니다. 만약에 트랜잭션이 퍼져 있고 일부 긴 시간이 걸리는 메서드가 실행되고 있다면 다른 간단한 조회 API 요청에서 커넥션을 취득하지 못할 수도 있습니다.

 

결론은, @Transactional이 꼭 필요한 상황에서만 달자!! 입니다.

 

Service단에 @Transactional을 습관적으로 달았는데 이는 좋지 않은 습관임을 깨달았습니다.

이러한 코드 리뷰를 회사에서 받고 싶었던 건데 면접에서라도 받을 수 있어 행복하네요.. 

앞으론 코드 한줄이라도 깊게 생각하면서 구현을 해야겠습니다.

 

 

참고

https://www.youtube.com/watch?v=mB3g3l-EQp0

 

댓글