본문 바로가기
study/geultto

백엔드 개발자의 프론트/모바일 개발 도전기 - Vue.js의 $nextTick 알아보기

by 고기만두(개발자) 2025. 3. 1. 14:24
728x90
반응형

Intro. 상황 설명

백엔드를 주력으로 개발하고 있지만,

최근 팀내 인원 변동 및 업무분장 변경에 따라 갑작스럽게 모바일앱을 인수받게 되었다.

해당 앱은 vue.js + javascript + 자체 프레임워크가 짬뽕되어 있으며

vue.js와 javascript에 대한 선수지식을 필요로 한다.

분명 회사에 모바일 개발을 전담하는 부서가 별도로 있음에도 불구하고,

이상하게도 해당 앱은 메뉴기능별로 원래 시스템 운영 부서들에 조각조각 관리 책임이 흩어져있는 상태.

사혼의 구슬
사혼의 구슬이야 뭐야

 

해당 앱 소스를 분석하며, 기존 웹 레거시 시스템의 사용빈도가 높은 조회성 화면 하나를

모바일 버전으로 옮기는 작업을 진행해 보았다.

권한 설정이나, 다른 불필요한 기능은 일단 모두 걷어내고 조회 기능만 따서 기존 소스 레퍼런스를 보며 클론코딩했고

장기 롤아웃 예정인 이전 담당자 외에는 vue.js 개발을 해본 사람이 거의 없는 팀 상황에 맞게

개발 후 관련 매뉴얼을 팀원 공유용으로 업데이트 했다.

반응형

라이브 오픈한 건 아니지만 맨땅에 헤딩 경험을 생생히 공유하고 (자랑하고).... 싶은데

전체 소스 및 산출물 공유가 불가능하여 특징적인 개념 하나를 잡아서 글을 작성해보기로 했다.


Vue.js의 $nextTick 개념과 역할  / async await랑은 뭐가 다르지?

 

1. $nextTick의 기본 개념

Vue.js에서 $nextTick()은 DOM 업데이트가 완료된 후 실행될 콜백을 예약하는 역할을 한다.

Vue의 반응형 시스템은 데이터 변경을 감지하면 비동기적으로 DOM을 업데이트한다.

이 때 $nextTick()을 사용하면 변경된 데이터가 실제로 DOM에 반영된 후 특정 로직을 실행할 수 있다.

2. $nextTick()의 동작 방식
$nextTick() 내부의 콜백 함수는 Vue가 데이터 변경을 감지하고, 가상 DOM을 다시 렌더링한 후 실행된다.
Promise와 함께 동작하며, 마이크로태스크(microtask) 큐에 등록되어 다음 이벤트 루프에서 실행된다.
이로 인해, $nextTick() 내에서 DOM을 조작하면 가장 최신 상태의 DOM을 반영한 후 실행되는 코드를 작성할 수 있다.

 

*Promise란? JavaScript에서 비동기 작업(예: 서버 요청, 파일 읽기 등)을 처리하는 객체.
보통 JavaScript는 한 줄씩 코드가 실행되지만,

버에서 데이터를 가져오는 작업처럼 시간이 오래 걸리는 작업이 있으면, 그걸 기다리지 않고 다음 코드를 실행한다.
그러면 작업이 끝났을 때 다시 결과를 처리할 수 있어야 하는데, 이때 Promise가 필요하다.

 

*Microtask란? JavaScript의 이벤트 루프(Event Loop)에서 실행 순서를 결정하는 큐(queue) 중 하나.
그럼 큐가 뭔지 궁금해지는데, 이벤트 루프의 작업 큐(Task Queue) 를 알아야 한다.

JavaScript에는 비동기 코드들이 실행되는 우선순위가 다르다.
이런 비동기 코드를 처리하는 두 가지 큐:
MacroTask Queue (일반 Task Queue) : setTimeout, setInterval, setImmediate 같은 타이머 기반의 작업
MicroTask Queue (우선 실행!) : Promise.then(), MutationObserver, queueMicrotask()

 

this.$nextTick(function(){
	this.isSearch = true
	this.List[this.listName] = [] //리스트 초기화
	this.$CommUtils.setPageInit({
    	name : this.pageName,
        listName : this.listName,
        row_cnt : this.rowCnt} ) //페이징초기화
	this.$refs.pagingLoading.stateChanger.reset()
	})
),
async fn_Search() {
	//조회 기능- 뒷부분 생략
}

 

