본문 바로가기

Project

'AI 협업 웹 사이트' 성능 개선 기록

문제 상황

 

메인 페이지 접속 시 데이터가 화면에 뿌려지는 데 까지

오랜 시간 소요

 


 

문제 분석

 

 

초기 랜딩 과정에서 API가 다건이 순차 호출 →

requests : 39

transferred : 140KB

finish : 2.48s

progress를 여러번 호출하는 것이 문제인 것으로 확인

 

const projectsWithProgress = await Promise.all(
   projectsWithFavorite.map(async (p) => {
    const progressResponse = await axios.get(
    `http://127.0.0.1:8000/api/user/${userId}/projects/${p.project_id}/progress/`,
    { withCredentials: true }
    );
    return { ...p, progress: progressResponse.data.progress };
  })
);

프로젝트 진행률을 조회하기 위해 프로젝트 개수만큼 따로 부르기 때문에

초기 개발 과정에서는 적은 수를 호출하였지만, 생성된 프로젝트가 쌓일수록

여러번 /progress 를 호출하게됨

 

결국 이건 프론트과정에서 진행률을 계산하려고 한 점이 문제라고 판단

 

 


 

문제 해결

 

 

우선, 기능을 만들며 기존 여러 API를 만들고 사용했던 것들을

기존 API를 재사용하지 않고 API를 새롭게 통합하여 구현

 

7개 → 1개

단일 API를 통해 왕복 및 중복 데이터 제거

 

그리고 중요한 가장 문제가 되었던 프로젝트 진행률을 조회하는 하는것을

API 에서 집계 쿼리로 조회 후 데이터를 넘겨주는 것으로 해결

 

active_by_project = dict(
  TaskManager.objects
  .filter(
    project_id__in=project_ids_qs,
    task__status__in=ACTIVE_STATUS_CODES
  )
  .values('project_id')
  .annotate(cnt=Count('task', distinct=True))
  .values_list('project_id', 'cnt')
)

 

결과를 dict로 만들어 O(1) 매핑만 하고 응답에 실어 보냄으로

프론트에서는 추가 호출이었던 progress 를 제거

 

즉, API도 단일 API로 만들고 프론트에서

필요했던 데이터도 미리 가공해서 전달

 

 


 

결과

 

 

requests : 39 → 14 (64.1%)

finish :  2.48s → 1.35s (45%)

transferred : 140KB → 16KB (88.6%)

 

단일 API와 서버에서 데이터를 집계한것으로 요청 수를 감소하며,

따라서 중복/분산 응답을 제거함으로 성능이 개선된것으로 확인 됨.

 

다시 실행하여 확인을 해보니 체감 될 정도로 속도가 개선 되었고

해당 문제에 대해서도 해결되었다고 판단

 

 


 

느낀점

 

1. API는 한 화면에서 여러개를 호출하는 것이 아닌,

"화면 단위" 로 모델링해야 성능적으로 우수한 것을 배웠다.

기능 개발 초기에는 엔드포인트로 기능별로 개발하다보면

규모가 커질 수록 여러 API가 호출되는데 이것은 바로 성능과 맞닿아 있다고 느꼈다.

 

2. 집계 즉, 데이터 가공은 DB에서 해결하고 애플리케이션에서는

매핑만 한다. 이번 가장 큰 문제였던, 진행률을 계산하는 API가 없어서

프론트에서 데이터 가공을해서 사용하려던 것이 결국 성능 저하의 원인이라고 느꼈다.

 

3. 기존 API를 억지로 조립해서 만드는 것은 항상 좋은 것이 아니다.

맥락에 맞게 API를 과감하게 통합하여 만드는 것이 때로는 전체적인 복잡도를

줄이는 경우가 있다. 재사용도 좋지만 규모에 따라 중복되는 데이터가 많아 성능을

저하 시키는 경우가 있으니 설계 전 필요한 데이터에 대해 깊게 생각 해보자.


GitHub