프론트엔드 개발자로 일하기

우리 서비스의 웹 성능을 최적화하기

프론트루나 2024. 9. 23. 09:16
반응형

컨셉

기존의 프레임워크 구조는 유지하되,
내부적으로 성능 개선이 가능한 요소를 리팩토링 하여 성능 최적화를 진행.


소스 상태

  • 동일한 페이지에서 파라미터만 동적으로 받아와서 같은 페이지를 사용
  • 이전에 저장된 캐시가 없는 최초의 상태
  • 동일한 조건에서, 파라미터를 변경하면서 크롬 개발자도구 > Lighthouse > Performance 지표 확인
  • 최초 로드 이후에 발생하는 이벤트 발생, 데이터 변경 등의 통합적인 성능점수가 아닌, 페이지를 최초로 로드할 때의 최적화 점수를 확인

concept

기존의 프레임워크 구조는 유지하되, 내부적으로 성능 개선이 가능한 요소를 리팩토링 하여 성능 최적화를 진행.


report condition

  • 동일한 페이지(reservation.html)
  • 동일한 골프장코드(세라지오, 사우스링스)
  • 캐시, 메모리 캐시 모두 제거한 최초의 상태
  • 동일한 조건에서, 크롬 개발자도구 > Lighthouse > Performance 지표 확인
  • 최초 로드 이후에 발생하는 이벤트 발생, 데이터 변경 등의 통합적인 성능점수가 아닌, 페이지를 최초로 로드할 때의 최적화 점수를 확인

테스크탑 환경, performance 지표만을 확인

 


최초 웹성능 지표 리포트

중간과정 웹성능 지표 리포트(진행중)

 


patch History

#5 사용하지 않는 레거시 css 파일을 제거

  • 사용되지 않는 css 파일을 제거하여 화면 렌더링 시간을 축소

#4 캘린더 영역 template 조건 분기 처리 개선

  • 템플릿 을 렌더링 할때 조건 에 따라 분기 처리 하던 로직에서, 일자마다 문자열형태의 클래스 명을 리턴받도록 개선
// as-is
<span class="calendar-t-time" v-if="day.today">오늘</span>
<span class="calendar-t-time" v-if="day.today != true && day.dayText != null">{{day.dayText}}</span>
<span class="calendar-t-time" v-if="day.today != true && day.openYN && day.timeYCnt == 0 && day.dayText == null">마감</span>
<span class="calendar-t-time" v-if="day.today != true && day.openYN != true && day.timeYCnt == 0 && day.dayText == null">오픈전</span>
....
// to-be
calendarDayCondition(calDay) {
	let classStr = '';
	const cal = ' calendar-'
	const { timeYCnt, bookday, dayNum, isHoliday, day } = calDay;

	// 선택일 활성화
	classStr += ...

	// 디세이블
	classStr += ...

	// 휴일, 공휴일
	classStr += dayNum == 7 ? `${cal}satur` : '';
	classStr += dayNum == ...
	classStr += ...
	return classStr
},

#3 공통 함수 영역 확대

  • 폼데이터를 생성하여 데이터를 다음 페이지로 이동하는 메소드
  • 접속한 기기가 PC/Mobile 여부를 판단하는 메소드
// as-is
let objs;
objs = document.createElement('input');
objs.setAttribute('type', 'hidden');
...
form.submit();

// to-be
this.formDataHandler({
	iterableObj: {
		... ${폼데이터로 전송할 정보}
	},
})

let form = document.createElement('form');
for (let key of Object.keys(objs)) {
    const formItem = document.createElement('input');
    ...
    form.appendChild(formItem)
}
...
form.setAttribute('action', ${targetURL});
document.body.appendChild(form);
form.submit();

#2 데이터 선언부 개선

- 전역 변수 형태의 데이터 선언

(var data = { … 형태를 뷰 객체 내부 데이터 로 변경하고, 데이터 호출 선언부를 data…. → this.da.. 의 형태로 변경

  • 데이터 선언부가 아닌 메소드 내에서 선언된 타임리프 형태의 변수를 데이터 선언부로 이동
  • var 타입의 변수를 const/let 형태로 변경
  • 전역변수의 데이터가 오버라이딩되어 오류가 발생하는 상황을 개선
    var 형태의 변수는 언제 어디서나 가져와서 읽을 수 있다는 장점이 있지만,
    변경도 가능하기 때문에 서비스 운영상의 사이드이펙트 발생 우려가 있다.
  • 스코프를 고려하여 const, let 타입의 데이터 선언을 지향
  • 뷰 객체에서 데이터의 상태관리가 가능하도록 객체 내부에서의 데이터 선언으로 리팩토링이 필요하다.

 

// as-is 
var data = {
	isPC: [[${ dataA.isPC }]],
}

// 호출
data.isPC

// to-be
new Vue({
data() {
    return {
        isPC : [[${ dataA.isPC }]],
    }
}
})

// 사용
this.isPC

#1 jquery, vanillajs → vue method 통합

  • 뷰와 별개로 분류되어 있는 제이쿼리 함수를 vue 인스턴스 객체의 method로 이동
  • 기존의 전역으로 선언된 data 객체를 참조하여 데이터를 가져오는 방식에서‘객체 구조 분해 할당’ 코드 가독성을 높이고 메모리 개선
// as-is
if(data.isOpen) {
....
}

// to-be
const {isOpen} = data;
if(isOpen){
....
}

 

  • 불필요한 변수 할당 및 조건 처리 영역을 리팩토링
  • 재사용하지 않거나, 함수 내에서 리턴을 처리하기 위해 생성된 변수를 제거.
  • 반복되어 참조하는 데이터는 상단에 변수로 선언하여, 가독성 개선
funcA: function () {
	// as-is 데이터에서 직접 접근
    if (data.reservationType.responseYN == 'N') {
        isPayment = true;
      
    // to-be 변수에 할당하여 접근
    const resType = data.reservationType.responseYN;
    if (resType == 'N') {
        return true;
    }
}
반응형