[TIL] Week3 동작 구현 (with 크롬 무한 alert)

샤이니·2023년 4월 11일
0

learned.log

목록 보기
19/46

오늘의 나는 무엇을 잘했을까?

  1. Week3 동작 구현을 완성 후 PR 생성
    • 선택 요구사항인 eye toggle을 구현하였다. 제리의 기술 공유를 바탕으로 eye icon click 시 focusout 되는 현상을 해결하였다.
      • event를 click이 아닌 pointerdown으로 변경, e.preventdefault 선언하면 된다.
      • pointerdown or mousedown으로 변경하는 이유는 전체 'click' event가 중단도

오늘의 나는 무엇을 배웠을까?

[1] click 대신 pointerdown이나 mousedown으로 변경 후e.preventDefault()하면 왜 focusout이 안될까?

  • e.preventDefault()
    • html 에서 a 태그나 submit 태그는 연속된 고유의 동작이 있다. 페이지를 이동시킨다거나 form 안에 있는 input 등을 전송한다던가 그러한 동작이 있는데 e.preventDefault 는 그 동작을 중단시킨다.
      • 연속된 고유의 동작에는 focus 이동도 포함되어 있다.
  • clickpointerdown or mousedown의 차이
    • click 이벤트는 마우스왼쪽 클릭만을 인식한다. 또한 요소가 눌렸다가 떨어지는 순간 발생한다.
    • pointerdown 이벤트는 마우스, 펜, touch에 의해서도 발생하며 마우스의 경우 왼쪽, 가운데, 오른쪽 클릭 전부를 인식한다. 요소가 눌리는 순간 발생한다.
    • input box에 focus가 되어있는 상태에서 input 이외의 요소에 이벤트가 발생할 경우
      • click : preventDefault 상태에서 focus가 input에서 넘어간다.
      • pointerdwon: preventDefault 상태에서 focus가 넘어가지 않는다.
      • 원인은 이벤트 발생의 시점!
        마우스 눌림 -> pointerdown 이벤트 -> focusout -> focusin -> 마우스가 올라감 -> click 이벤트
        e.predefault의 경우 이벤트가 발생하면 뒤따라오는 focusout, focusint이라는 브라우저 기본 동작을 차단하는데click이벤트는 focusout과 focusin이 발생한 뒤 발생함으로 차단을 할 수 없다.

[2] setTimeOut() 메소드의 동작

아래의 코드의 실행 순서

let num = 1; //a번

setTimeout(() => {
  num = 2; //b번
}, 0);

num = 3; //c번

console.log(num);

setTimeout 함수

특정 함수의 실행을 원하는 시간만큼 미루기 위해 사용된다. 첫번째 파라미터에 있는 콜백의 실행을 두번째 파라미터에 적힌 숫자 ms 뒤로 미룬다.

  • 콜백이 실행되는 조건은 설정한 ms 만큼의 시간이 경과했을 때이다.

타이머 식별자를 반환합니다. 하지만 타이머 사용 시, 정확한 지연 시간을 보장해주지는 않는다!

코드에서는 지연 시간을 0으로 뒀는데, 기대한대로 동작하지는 않았다.

🙋‍ 내가 기대한 것은 지연시간이 0이기 때문에 c번보다 먼저 실행되는 것을 기대했다.

이때 고려해야할 점은 브라우저에서 JavaScript 코드가 실행되는 과정을 알아야한다.

브라우저의 JavaScript 코드 실행 과정

먼저! 자바스크립트는 싱글스레드 언어이다.

하나의 싱글 콜 스택만을 가지고 있다는 뜻이며, 자바스크립트의 엔진은 한 번에 하나의 태스크만 실행할 수 있다는 뜻이다.

호출 스택 (Call Stack)

호출 스택에 저장되는 각 항목을 실행 맥락(execution context)이라고 부릅니다. 실행 맥락에는 아래와 같은 정보들이 저장된다.

  • 함수 내부에서 사용되는 변수
  • 스코프 체인
  • this가 가리키는 객체

브라우저가 JavaScript 코드를 실행시킬 때, 호출 스택을 다음과 같이 조작한다.

  • 스크립트를 불러올 때, 전역 실행 맥락(global execution context)을 호출 스택에 추가한다.
  • 함수가 호출되면, 해당 호출에 대한 실행 맥락을 생성해서 호출 스택에 추가(push)한다.
  • 변수에 대입이 일어나면, 호출 스택에 저장되어 있는 변수의 내용을 변경한다.
  • 함수의 실행이 끝나면, 결과값을 반환하고 호출 스택 가장 위에 있는 실행 맥락을 제거(pop)한다.
  • 스크립트의 실행이 모두 끝나면, 전역 실행 맥락을 호출 스택에서 제거(pop)한다.