3. 이 코드에서 $nextTick()이 하는 역할
this.isSearch = true 및 리스트 초기화를 수행하면 데이터 변경이 발생한다.
Vue는 데이터 변경을 감지하고 DOM 업데이트를 예약한다.
그래서 $nextTick() 내부 코드가 실행될 시점에는 DOM 업데이트가 완료된 상태다.
따라서 this.$refs.pagingLoading.stateChanger.reset()를 호출하면, 최신 DOM 상태를 보장한다.
즉, DOM이 반영되지 않은 상태에서 setPageInit() 또는 reset()을 호출하면 원하는 동작이 안될 수도 있기 때문에,

DOM 업데이트가 완료된 후 안전하게 실행하려고 $nextTick()을 사용하였다고 보인다.

 

물론 이번 프로덕트는 단순 조회만 구현하여 앱내에서 Update/Insert/Delete가 수행될 가능성은 많지 않지만,

레거시 시스템과 같은 백엔드 코드를 사용하므로 그쪽에서 입력을 진행한다면 데이터가 변경될 가능성이 있다.

백엔드단에서도 그런 충돌에 대한 익셉션 대비는 되어있지만,

vue나름대로도 그러한 충돌을 나름대로 막아보기 위해 노력한 것이라고 보인다.

728x90

4. 어? 나 다른 언어에서 async/await 를 본 적 있는데, 그거와 $nextTick()은 어떤 차이점이 있어?

결국 $nextTick()은 Vue의 DOM 업데이트가 끝난 후 실행할 콜백을 예약하는 역할을 한다.
async/await는 비동기 함수 내에서 Promise의 완료를 기다리는 역할을 한다.
따라서 $nextTick()과 await를 같이 사용하면 Vue의 렌더링이 끝난 후에 비동기 처리를 기다리는 방식으로 동작할 수 있다.

 

async fn_Search() {
    this.loading = true;
    
    await this.$nextTick(); // Vue가 DOM 업데이트 후 실행 보장
    console.log("DOM 업데이트 완료");

    const result = await fetchData(); // 비동기 데이터 가져오기
    this.list = result;
    
    this.loading = false;
}

위 코드에서 await this.$nextTick();을 사용하면,
Vue의 데이터 변경으로 인해 DOM이 반영된 후에 비동기 함수를 실행하게 된다.

 

5. $nextTick()을 사용하는 대표적인 상황

1) DOM 변경 후 특정 동작을 해야할 때

this.showModal = true;
this.$nextTick(() => {
    this.$refs.modal.focus(); // 모달 창이 열린 후 포커스 설정
});

 

2) 애니메이션 및 UI업데이트 직후 실행

this.isLoading = true;
this.$nextTick(() => {
    document.getElementById("spinner").classList.add("visible");
});

 

3) v-for을 사용한 리스트 업데이트 후 실행

this.items.push(newItem);
this.$nextTick(() => {
    console.log("아이템 추가 후 DOM 업데이트 완료");
});

 


✅ 정리하면
$nextTick()은 Vue가 데이터 변경을 감지하고 DOM을 업데이트한 후 실행되는 콜백을 예약하는 함수이다.
Vue의 렌더링이 비동기적으로 이루어지므로, DOM 변경 직후 실행해야 할 코드가 있다면 $nextTick()을 사용하면 된다.
async/await과는 역할이 다르며, 필요하면 await this.$nextTick(); 형태로 함께 사용할 수도 있다.
$refs를 통해 특정 DOM 요소를 조작해야 할 때 DOM 업데이트가 완료된 후 실행하는 데 유용하다.


TODO : 

업무 비중이 높진 않지만, 한번 착수하면 백지상태에서 너무 오래 시간이 걸릴 것 같아 튜토리얼을 만들어보기 잘했다.

나 하나 고생해서 뒤에 올 사람들이 편해지면 그것도 장기적 관점에선 팀에 플러스.

업무용 프로덕트가 아니더라도 실제로 UID 실행하는 폼 형태의 미니 프로젝트 구현으로 좀 더 딥다이브 예정.

728x90
반응형