https://dbd-random-perks-kr.netlify.app/
데바데 랜덤퍽KR
dbd-random-perks-kr.netlify.app
크롤러 서버를 적용한 DBD 랜덤퍽 사이트가 배포되었다.
데이터 관리의 편의성은 증가했지만, 매번 서버에서 데이터를 받아오는 과정에서 소요되는 시간이 너무 길었다.
기존 서버 응답시간은 7.04초로, 사용자 입장에서 불편할 정도로 너무 긴 시간이 소요되었다.
❓ 문제 원인
먼저 개발되어 배포 중이던 프론트엔드의 수정을 최소화하기 위해, 프론트엔드에서 요구하는 데이터 형식에 최대한 맞추는 형식으로 백엔드 서버를 개발했다.
크롤링 된 데이터는 Playable, Item, Perk, Addon, Offering 5개의 테이블에 저장되고, 프론트엔드에서 요청시 나뉘어진 데이터를 하나의 JSON 형식으로 가공하여 응답하게 된다.
이 과정의 소요 시간이 길 것은 개발할 때에도 예상할 수 있는 문제였기에 DB 구조 자체를 응답할 데이터 형식과 유사하게 설계하는 방법도 고려했으나, 데이터의 관리나 추후의 기능 확장 등을 고려하여 클래스별로 테이블을 나누어 저장하는 것이 맞다고 판단했다.
어쨌든 원인은 5개의 테이블에서 데이터를 조회해 가공하는 과정을 역할군(killer, survivor)별로 두 번 씩 거친다는 점이다.
✅ 개선 방법
수정 전 코드
DataService.java
public WholeDataFindResponse getData() {
return new WholeDataFindResponse(getSurvivorData(), getKillerData());
}
public SurvivorFindResponse getSurvivorData() {
/*...*/
}
public KillerFindResponse getKillerData() {
/*...*/
}
데이터 요청시 controller에서 DataService의 getData를 호출하며, 매번 데이터를 가공하는 과정을 거치게 된다.
그러나 요청시 인수를 받아 특별한 조건에 맞는 데이터를 응답하는 것도 아니고, 크롤링으로 인해 데이터가 변하지 않는 이상 항상 같은 데이터를 응답하게 된다.
그러므로 이 응답 데이터를 저장해두고, 요청이 들어오면 저장해둔 데이터를 즉시 응답해주면 될거라고 생각했다.
수정 후 코드
DataService.java
private static WholeDataFindResponse wholeDataFindResponse = null;
public WholeDataFindResponse getData() {
return wholeDataFindResponse;
}
@PostConstruct
public void setData() {
wholeDataFindResponse = new WholeDataFindResponse(getSurvivorData(), getKillerData());
}
public SurvivorFindResponse getSurvivorData() {
/*...*/
}
public KillerFindResponse getKillerData() {
/*...*/
}
응답 데이터를 저장할 변수 wholeDataFindResponse를 static으로 선언해두고, setData 메서드를 만들어 wholeDataFindResponse에 데이터를 가공해 저장한다.
setData 메서드는 PostConstruct 어노테이션을 설정하여, 애플리케이션 시작시 자동으로 실행된다.
기존의 getData 함수는 저장된 wholeDataFindResponse를 그대로 반환한다.
DataCrawler.java
@Async
@Transactional
public void runCrawlerAll() {
/*...*/
dataService.setData();
}
크롤러의 마지막 부분에서도 setData를 호출하여, 데이터 변동시 응답용 데이터를 다시 가공하여 저장하도록 한다.
👍 개선 결과
서버 응답시간이 152.44ms로 확연히 줄어든 모습이다😄
콘텐츠 다운로드 속도는.. 프론트엔드 담당 친구와 천천히 고려해보는걸로..