김영준

김영준님의 아티클

김영준

김영준

프로젝트 [Find Spot] 에서 어떤 이슈가 있었나?

여행을 위한 새로운 컨텐츠를 만들어 보고자 시작한 졸업 프로젝트입니다. 어쩌다 보니 졸업 프로젝트지만 대부분 혼자 작업했습니다. 작업 중에 일도 하고, 미국도 갔다오고, 있었던 크고 작은 일이 하나 하나 이슈 같다는 생각도 듭니다.

Find Spot은 미션 사진의 포토스팟을 찾아가서 같은 구도로 촬영한 사진을 이미지 유사도 분석을 통해 인증하는 챌린지 서비스입니다.

오랜기간 야금야금 얇고 길게 개발하면서, 비슷한 케이스에 도움이 되길바라며, 기억에 남는 이슈와 해결 과정을 모아봤습니다.


이슈 4 #리팩토링 #QueryDSL #N+1이슈

⚠️ 데이터베이스에서 Soft Delete 정책을 사용하였기에, 대부분의 쿼리에서 ORM의 순정 쿼리를 사용하기에 문제가 있었다.
⚠️ 3개의 테이블을 join해서 데이터를 가져오는 복잡한 쿼리를 JPQL을 통해 처리하였는데, 유지보수 측면에서 코드 관리에 용이하지 않았다.

해결

  • QueryDSL을 도입하여 기존의 쿼리를 유지보수에 용이하도록 리팩토링했다.
  • Soft Delete 정책을 사용하게 되면, 삭제 여부를 나타내는 칼럼의 값에 따라 조회 여부가 갈리기 때문에, 모든 조회 ORM을 새로 정의해서 사용해야 했다.
  • 특히 쿼리에 힘을 주어 데이터 처리 로직을 가볍게 만드는 방법에 관심이 많았기 때문에, JPQL로 정의된 복잡한 쿼리가 많았다.
  • 이러한 쿼리를 관리하기에 QueryDSL이 적합하다는 기술 블로그 글을 보고 채택하게 되었다.
  • 추가적으로 QueryDSL의 기능을 사용하면 N+1 이슈를 해결하기도 쉬웠기 때문에 적용해보고 싶었다.

성과

  • 기존보다 더 복잡한 쿼리를 편리하게 사용할 수 있어서, 서버에서의 후처리를 대폭 줄일 수 있었다.
  • .fetchjoin() 으로 한번에 필요한 데이터를 모두 불러오거나 Projection.constructor 를 통해 쿼리 결과를 DTO에 바로 맵핑하는 방법으로 쉽게 N+1 문제를 해결할 수 있었다.
  • 상당 수의 코드를 재사용하여 유지보수가 편리해졌다.

이슈 3 #React #Hook

⚠️ 페이지를 빠르게 새로고침할 때, 일부 리소스가 비어있거나, 중복으로 표시되거나, 표시 위치가 섞이는 문제가 발견되었다.

해결

  • setState를 통해 데이터를 저장 직후 state를 사용하던 부분을 직접 대입하는 방식으로 변경했다.
  • 원인을 분석하다 각 코드의 동작 방식을 알아보기 시작했다.
  • React hook에 대해 알아보다가 setState를 통해 state에 데이터를 저장하는 것이 비동기 적이므로, 순차적으로 실행되는 것이 보장할 수 없다는 것을 알게되었다.
const [mission, setMission] = useState(0);
const getSuccess (id) => {/* ... */};

setMission(1);
getSuccess(mission);
  • 해당 부분을 원인으로 판단하고 테스트 해본 결과 원인이 맞았다.

성과

  • 앞서 언급했던 페이지의 이상 현상을 해결할 수 있었다.
  • React Hook의 동작 방식을 이해하게 되었다.

이슈 2 #리팩토링 #Code-Convention

⚠️ 백엔드를 공부하던 초기부터 개발한 프로젝트였기 때문에, 개발하면서 코딩 스타일과 설계 방법이 달라져서 도메인 마다 코드가 중구난방이 되었다. 따라서 생산성이 점차 떨어지기 시작했다.

해결

  • 기능 개발 스프린트를 멈추고, 리팩토링 스프린트를 할당하여 작성 방식을 통일하는 작업을 수행했다.
  • 개발 초기에 코드 컨벤션의 중요성을 간과했기에 작성한 코드는 나중에 작업한 코드와 비교하여 코드 작성 규칙이 너무 달랐다.
  • 따라서 개발 과정에 다른 도메인의 코드를 다시 분석해야 하는 일이 많았다.
  • 앞으로 길게 개발하기 위해 내실을 다질 필요가 있다고 판단했다.

성과

  • 리팩토링을 한 이후로 개발이 편해졌다.
  • 코드 작성 규칙을 정리하였다.
  • 인터페이스 분리, 컨벤션 통일, 설계 통일을 통해 코드 생산 속도가 더 빨라졌다.
  • 장기적으로 개발할 것을 생각했을 때 탁월한 판단이었던것 같다.

이슈 1 #설계

⚠️ 스프링부트 메인 서버와 플라스크 AI 서버간에 통신을 어떻게 할지 고민이 있었다.

해결

  • 단계적으로 개선하도록 계획했다. 1차적으로 Rest Template으로 요청을 보내고, 이후에 RabbitMQ를 통해 의존성을 낮추는 계획을 했다.
  • http, gRPC, MQ 중 고민을 했었다.
  • 속도가 빠른 gRPC를 사용하는 것을 고려하였으나, 유사도 분석 과정의 속도가 느리기 때문에 Non-Blocking으로 의존성을 낮추고, 별도의 Scale out이 가능하게 되는 것이 적절하다고 판단했다.
  • 그래서 MQ를 통한 의존성 분리를 적용하는 것을 최종 목표로 하고, 시간상 임시로 http 를 사용하기로 했다.

현황

  • 현재 http로 요청을 보내게 구현을 해둔 상태로, 다음 개발 기간에 MQ 적용 예정이다.


앞으로 계획

데이터 엔지니어링을 공부하는 입장에서 적용하고 싶은 고도화 플랜이 많은데, 현재 진행중인 프로젝트가 끝난다면 한 부분씩 고도화 해볼 계획입니다. GPT를 활용하여 기존에 갖고있던 데이터에 쉽게 새로운 인사이트를 +@를 해서 예상치 못한 다른 인사이트를 제공할 수 있을것 같아 가장 기대가 됩니다.

Find Spot

이미지 유사도 분석 AI 기반 포토스팟 인증 서비스

11
4