개요
슬축생 프로젝트 시리즈는 이제 끝날줄 알았다, 개발 후 문제 없이 운영한지 1년이 되어 가는 서비스였고 더 이상 개선점이 없다고 생각했다.
그렇게 1년이 지나가는 사이에 나는 많이 성장하였다, 영한님의 강의를 들으면서 여러 성능 최적화와 프레임워크의 내부 동작 방식에서 오는 문제점을 해결하는 법등을 배워나갔다.
그러다가 문득 생각이 들었다, 내가 슬축생을 개발할 당시에는 N+1에 대한 지식이 없이 개발을 하였는데 과연 N+1이 발생되고 있지 않을까라는 의문이 들었다. 그런데 발생 안 할 가능성이 거의 없다고 생각했다, 왜냐면 엔티티끼리 긴밀하게 연결되어 있고 서로 LazyLoading 전략으로 데이터를 끌어온다는 것을 개발한지 1년이 지난 지금도 명확하게 기억하고 있기 때문이다.
그래서 다급하게 오랜만에 잠들어 있던 도커의 테스트용 컨테이너들을 가동하고 테스트를 하기 시작했다.
역시나 없을리가 없지!
직접 테스트 환경에서 테스트 하기전 코드를 먼저 오랜만에 열어봤다, 역시나 레포지토리에서 List로 가져온 후 서비스 클래스에서 신나게 for each문으로 데이터를 돌려가는 코드를 보면서 아직 실행도 안해봤지만 쿼리나 얼마나 쫙쫙 나가고 있을까 한숨이 나왔다. 🫣
N+1이 발생하는 부분이 한 두곳이 아니였지만 일단 제일 많이 발생할것 같은 부분을 꼽아서 테스트 해보기로 하였다.
테스트 환경을 가동하고 테스트 데이터를 넣어서 로그를 찍어본 결과..
이 로그를 보자마자 작년의 내 모습이 스쳐지나간다. 그때도 분명 이렇게 쿼리가 쫘라락 실행되는걸 목격했던 기억이 분명 있다.
근데 그때는 정말 무지했던 상태여서 정말 아무 생각도 없었던 것 같다, 근데 아무리 무지해도 이렇게 찍히면 음? 해야했는데 왜 그랬을까..
그래서 바로 지라에 이슈를 등록하고 해결을 하기 시작했다.
해결 방법
Fetch Join을 제일 먼저 고려해봤다, 전체적으로 딱히 페이지네이션 하는 부분이 존재하지 않아서 괜찮은 선택지였다고 생각이 들었다.
수정 후 테스트를 해보니 쿼리가 두개로 줄어들었다, 너무 간단하지만 모른다면 무심코 넘어갈 수 있는 무시무시한 문제 중 하나인것 같다.
근데 간단하다고 생각했는데 팀원들에게 설명해주니 이해를 못하는 눈치였다, 영속성 컨텍스트나 1차 캐시, 스프링 컨테이너의 프록시 같은 내부 동작 배경이 깔려 있지 않은 사람들에게는 또 이해가 어려울 수 있다고 생각이 들었다.
나중에 팀 기술 블로그에 N+1 문제를 배경지식과 함께 풀어서 설명하는 글을 써봐야겠다고 생각이 들었다.
얻어낸 결과
무엇이든 문제를 해결했다면 얻은 결과가 있어야한다, 그래서 나는 수정된 버전을 배포하기 전에 API의 응답 시간을 기록하고 수정된 버전이 배포 된 후의 응답 시간을 비교해봤다.
Postman으로 측정한 전과 후 차이나, 데이터가 워낙 많이 있지는 않아서 유의미한 차이인가? 싶기는 했는데 여러번 시도한 결과 분명 10ms 이상이라도 단축되는것이 랜덤한 수치가 아닌 개선 전과 후에서 명확하게 들어났다.
마무리하며
이제 막 시작하는 꿈나무 개발자로써 매년마다 성장 커브가 매우 빡쎄게 올라가고 있다고 생각이 든다, 그러니까 더더욱 새로운 프로젝트에만 집중하는것이 아닌 예전에 개발된 프로젝트들도 배운 내용들을 적용하면서 코드를 개선해 나가는것이 복습과 성장에 좋은 영향을 준다고 생각하는 계기가 되었다.
특히나 현재 운영중인 프로젝트는 새롭게 배우는게 생기는 부분이 있을때마다 뒤돌아봐야겠다고 느끼게 되었다.
'개발 공부 일기장 > 사이드 프로젝트' 카테고리의 다른 글
[슬축생 프로젝트] 12. 서비스 1년째, 도메인과 ssl 인증서 연장 (0) | 2024.09.02 |
---|---|
[슬축생 프로젝트] 10. 회원가입 아이디 중복 확인시 동시성 문제 해결 (0) | 2024.02.19 |
[슬축생 프로젝트] 9. 프로메테우스 & 그라파나 모니터링 도입기 (0) | 2024.02.09 |
[슬축생 프로젝트] 8. Vultr로 이사가기 & 도커로 배포 자동화 하기! (1) | 2024.01.21 |
[슬축생 프로젝트] 7. Spring Exception Handler로 우아하게 예외 처리하기 (0) | 2023.12.28 |