티스토리 뷰
대용량 데이터를 렌더링해야 하는 상황에서, 프론트엔드 측면에서 성능을 향상시킬 수 있는 방법을 고민해 보았습니다. 이 글에서는 제가 적용한 성능 최적화 기법들과 그에 따른 코드 예시를 공유하고자 합니다.
1. 지연 로딩(Lazy Loading)과 조건부 렌더링 활용
v-if를 사용한 컴포넌트 렌더링 제어
- v-if를 사용하여 컴포넌트가 필요한 시점에만 렌더링되도록 제어합니다.
- 초기 로딩 시에는 최소한의 요소만 렌더링되므로 성능이 향상됩니다.
<!-- ParentComponent.vue -->
<template>
<div>
<div
v-for="item in filteredItems"
:key="item.id"
class="card"
>
<CardItem :data="item" />
</div>
</div>
</template>
<script>
export default {
props: ['items'],
computed: {
filteredItems() {
return this.items; // 검색어나 필터링 조건에 따라 데이터 필터링
}
}
};
</script>
<!-- CardItem.vue -->
<template>
<div class="card-item">
<div @click="toggle">
<h3>{{ data.title }}</h3>
</div>
<div v-if="isExpanded">
<!-- 상세 정보 컴포넌트 -->
<DetailInfo :info="data.info" />
<div @click="toggleGrid">
<span>추가 정보 보기</span>
</div>
<div v-if="isGridExpanded">
<!-- 그리드 뷰 컴포넌트 -->
<GridView :params="data.params" />
</div>
</div>
</div>
</template>
<script>
export default {
props: ['data'],
data() {
return {
isExpanded: false,
isGridExpanded: false
};
},
methods: {
toggle() {
this.isExpanded = !this.isExpanded;
},
toggleGrid() {
this.isGridExpanded = !this.isGridExpanded;
}
}
};
</script>
v-once를 사용한 정적 콘텐츠 렌더링
변경되지 않는 정적 콘텐츠에 v-once 디렉티브를 사용하여 한 번만 렌더링하고 재활용합니다.
- 정적 콘텐츠는 한 번만 렌더링되므로 불필요한 재렌더링을 방지합니다.
<div v-once>
<!-- 변경되지 않는 정적 콘텐츠 -->
</div>
2. 데이터 관리 최적화
불필요한 반응성 제거
반응성이 필요 없는 데이터는 Object.freeze()를 사용하여 반응성 시스템에서 제외합니다.
- 대용량 데이터를 반응형으로 관리하면 오버헤드가 발생할 수 있으므로, 변경되지 않는 데이터는 반응성에서 제외합니다.
<script>
export default {
data() {
return {
items: Object.freeze(this.initialItems)
};
},
props: ['initialItems']
};
</script>
3. 렌더링 작업 분할
Chunk Rendering을 통한 렌더링 작업 분할
렌더링 작업을 작은 단위로 나누어 순차적으로 수행합니다.
- setTimeout과 $nextTick을 활용하여 렌더링 작업을 비동기로 처리합니다.
- 한 번에 모든 데이터를 렌더링하지 않고, 작은 덩어리로 나누어 브라우저의 메인 스레드가 막히는 것을 방지합니다.
<script>
export default {
data() {
return {
items: Object.freeze(this.initialItems)
};
},
props: ['initialItems']
};
</script>
4. 컴퓨티드 프로퍼티와 캐싱 활용
컴퓨티드 프로퍼티로 효율적인 데이터 필터링
검색어에 따라 데이터를 필터링할 때 컴퓨티드 프로퍼티를 사용하여 성능을 향상시킵니다.
- 컴퓨티드 프로퍼티는 종속된 데이터가 변경될 때만 재계산되므로 불필요한 연산을 줄일 수 있습니다.
<script>
export default {
data() {
return {
items: Object.freeze(this.initialItems)
};
},
props: ['initialItems']
};
</script>
5. 이벤트 핸들러 및 데이터 바인딩 최적화
이벤트 위임을 통한 이벤트 핸들러 최소화
각 요소에 개별적으로 이벤트 핸들러를 등록하지 않고 상위 요소에서 이벤트를 관리합니다.
- 이벤트 리스너의 수를 줄여 메모리 사용량과 이벤트 처리 오버헤드를 감소시킵니다.
<!-- ParentComponent.vue -->
<template>
<div @click="handleClick">
<div
v-for="item in filteredItems"
:key="item.id"
class="card"
:data-id="item.id"
>
<h3>{{ item.title }}</h3>
</div>
</div>
</template>
<script>
export default {
methods: {
handleClick(event) {
const id = event.target.closest('.card').dataset.id;
if (id) {
// 해당 아이템에 대한 로직 처리
}
}
}
};
</script>
데이터 바인딩 간소화
불필요한 양방향 바인딩을 피하고 단방향 바인딩을 사용합니다.
- 양방향 바인딩(v-model)은 편리하지만, 필요한 경우에만 사용하여 반응성으로 인한 오버헤드를 줄입니다.
<!-- 양방향 바인딩 지양 -->
<input :value="value" @input="updateValue" />
6. 브라우저 개발자 도구를 활용한 성능 분석
Performance 탭을 사용한 성능 프로파일링
- 성능 병목 지점을 정확히 파악하여 최적화가 필요한 부분에 집중할 수 있습니다.
- 녹화 시작: 브라우저 개발자 도구의 Performance 탭에서 녹화 버튼 클릭
- 사용자 행동 수행: 페이지 로딩, 검색 기능 사용 등
- 녹화 종료: 녹화 버튼 다시 클릭
- 분석: 타임라인을 확인하여 렌더링 시간, 스크립트 실행 시간 등 분석
결론
프론트엔드 성능을 최적화하기 위해 여러 가지 방법을 시도해 보았습니다. 그 결과, 초기 로딩 시간과 검색 시 재렌더링으로 인한 성능 저하 문제를 개선할 수 있었습니다.
- 지연 로딩과 조건부 렌더링으로 초기 렌더링 부담 감소
- 반응성 데이터 관리 최적화로 불필요한 데이터 추적 제거
- 렌더링 작업 분할로 메인 스레드의 부담 완화
- 컴퓨티드 프로퍼티 활용으로 재계산 최소화
- 이벤트 핸들러 및 데이터 바인딩 최적화로 오버헤드 감소
- 성능 분석 도구 활용으로 정확한 병목 지점 파악
'FRONTEND' 카테고리의 다른 글
모바일 앱처럼 보이는 웹 만들기! (0) | 2025.02.15 |
---|---|
내 친구 TypeScript를 알아보자 (3) | 2025.01.18 |
프론트엔드 개발자는 언제까지 변화에 대응해야할까요? (0) | 2024.04.14 |
프론트엔드 개발자의 클린 코드 (2) | 2024.03.31 |
vue.js 2 에서는 재사용을 어떻게 할까요? (1) | 2024.03.17 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 단독홀
- 결혼식장
- 구로결혼식장
- 코파일럿 사용 방법
- 웨딩후기
- 단독웨딩홀
- Github Copilot
- 코파일럿 꿀팁
- 2023년 회고
- 20대회고
- tip of copilot
- 개발자회고
- 코파일럿
- 2023회고
- 지타워컨벤션
- 본식후기
- How to use Copilot
- 회고
- 29살회고
- 지블리안
- Github universe 2023
- github
- Tips for using copilot
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
글 보관함