웹 브라우저는 호출 스택에 실행 맥락이 존재하는 동안, 즉 실행 중인 함수가 존재하는 동안에는 먹통이 되어 버린다

작업 큐 (Task Queue)

브라우저에서는 다음과 같은 절차를 통해 오래 기다려야 하는 일을 처리할 수 있다.

  • 기다려야 하는 일을 JavaScript 엔진에서 직접 처리하는 것이 아니라 API를 통해 브라우저에 위임한다. 이 때, 일이 끝나면 실행시킬 콜백을 같이 등록한다.
  • 위임된 일이 끝나면, 그 결과와 콜백을 작업 큐(task queue)에 추가한다.
  • 브라우저는 호출 스택이 비워질 때마다 작업 큐에서 가장 오래된 작업을 꺼내와서 해당 작업에 대한 콜백을 실행시킨다. 브라우저는 이 과정을 끊임없이 반복하는데, 이를 이벤트 루프(event loop)라고 부른다.

JavaScript 코드를 작성할 때에는, 호출 스택과 작업 큐의 성질을 반드시 염두에 두어야 한다.

  • 각 작업은 작업 큐에 쌓인 순서대로 실행된다.
  • 이미 작업 큐에 작업이 쌓여있다면, 뒤늦게 추가된 작업은 앞서 추가된 작업이 모두 실행된 다음에, 즉 호출 스택이 비워진 다음에야 실행된다.
  • 호출 스택이 비워지지 않는다면, 작업 큐에 쌓여있는 작업을 처리할 수 없다.
  • 각 작업 사이에 브라우저는 화면을 새로 그릴 수 있다. 즉, 호출 스택이 비워지지 않는다면 브라우저는 화면을 새로 그릴 수 없다.

그래서 코드는?

지연시간을 0으로 주면, 브라우저는 setTimeout에 넘겨진 콜백을 바로 실행하는 것이 아니라 그 콜백을 작업 큐에 등록한다. 호출 스택이 비워지면, 그제서야 작업 큐에 들어있는 콜백을 가져와서 실행시킨다. 이 때문에 num = 2가 나중에 실행되는 것이다.

let num = 1; //a번

setTimeout(() => {
  num = 2; //b번, 작업 큐에 콜백이 추가됨
}, 0);

num = 3; //c번

console.log(num); //d번

따라서 실행 순서는, a번 → c번 → d번 → b번 순서이다.

그러니 출력되는 값은 3이다. 하지만 이후 console.log(num)을 해보면 num에 2가 할당되어있음을 알 수 있다.

관련한 참고할 코드!

const s = new Date().getSeconds(); 
setTimeout(function() { 
	// "2"를 출력, 즉 0.5초가 지난 후 즉시 실행된 것이 아니라는 것
	console.log((new Date().getSeconds() - s) + "초 후 실행됨"); }, 500)

while (true) {
 if (new Date().getSeconds() - s >= 2) { 
		console.log("좋아요, 2초간 반복했습니다.") break; } 
}

오늘의 나는 어떤 어려움이 있었을까?

eventhandler 에서 무한 alert 발생

Week3 미션의 signup 기능 구현 시,

  • 이메일 input에서 focus out 일 때, 값이 유효하지 않으면 alert 경고문 생성
  • 비밀번호 input에서 focus out일 때 값이 유효하지 않으면 alert 경고문이 생성되는 기능

을 구현하는 요구사항이 있다. 이때 focus를 이메일 input에 뒀다가 바로 비밀번호 input을 클릭할 경우

이메일 input focusout비밀번호 input focusin (add focusout eventlistener)alert와 동시에비밀번호 input focusoutalert와 동시에 ..

이 과정이 무한 루프로 발생하는 이슈가 생겼다.
+추가적으로 Enter를 사용한 submit을 했을 때도 무한 루프가 발생!!ㅠㅠ

이를 해결하기 위해서 ChatGPT에게 alert로 인한 focusout과 디바이스의 click으로 인한 focusout의 차이를 알려달라했더니 그 결과,

하지만 sourceCapability 프로퍼티를 처음봤고.. 이를 사용하는 것은 일반적이지 않은 것같다는 결론이 나왔다. 아직 해결 못함..

내일의 나는 무엇을 해야할까?

  • 알고리즘 2문제
  • 모던 자바스크립트 완강

0개의 댓글