메가바이트 스쿨 4주차 (1/6) Coding Test, Clone Coding, Javascript

정영찬·2023년 1월 6일
0
post-thumbnail

TIL

프로그래머스 코딩 테스트 14일차 문제 풀이 완료

  • 숫자 찾기
  • n의 배수 고르기
  • 자릿수 더하기
  • OX 퀴즈

eval()??

문자로 표현 된 JavaScript 코드를 실행하는 함수인데 OX퀴즈를 풀기위해서 해당 메서드를 사용했다.
근데 수식에서 =이 하나인 상태로 eval()를 호출해서 값을 출력하려고 했는데 오류가 나타나는 바람에 =을 더 추가해서 boolean 값을 얻어냈다.

이를 조사하는 과정에서 꽤나 다수의 부정적인 의견들이 많았다.

eval is evil... 왜?

  • eval()은 인자로 받은 코드를 caller의 권한으로 수행하는 위험한 함수이다
  • 악의적인 영향을 받았을 수 있는 문자열을 eval()로 실행한다면, 해당 웹페이지나 확장 프로그램의 권함으로 사용자의 기기에서 악의적인 코드를 수행하는 결과를 초래 (이게 제일 위험한 점인 것 같다...)
  • 제3자 코드가 eval()이 호출된 위치의 스코프를 볼 수 있으며, 이를 이용해 비슷한 함수인 Function으로는 실현할 수 없는 공격이 가능(밖에서 공격이 가능해진다)
  • 최신 JS 엔진에서 여러 코드 구조를 최적화하는 것과 달리 eval()은 JS 인터프리터를 사용해야 하기 때문에 다른 대안들보다 느림
  • 최신 자바스크립트 인터프리터는 코드를 기계 코드로 변환함. 즉, 변수명의 개념이 완전히 사라짐
  • eval()을 사용하면 브라우저는 기계 코드에 해당 변수가 있는지 확인하고 값을 대입하기 위해 길고 무거운 변수명 검색을 수행해야 함
  • eval()을 통해 자료형 변경 등 변수에 변화가 일어날 수 있으며, 브라우저는 이에 대응하기 위해 기계 코드를 재작성해야 함

출처 : https://velog.io/@modolee/javascript-eval-is-evil

문자열로 수식이 적혀있는 것을 입력받았을때, 수식에 대한 값을 받기 위해서 사용했지만, eval()메서드가 어떤 특징을 지녔는지 알수 있게된 계기가 되었다.... 무서운 녀석이었네..

javascript 강의 (이벤트 루프)

링크 : https://www.youtube.com/watch?v=8aGhZQkoFbQ

자바스크립트는 뭐에요?

싱글 스레드 논 블록킹 비동기 동적 언어입니다.....?

콜스택, 이벤트 푸르, 콜백 큐 , 이런저런 api를 보유했죠....

자바스크립트 런타임

위의 그림은 자바스크립트의 런타임을 간단하게 그림으로 나타낸 것이다.

  • heap: 메모리 할당 변수와 객체에 대한 메모리 할당

  • call stack : 코드가 실행될 때 쌓이는 호출 스택

그런데 v8 프로젝트를 클로닝해서 코드 베이스를 들여다 보면, setTimeout, DOM, HTTP 요청을 관리하는 코드를 찾아볼수가 없다...

엥 너 비동기 언어라면서?

위의 그림에서 좀더 디테일한 내용을 보여주면


