본문 바로가기

JavaScript/공부공부

[JS / jQuery] 동적 요소 이벤트 바인딩

 

append() 를 사용해 동적으로 생성한 요소에 스크롤 감지 이벤트가 적용이 안됨. 

$target.append($ulElement)

// 생략

$('.scroll_ul').on('scroll', function () {
    console.log('스크롤 위치:', $(this).scrollTop());
});

 

새로운 요소 append이후
아래처럼 실행해주니 해당 요소를 잡아 이벤트가 실행된다.

$target.append($ulElement)

// 생략

setTimeout(() => {
    $('.scroll_ul').on('scroll', function () {
        console.log('스크롤 위치:', $(this).scrollTop());
    });
}, 0);

 

자바스크립트는 단일 스레드 기반으로 아래의 순서로 코드가 처리되기 때문. 

  1. 동기(Synchronous) 코드 → 위에서 아래로 한 줄씩 실행
  2. 비동기(Asynchronous) 코드는 따로 대기 → 이벤트 루프가 다음 타이밍에 실행

 

$target.append($ulElement)		// 동기 실행

// 생략

$('.scroll_ul').on('scroll', function () {
    console.log('스크롤 위치:', $(this).scrollTop());
});

DOM을 조작했지만, 그 변경이 브라우저에 반영되기 전에 .on('scroll', ...)이 실행

 .append()를 하더라도 자바스크립트는 브라우저에 DOM 변경 요청만 할 뿐,
브라우저가 실제로 DOM을 렌더링하는 시점은 자바스크립트 실행이 끝난 뒤!!

비동기 코드인 setTimeout(..., 0)은 현재 실행 컨텍스트가 모두 비워진 이후 실행되기 때문에
브라우저가 DOM 업데이트 및 렌더링을 완료한 이후 호출된다.

$target.append($ulElement)

// 생략

// DOM 완성된 다음 실행 보장
setTimeout(() => {
    $('.scroll_ul').on('scroll', function () {
        console.log('스크롤 위치:', $(this).scrollTop());
    });
}, 0);

따라서, 현재 실행 중인 모든 동기 코드가 끝난 뒤 실행되기 때문에 
추가된 대상 요소를 정상적으로 인식하고 이벤트 바인딩이 이루어진다.


(참고)

setTimeout(fn, 0) 
가능한 한 빠르게, 현재 작업(콜스택) 이후 실행.

setTimeout(fn, 1)
최소 1ms 이후 실행. ( 실제론 보통 4ms 이상 )

setTimeout(fn, 1000)
1000ms(1초) 후에 실행.


(출력 예시)

console.log("A");

setTimeout(() => {
  console.log("B");
}, ms);

console.log("C");

[ 실행순서 ]

  1. "A" 출력 (동기)
  2. setTimeout(..., ms) → 브라우저에 "ms 뒤 실행해줘" 요청 → task queue에 등록 ( ms 이후 등록 )
  3. "C" 출력 (동기)
  4. 콜 스택이 비면 이벤트 루프가 task queue에서 console.log("B")를 꺼내 실행 (콜 스택에 넣음)
  5. "B" 출력 

'JavaScript > 공부공부' 카테고리의 다른 글

[JS / jQuery] 커스텀 select-option 디자인  (0) 2025.10.18
[JS] URL 객체  (0) 2025.07.15
[JS] event.currentTarget vs event.target  (0) 2025.02.27
[JS] Form & Checkbox  (2) 2024.11.06
[JS] Property vs Attribute  (0) 2024.11.06