Weekly I Learned/2023's(1. ~ 12.) WIL

2023년 10월 5주차(10/30 ~ 11/3) Weekly I Learned "점차 익숙해지고 있는 업무! 🐥"

ikjo 2023. 11. 6. 04:19

지난 한 주 되돌아보기

입사한지 어느덧 3개월이 되가고 있는 요즘 이슈 처리 사이클을 여러번 거치면서 업무가 점차 손에 익는듯한 느낌을 받고있는 중에 있다. ✨ (이전 보다는 뭔가 자연스러워진 느낌이다. 👀)

 

Http Client 동작 테스트 및 재배포 🔧

지난 주 blocking I/O 방식을 그대로 유지한채(비지니스 로직 변경 없이) 단순히 RestTemplate 에 의존하는 것을 WebClient 에 의존하는 것으로 바꾸기만한 일부 Http Client 에서 예상치 못한(인코딩과 관련된) 에러가 발생했었기에, 해당 Http Client 들에 대해 일괄적으로 로컬 환경에서 Client Server 를 구축한 이후 Test Target Server 와의 연동 테스트를 재수행했다.

 

로컬 환경 상에서 Client Server, Test Database 등을 일일이 구축하여 실제 운영 환경과 거의 근접한 상황을 구현하는 것이 생각보다 오랜 시간이 소요되었는데, 이러한 작업들을 수행하면서 현재 업무에 대한 많은 지식을 쌓을 수 있어 유익했다. 이후 연동 테스트 작업을 통해 운영 상에서 발견되지 않은 몇가지 잠재적인 추가 에러 시나리오들도 검출할 수 있었다. (ObjectMapper 는 기본 설정 상으로는 빈 문자열을 파싱할 수 없었으며, DB 에 저장된 callback url 상에 제어문자가 포함되어 해당 제어문자가 URL 인코딩 되는 이슈 등이 있었다. 💫)

 

단순 변경 작업이었기에 팀 내에서도 별다른 걱정을 하지 않은 채 요청 작업이 제대로 처리되는지 정도만 확인된 후 배포가 되었으나, 기대와 달리 전혀 예상치 못한 부분(인코딩)에서 에러가 발생했기에, 다시 한 번 테스트를 "잘" 해야한다는 교훈을 뼈저리게 느낄 수 있었다. 💦

 

결론적으로 해당 Http Client 들은 재배포되어 정상적으로 동작했다. 🍺 아울러, 지난 주에 배포되어 정상적으로 수행됐었던 (애초에, 철저한 테스트 과정을 거쳤던) non-blocking I/O 방식의 Http Client 는 사용자 latency 를 85% 절감시킬 수 있었다. (이제서야 WebClient 관련 작업이 모두 종료되었다. 👀)

 

Update 쿼리 튜닝 도전! ✍

지난 주 실행 시간이 최소 1시간 이상 발생했었던 Update 쿼리를 튜닝하기 위해 우선 몇달 전 읽었던 "업무에 바로 쓰는 SQL 튜닝" 책을 다시 한 번 훑어 보며 기반 지식을 재점검해보았다. 이후, 해당 쿼리에 대한 실행계획을 살펴보니 JOIN 되는 테이블에서 데이터를 가져올 때 풀 테이블 스캔(ALL) 및 인덱스 풀 스캔(index)이 발생하는 것을 확인할 수 있었는데, 결론적으로 해당 쿼리가 이처럼 악성 SQL 이 됐었던 데에는 JOIN 시 ON 절에서 CAST 를 이용한 형변환을 했기 때문이었다.

 

해당 Update 작업을 수행하기 위해서는 참조 관계가 아닌 (타입이 VARCHAR, BIGINT 로 각각 다른) 필드간 JOIN 이 필요했는데, 동등 비교 연산을 위해 CAST 를 이용해 같은 타입(CHAR)으로 형변환 처리를 해주었었다. 하지만 해당 Update 쿼리의 조건절 상에서의 데이터 분포를 살펴보니, 해당 조건 상에선 VARCHAR 데이터는 모두 정수값을 지니고 있었기에, 굳이 두 필드를 모두 CHAR 로 변환할 필요가 없었다. (별도로 CAST 하지 않을 경우 MySQL 은 경우에 따라 자동으로 문자열을 숫자로 변환하거나 숫자를 문자열로 변환한다.) 문제는 이러한 CAST 연산 때문에 DB 에서 JOIN 시 인덱스를 제대로 활용하지 못하고 있다는 것이었다.

 

결론적으로, JOIN 시 ON 절에서 이러한 불필요한 CAST 연산을 제거해주니 당초 1 시간 이상 소요됐었던 악성 SQL 이 5초만에 실행되었고, 실행계획 상으로도 JOIN 되는 테이블로부터 데이터를 조회 시 모두 인덱스를 활용하여 최적화(index → eq_ref, ALL → ref)되는 것을 확인할 수 있었다. 굉장히 초보적인 실수였지만, 해당 문제 해결 과정을 통해 이전보다 조금이나마 DB 에 대해 더 알아갈 수 있었다. 🚀

 

Pullanner 프로젝트 기능 구현은 완료..!

무려 2달 전 Pullanner 프로젝트의 Plan & Badge & Level 기능 구현을 마무리 지은 이후 한동안 작업이 없었는데, 최근 사용자의 운동 정보를 요약해서 보여주는 Dashboard 기능에 대한 기획과 기능 구현까지 마무리할 수 있었다. 이제 Pullanner 프로젝트를 구성하는 Auth, User, Plan, Workout, Article, Summary 각각의 비지니스 도메인 백엔드 기능들을 모두 구현했는데, 이제는 기존 코드들을 최적화하고 각각의 기능들에 대해 고도화해야 (내실을 다져야) 할 때가 온 것 같다. 👀

 

(백준 1일 1커밋 운동은 계속되고 있다...🏃‍♂️)