(이미지 출처 : https://baeharam.github.io/posts/javascript/jshow-javascript-works/)

이렇게 생겼다. V8런타임과 브라우저가 제공해주는 웹 API가 존재한다.

call stack

one thread == one call stack == one thing at a time

자바스크립트는 싱글 스레드 프로그래밍 언어인데, 이것은 한번에 하나의 싱글 콜 스택만을 가지고 있다는 뜻이다.
하나의 프로그램은 동시에 하나의 코드만 실행할수 있다

데이터 스트럭처로 실행되는 순서를 기억하고 있다. 따라서 함수를 실행하려면 스택에 해당하는 함수를 집어넣게 되고, 함수에서 리턴이 일어나면 스택의 맨위에서 해당 함수를 꺼내서 사용하게 된다.

뭔소리여...

그냥 한번 눈으로 보자.


function multiply(a,b){
	return a * b;
}

function square(n){
	return multiply( n,n);
}

function pringSquare(n){
	var squared = square(n);
  	console.log(squared); // 16
}

숫자를 입력하면 그에 대한 제곰을 해서 값을 출력하는 내용이다.

실행하게 되면 진행되는 과정은 아래와 같다.

main() -> printSquare(n)호출 -> square(n) -> multiply(a,b)

main() <- console.log(sqaured) <- printSquare(n)리턴 <- square(n)리턴 <- multiply(a,b)리턴

이렇게 차근차근 하나씩 스택에 쌓이고 해당 함수의 내용을 실행하는 과정을 진행해 나가면서, 리턴값을 보낼때는 다시 스택에서 하나씩 제거하는 모습을 볼수 있다.

만약 같은 함수를 여러번 호출하게 되면 어떻게 될까?

function fu() {
  return fu()
}

fu()

함수를 호추라는 횟수가 정도를 넘어가게 되면 위와같은 오류를 보여주면서 종료시켜버린다.

블로킹(blocking)

정확한 정의는 존재하지 않지만, 간단하게 말하면 느리게 동작하는 코드이다.

console.log는 느린게 아니지만 while 루프안에서 수억번 돌아가면 느릴것이다.

네트워크 요청, 이미지 프로세싱 같이 느린 동작이 스택에 남아있는것을 보통 블로킹이라고 말한다.

var foo = $.getSync('.//foo.com');
var bar = $.getSync('.//bar.com');
var qux = $.getSync('//qux.com');

console.log(foo);
console.log(bar);
console.log(qux);

예를 들어서 이런 jquery 구문을 실행한다고 가정해보면 어떻게 될까? 3개의 console.log 모두 동기적으로 실행된다고 가정했을때 하나의 console.log가 끝날때까지 아무런 동작을 할수 없게 된다. 바꿔 말하면 콜스택에 어떤 것들이 남아있으면, 네트워크 요청이 콜스택을 막아버려서 브라우저는 다른일을 할수가 없다.

이런 현상을 막기 위해서 사용하는 것이 비동기 콜백이다.

비동기 콜백

어던 코드를 실행하면 결국 콜백을 받고 나중에 실행한다는 뜻

console.log('hi)
setTimeout(function() {
  console.log('there');
},5000)

console.log('jyc')

해당 코드를 실행하게 되면

이렇게 위아래의 console.log가 먼저 실행되고 5초뒤에 there가 나타난다. there를 출력하는 내용은 콜스택에 추가되지 않고 있다가. 5초뒤에 스택에 추가되고 결과를 출력해준다.

엥 왜지?

여기에서 이벤트 루프와 동시성이 나설 차례가 되는 것이다.

이벤트 루프 & 동시성

자바스크립트는 하나에 한가지 일만 한다... 이게 정말 맞는말일까?
그럼 다른 사이트들은 로딩하면서 다른 동작도 하는데.. 순엉터리 아냐?

자바스크립트는 다른 코드를 실행시키는 동한 Ajax 요청을 실행할수 없다. setTimeout도 마찬가지이고.
근데 우리가 이걸 동시에 할수 있는 이유는 바로

브라우저는 단순 런타임 이상을 의미하기 때문이다.

처음에도 언급했지만 자바스크립트 런타임은 한번에 하나만 할수 있다고 설명했다. 하지만 브라우저가 Web API와 같은 것들을 제공한다. 이들은 자바스크립트에서 호출할 수 있는 스레드를 효과적으로 지원하게 된다.
아까도 말했지만 자바스크립트 엔진 내부에는 비동기적 코드가 없다고 설명했었는데, setTimeout이 바로 그 web API중에 하나였던 것!

아래의 화면을 보자.

console.log(hi)가 콜스택에서 빠져나가 출력된다음 setTimeout콜에 넘어가게 되는데 setTimeout은 브라우저에서 제공하는 API로, setTimeout이 콜스택으로 들어가면 브라우저는 타이버를 실행시키고 카운트 다운을 시작한다.

그리고 이것이 setTimeout 호출 자체가 완료되었다는 의미이고, 콜스택에서 함수를 지울수 있게 된다. 이제 바로 다음에 작성된 console.log를 실행하게 된다.

자 이제 남은건 webapis에서 신나게 돌아가고있는 timer인데 만약 시간이 경과하게 되면 어떻게 될까?

시간이 경과하게 되면 태스크 큐로 넘어가게 된다. 이제 여기서 드는 의문은, '저기있는 이벤트 루프는 뭐하는 녀석이지?' 일텐데 이벤트 루프의 역할은 콜 스택과 태스크 큐를 주시하는 것이다.

  • 스택이 비어있으면, 큐의 첫번째 콜백을 스택에 쌓아서 효과적으로 실행할 수 있게 해준다
  • 현재 상황에서 스택이 비어있고, 태스크 큐에는 콜백이 하나가 있으니 스택으로 옮겨주게 되는 것이다.

이제 마지막으로는 cb 함수에 작성된 내용이 실행되는 것으로 마무리가 되는 것이다.

  • 비동기 함수가 실행되면 (setTimeout, ajax Request, 따위)는 web API이기 때문에 스택에서 바로 전달되어서 작업을 마친뒤 태스크 큐로 넘긴다.
  • 이벤트 루프는 콜스택과 태스크 큐를 주시하고 있다가 스택이 비었고, 태스크큐에 콜백이 존재하므로 스택으로 옮겨준다!

더 간단하게 말하면

비동기 함수가 스택에 추가되면 webAPI로 떠넘기고 다음 내용을 받는다.

라고 생각하면 이해가 편할 것이다.

setTime 함수의 진실

setTimeout 함수는 정말 지정한 시간이 지나면 실행될까?
아래의 코드는 어떻게 동작할까? 정말로 1초뒤에 주르륵 'hi'가 나타날까?

setTimeout(function timeout() {
    console.log('hi')
}, 1000);

setTimeout(function timeout() {
    console.log('hi')
}, 1000);

setTimeout(function timeout() {
    console.log('hi')
}, 1000);

setTimeout(function timeout() {
    console.log('hi')
}, 1000);

실상은 그렇지 않다.

시간이 다 지났음에도 불구하고 큐에서 대기하고 있다가 전부 다 콜백 큐로 이동하고 난 다음 하나씩 차례로 진행하는 모습니다.
이를 통해서 timeout이 실제로 정해진 시간과는 달리 제대로 작동하지 않을 수도 있고 다만 최소의 시간만을 지정할수 있다는 것을 알수 있다. (실제로 코드를 작성해서 실행해보면 거의 동시에 출력되는 것이라고 생각 될
만큼 빠르게 나온다.)
위의 이미지는 자바스크립트의 비동기 콜백이 어떤 과정을 통해서 출력되는지를 보여주기위한 프로그램이다.

링크: http://latentflip.com/loupe/?code=c2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coJ2hpJykKfSwgMTAwMCk7CgpzZXRUaW1lb3V0KGZ1bmN0aW9uIHRpbWVvdXQoKSB7CiAgICBjb25zb2xlLmxvZygnaGknKQp9LCAxMDAwKTsKCnNldFRpbWVvdXQoZnVuY3Rpb24gdGltZW91dCgpIHsKICAgIGNvbnNvbGUubG9nKCdoaScpCn0sIDEwMDApOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coJ2hpJykKfSwgMTAwMCk7Cg%3D%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D

코드를 작성하고 실행하면 어떤 과정을 거치는지 보여준다.

렌더링

브라우저는 우리가 자바스크립트로 하는 어떤 무언가로 인해서 제약을 받게된다.
브라우저는 기본적으로 화면을 매 16.6 밀리초, 즉 1초에 60프레임을 repaint 하는데, 우리가 자바스크립트로 실행하는 코드들로 인해서 혹은 다른 이유들로 제약을 받게된다. 그래서 아까 블로킹 섹션에서도 얘기 했지만 스택에 코드가 존재하면 렌더링을 못하게 된다. 렌더도 하나의 콜백처럼 행동하기 때문인데, 여기서 다른 점은 우리가 발생시킨 콜백에 비해서 더 높은 우선순위를 가진다.

매 16.6 밀리초마다 큐에 렌더가 들어가고 스택이 깨끗한 것을 확인한 후에 렌더링을 진행한다. 녹색으로 깜빡이고 있는것이 렌더링 콜백이라고 생각하자.

만약 우리가 비동기식으로 코딩을 짜지 않은 방식으로 실행을 한다면, 계속 콜스택에 코드가 머무르게 되므로 렌더링이 더뎌지게 된다. 스택에 표시된 delay() 우리가 원치 않게 작성한 동기적 코드라고 생각하자. 예를들면 다른 서버에서 데이터를 요청하고 계속 기다리는 요청 메서드로 봐도 좋다.

만약 이런 현상을 줄이기 위해서 비동기 콜백을 사용한다면

반복으로 동작하는 console.log를 setTimeout 콜백을 사용해서 webAPI로 돌린 다음 태스크 큐로 전부 전송한 다음에 하나씩 동작을 진행하면서 렌더링이 방해받는 시간을 줄이는 것이다. 물론 delay()는 똑같은 횟수로 동작하지만, 작은 시간을 벌어주게 되면서 그 시간에 하나씩 동작이 완료되는 것이다.

이를 통해서 이벤트 루프를 막는 행위를 줄이라는 이유가 설명된다. 스택에 눌러앉게 되는 코드를 작성해서 브라우저가 할일을 못하게 되는 것이고, 이를 막기위한 유동적인 UI를 만들어야 한다는 것이다.

해당 강의를 통해서 자바스크립트가 무엇인지, 비동기적 콜백이 어떤 과정을 거쳐서 실행되는 것인지 조금 더 이해할수 있게 되어서 좋았다.

Clone Coding

banner 섹션과 slider 섹션 구현을 완료했다.

banner 섹션

  • banner__boxflex 정렬히고 banner__textbanner__image로 나눠서 텍스트와 이미지를 표시했다.
  • 텍스트에는 사이트를 더 둘러볼수 있게 링크로 이동할수 있는 버튼 모양의 a태그가 존재한다.

slider 섹션

  • slider__headerslider__contents로 나누어져 있으며slider__header는 상부에 위치한 텍스트, slider__contents는 그 아래에 좌측에 텍스트, 우측에는 이미지가 표시된다.
  • 세개의 항목중에서 하나를 클릭하면 그에 맞는 이미지가 나타나는 방식이지만 레이아웃에 대한 구현 연습이 목적이므로 아직 그런 애니메이션은 구현하지 않음

profile
개발자 꿈나무

0개의 댓글