Devkor

[고대로] static 변수와 영속성 컨텍스트

진진리 2024. 8. 17. 22:32
728x90

https://jinjinjincode.tistory.com/313

 

[고대로] 운영 시간 관리

Devkor에서 '고대로'라는 학교 안내 어플을 개발하는 활동을 하고 있다.학교의 건물, 강의실, 편의시설 등의 운영시간을 관리할 필요성이 생겨 해당 기능을 맡아 구현하였다. 프로젝트를 시작하

jinjinjincode.tistory.com

 

운영 시간 관리를 구현하면서 영속성 컨텍스트 때문에 운영 시간 변동이 제대로 반영되지 않았던 오류가 발생하였다.

 


문제 상황

기능 구현 이후에 DB를 확인하던 중 운영하고 있는 시간임에도 건물의 isOperating이 false임을 발견하였다.

 

우선 해당 건물이 운영 중이라고 판단하는 로직에 오류가 발생해 false로 값이 저장되었나 싶어서 log.info로 확인해보았는데 스케줄러가 돌아갈 때마다 제대로 true로 찍히고 있었다.

하지만 DB를 보면 building의 isOperating은 그대로 false였다..

 

이 경우 영속성 컨텍스트가 생성되지 않아 객체의 변화가 DB에 반영되지 않는 케이스가 가장 먼저 떠올라서 트랜잭션을 확인해보았는데 해당 메서드에 @Transactional은 제대로 작성한 상태였다.

 

더욱 이상한 것은 위의 메서드에 있는 운영조건의 시설은 제대로 값이 반영되었는데 아래의 메서드에 있는 운영조건의 시설은 값이 반영되지 않는 것이었다.

 

해결 과정

일단 영속성 컨텍스트와 관련된 문제라고 생각해서 GPT의 힘을 빌려... 코드를 보내 질문을 했다.

시설 객체가 영속성 컨텍스트에서 관리되고 있는지 확인하라고 조언해줘서 코드를 가져와 의심쩍은 부분에 추가하였다.

// 영속성 컨텍스트에서 관리되고 있는지 확인
boolean isPersistent = entityManager.contains(building);
log.info("Is building persistent? {}", isPersistent);

 

역시나 반영이 되지 않는 시설 객체의 경우 false로, 반영이 되는 객체는 true로 로그가 찍혔다.

 

처음에는 운영 조건과 시설이 다대일 관계인 만큼 시설을 지연로딩으로 가져오기 때문에 이런 문제가 발생하는 것이라고 생각했다.

하지만 코드가 동일함에도 두 메서드에서의 시설의 영속 여부가 달라서 의문을 가지게 되었다.

 

문제 원인

그때 생각난 것이 운영 조건 리스트를 static 변수로 선언하였다는 것과

앞의 메서드에서는 해당 변수에 값을 저장하고 바로 사용하였지만 두 번째 메서드에서는 static 변수를 바로 사용하였다는 점이었다.

 

// 앞의 메서드에서는...
operatingConditionList  = findOperatingCondition(dayOfWeek, isHoliday, isVacation, evenWeek);

        for(OperatingCondition operatingCondition : operatingConditionList) {
            List<OperatingTime> operatingTimeList = operatingTimeRepository.findAllByOperatingCondition(operatingCondition);
        // . . . 중략 . . .
        
// 뒤의 메서드에서는...
for(OperatingCondition operCondition : operatingConditionList) {

            boolean isOperating = checkOperatingTime(operCondition, now);
            log.info("isOperating: {}", isOperating);
            // 중략 . . .

 

앞에서는 쿼리 메소드로 조회함으로써 영속성 컨텍스트에 의해 관리되게 된 운영 조건 리스트를 사용하고 있기 때문에 운영 조건의 시설의 운영 여부를 업데이트할 수 있었지만

 

뒤에서는 한 번 트랜잭션이 종료되어 영속성 컨텍스트에서 분리되었던 운영 조건 리스트를 가져와 사용하였기 때문에 static 변수인 운영 조건 리스트가 영속성 컨텍스트에 의해 관리되지 않아 운영 여부가 제대로 업데이트되지 않았던 것이다.

 

따라서 entityManager를 통해 각 시설을 업데이트 하기 전에 영속성 컨텍스트에 merge해주었다.

그러자 DB에 값이 제대로 반영되었다.

 

소감

서버를 돌려본 경험이 적다보니 효율적인 코드를 위해 static 변수를 사용해보면 어떨까? 싶어 사용해 보았는데 생각하지도 못했던 오류가 발생하였다. 이번 계기로 static 변수를 사용할 때의 영속성 컨텍스트를 고려할 필요성을 느끼게 되었다.