티스토리 뷰
사이드 프로젝트 중 상세에서 목록으로 이동할 때에 들어왔던 상태의 화면을 표시하려 했다.
1. KeepAlive 방식(시도)
// app.vue - NuxtPage에 keepalive 활성화
<NuxtPage :keepalive="true" />
// 페이지 파일 - 캐시할 페이지에 keepalive: true
definePageMeta({ layout: 'member', keepalive: true })
KeepAlive는 Vue와 Nuxt에서 컴포넌트의 상태를 메모리에 박제(캐싱) 해두는 기능이다.
사용자가 A페이지에서 B페이지로 이동하면, A컴포넌트는 파괴(Unmount)되고 메모리에서 사라진다.
하지만 KeepAlive로 감싸주면 컴포넌트가 파괴되지 않고 '비활성화(Deactivated)' 상태로 메모리에서 머물다가, 다시 돌아왔을 때 이전의 데이터, 입력값, 스크롤 위치 등을 그대로 보여준다.
KeepAlive를 사용하면 컴포넌트가 다시 나타날 때 onMounted가 호출되지 않는다. 대신 전용 훅을 사용해야 합니다.
- onActivated: 캐시된 컴포넌트가 화면에 다시 나타날 때 실행됩니다. (데이터 갱신 로직을 여기에 넣습니다.)
- onDeactivated: 다른 페이지로 이동하여 컴포넌트가 숨겨질 때 실행됩니다.
AI 왈:
KeepAlive는 "사용자가 입력하던 폼 내용이 많거나, 리스트 렌더링 비용이 너무 커서 0.1초의 딜레이도 없어야 할 때" 사용하면 좋습니다.
😭 캐시방식으로 선택
1. 목록(/member/feedback/board, layout: member) → 상세(/common/feedback/detail/123, layout: default) 이동 시 레이아웃이 바뀐다.
2. 레이아웃을 바꿔 시도하려했으나, 해당 목록은 main의 성격을 띄고있어 상세와의 레이아웃이 같지 않다.
3. 만약 레이아웃을 바꿔서(후에 레이아웃 안에 추가코드가 발생확률 큼) 시도한다면 괜찮을지 시도해봣으나,
이미 작업이 완료된 페이지인 터라, KeepAlive를 적용하려 보니 SSR 컴포넌트 생명주기와 엉켜서 제대로 작동되지 않았다.
원인을 파악하는데에 시간 소요가 클 것이라 판단, Vue에서 권장하는 캐시방식으로 작업을 진행했다.
1. 목록에서 돌아온 후 필요한 캐시 값들을 state로 선언해준다.
const cache = useState<{
list: FeedbackPost[]
ranking: FeedbackRanking | null
category: string
page: number
hasMore: boolean
scrollY: number
} | null>('feedback-board-cache', () => null)
2. 상세 이동 시 캐시 값을 담아준다. 참고로 현재의 scrollY와 현재 page는 페이징을 위해 필수가 된다.
// 상세로 이동 시 → 현재 상태 저장
const goToDetail = (id: number) => {
cache.value = {
list: feedbackList.value,
ranking: ranking.value,
category: activeCategory.value,
page: currentPage.value,
hasMore: hasMore.value,
scrollY: window.scrollY,
}
router.push(`/detail/${id}`)
}
3. 상세에서 router.back()으로 돌아올 시에 마운트에서
캐시 값을 확인하는 코드를 담아서 복원해준다.
// 목록 마운트 시 → 캐시 있으면 복원, 없으면 fetch
onMounted(async () => {
if (cache.value && cache.value.list.length > 0) {
// 캐시에서 복원
feedbackList.value = cache.value.list
ranking.value = cache.value.ranking
activeCategory.value = cache.value.category
currentPage.value = cache.value.page
hasMore.value = cache.value.hasMore
const savedScrollY = cache.value.scrollY
cache.value = null // 사용 후 캐시 초기화
isLoading.value = false
nextTick(() => {
setupObserver()
setTimeout(() => window.scrollTo(0, savedScrollY), 50)
})
return
}
// 캐시 없음 → 새로 API 호출
isLoading.value = true
await fetchData()
isLoading.value = false
})
✍️ 흐름정리
목록 (최초 진입)
→ cache === null → API fetch → 렌더링
목록 → 상세 이동
→ cache에 {list, scrollY: 500, ...} 저장
→ 컴포넌트 파괴 (but useState는 살아있음)
상세 → 뒤로가기
→ 목록 마운트 → cache !== null
→ 캐시에서 복원 (API 안 부름)
→ scrollTo(500) → 원래 위치
목록 (탭 메뉴에서 재진입)
→ cache === null (이전에 초기화됨) → API fetch
☝️ useState
useState와 ref의 차이점은 ref는 컴포넌트 내부에서만 사용되며, useStatesms 전역에서 사용된다. 따라서 페이지 이동시에도 유지가 된다. useStete(키, ()=>초기값)
'prod > Nuxt.js' 카테고리의 다른 글
| Nuxt 사용기 (1) (1) | 2025.03.17 |
|---|
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- exception
- 향해플러스백엔드
- 스프링부트
- hypertexttransferprotocol
- 리터럴
- 백엔드 개발자 역량
- SpringBoot
- 인터셉터
- Java
- 스프링공부
- 향해플러스
- React
- HTTP
- react실행
- reject
- rejectValue
- 예외처리
- BindingResult
- 로그인
- JPA
- 향해99
- filter
- 항해99
- 백엔드 개발자 공부
- jpa api
- 항해플러스
- thymleaf
- Intercepter
- 컨트
- ArgumentResolver
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
글 보관함
