#1. JS상식과 이벤트루프

영가이·2024년 5월 11일

FrontEnd

목록 보기
1/7

아직 벨로그 꾸미는 법을 알지 못하여,,,
깃허브 링크를 걸어두진 않았지만,
내 옹졸한 레포지토리들을 살펴보면
대부분의 경우 데이터 관련 파일이 주를 이루고 있다.
이에 따라 네이버 블로그에도 주로 파이썬과 아나콘다 얘기를 썼다.
(사실 포르투갈 이야기가 더 많읍읍)

https://blog.naver.com/applelgy/223160712901
이런거 씀 ㅎㅎ... 아마 게시글 공개해둔건 세개일텐데
세개 다 아나콘다 안켜져서 울면서 쓴 글ㅋㅋㅋ

아무튼,
JS 이야기는 서툴 수 있지만
멋사 4주차 과제니 써야지

1. 괴랄하기로 유명한 JS의 연산

나에게 JS 첫인상은 이 사진이었다.
웃긴데, 웃을 수 없었다.
나는 멋사 프론트엔드를 지원해둔 상태였기 때문에.
그래서 이제 안웃기다. 하지만 왜 저런지 설명은 할 수 있다.

암묵적 타입변환

저 사진의 이유를 찾으려면 JS의 암묵적 타입변환 개념을 알아야한다.
Java는 고사하고 파이썬도 이런 해괴망측한 짓은 하지 않는데,
얼추 써도 돌아가주는 JS답게 +에 한해서 타입 변환을 임의적으로 해준다.
눈치보다가 int, str 등으로 바꿔줘서 저 난리가 나는 것.

문자타입으로의 변환 (+)

31 + '2' // '312'
31 + 'ab' // '31ab'
310 + ' ' // '310'
true + ' ' // 'true'

주석 처리 해둔 부분이 결과 값이다.
뒤에 더해지는 값이 문자열이면 앞값은 무조건 문자열로 바뀐다.
3,4번째 결과를 보면 알겠지만 공백을 더해주면 int, bool모두 문자열(str)화 된다.(...)

최근 유튜브를 보면 코딩 입문을 아예 웹개발로 해야한다는 주장이 있던데,
그 주장대로 코딩을 입문한다면 사실 1,2는 꽤, 나쁘지 않게 느껴질 것 같다.

숫자타입으로의 변환

+를 제외한 연산자가 해당된다.

1 - '2' // -1
9 - '3' // 6
9 * '3' // 27
9 / '3' // 3

조금 헷갈리니 비교해보면

1 + '2' //'12'
1 - '2' // =1

이다. 더하면 그대로 문자열(str)로 변하는데
빼거나 곱하거나 나누면 그대로 숫자로 받아 연산한다.
이는 비교 연산자도 마찬가지라

1 > '-1' // true
'1' < '-1' // false 

+를 단항 연산자로 쓰면
숫자가 아닌 피연산자를 숫자로 바꿔준다.

+false // 0
+true //1
+'' // 0
+'3' // 3
+null //0

이를 보고 다시 첫짤을 보면 명료하다

"이" + "이" = "이이"
"2" + "2" = "22" // 문자열로 2와 2가 붙은 것

//4번예시
"2"+"2"-"2" //"22"-"2" -> 22 -2 ->20

물론 이런 방식은 정말 유연하다는 R에도 없는 연산 방식인지라,
사람들을 혼란에 빠트리기 좋다는 건 부정할 수 없는 것 같다.

+"0" == [] // true

ㅋㅋㅋㅋㅋ
인생이 심심하다면 JS 연산방식을 공부해보자.

참고로 이러한 방식 때문에 안정성을 위해 사용하는 것이
TypeScript 라고 한다.
이력서에 많은 그 언어.
예상과 다른 자료형이 오지 않도록 막아주는 프로그래밍 언어라는데,
배우면 적으러 오겠습니다~~!

2. 전달 방식

JS는 변수 하나 할당하기도 어렵다.
var, let, const.. 등등. 물론 요즘은 let을 더 쓴다고는 하는데,
( let's use라는 뜻이래나ㅋㅋㅋ)
책펴서 공부하거나 사이트 찾아보면 var도 정말 많이 선언하기 때문에
알아둬야한다.

쨋든, 이 부분은 다소 cs스럽지만
변수에 따른 메모리 할당에 대한 이야기이다.

변수에 할당하다 = 변수에 값을 저장하다 ( var a = 1)
변수를 참조하다 = 변수에 저장된 값을 읽어들이다 ( b = a)

값에 의한 전달 (pass by value)

JS에서 Boolean, Null, Undefined, int 등의 값을 원시타입(Primitive Type) 이라고 한다.
사실 함수, 리스트 등을 제외한 모든 값이 원시타입이다.

let a = 100; 을 할당했다면 컴퓨터는 안에서 어떻게 움직일까?
변수를 지정하면 컴퓨터 메모리는 할당된 주소에 값을 저장한다.
이를 다른 변수에서 읽어들이면 그 값을 그대로 저장하여 자신의 메모리 주소에 저장한다.

let score = 80; // 80이 저장되어 있는 메모리 공간의 주소값 X
let copy = score; // 80을 다른 메모리 공간 Y에 저장하여 전달받음

score = 500 // 500을 저장한 새로운 메모리 공간 Z로 주소값 변경

console.log(copy);  // 80

혹시 게임 파일을 복사해본 경험이 있는가?
보스전을 앞두고 저장 후 게임파일을 복사해두고
보스전에서 죽고 아이템 다 잃어버리면
복사해둔 파일로 도망치고...ㅎㅎ

이 사례와 비슷하다.

copy는 보스에 도전하기 전, 80 점짜리의 내가 저장되어 있는 것이다.
보스를 깨고 보상을 빵빵하게 받아 500점짜리가 된 나는 본 파일에 저장되어 있을 뿐
copy에는 80점인 늅늅한 내가 저장되어있는 것이다.

이를 알아두면 좋은게,
데이터 측면에서도 이 원리를 이용해서
csv를 직접 바꾸지 않고 copy하여 데이터를 돌린다.
거꾸로 copy해서 복사본 점수를 한번 죽어서 0점으로 돌리던
다크소울로 동숲을 하던 본 파일에는 지장이 없으니 실험적인 무엇인가,
특히 협업할 때 최종 컨펌 나기 전에 변수를 copy해둔 채로 무엇인가 코딩해두면
충돌이 적어지겠지요?

물론, 복사해둔 걸 꼭 저장하고, 다운로드하고, 할당해주는 버릇을 기릅시다.

참조에 의한 전달 (Pass by Reference)

array(배열), function, object 등 객체 타입의 값에 할당 시 이루어지는 전달 법이다.
감이 오겠지만, 얘는 변수를 copy 해둬도 같은 메모리 주소를 가르키게 되어
변수가 같이 변하게 되는 경우이다.
때문에 얘는 변수 공유에 해당하게 된다.

let person = {
  name : 'Lee'
} // 객체의 주소 X가 담겨있는 메모리 주소 Y

let copy = person; // 객체의 주소 X가 담겨있는 메모리 주소 Z
// 결국 두 변수는 같은 객체를 가리키게 됨

console.log(person.name, copy.name); // Lee Lee

copy.name = 'Kim';

console.log(person.name, copy.name); // Kim Kim

person을 복사한 copy. 둘 모두 Lee가 있었다.
copy의 변수에 kim을 다시 할당해줬더니
person.name에도 kim이 할당되는 일이 발생되었다..!
정말 헷갈린다.

copy는 사실 person의 Lee만을 맏은 것이 아닌,
person 함수 자체를 다 받아왔다고 생각하면 편하다.
그 함수를 다 받아와서 그 안의 객체인 name의 값을 kim으로 바꿔준다.
때문에

let person = {
   name = 'Kim'
}

인 상태가 되어 내용이 다 바뀐 것을 알 수 있다.

조심 조심.

3. Truthy, Falsy

처음에 듣고 와 무슨 코딩하는 언어가 이렇지?
True스러운 값이라니, 충격적인 타입 변환이다.

배운 바로는

true로 형변환을 강제하는 것을 Truthy라고 하고, false로 형변환을 강제하는 것을 Falsy 라고 합니다.

라고 한다.

대부분의 값은 Truthy이며

Falsy로 취급되는 값은 아래의 7가지다

false
0
null
undefined
''
NaN
-0

용법은 아래와 같이 if문 넣을 때 유용하게 쓰인다.

// Truthy
if (-1)

//Falsy
if (-0)

가독성이 아주 굿이니까요.
그리고 조건에 따라 화면을 바꿔주고 싶어서 배우는JS니까,
이런 if문에 따라 코드가 바뀌어야할 경우가 많을텐데
그런 경우 조금은 간단해질 수 있겠지요??

화살표 함수

Js는 함수를 선언하는 방법이 많다.
위와 같이 function으로 해주는 방법도 많지만
아니 1회용으로 쓸건데 function으로 써서 export하고
내가 파일을 import까지 해와야할까?
그런 당신을 위한 화살표 함수.

const arrowtest = (name) => {
    console.log(name)
    console.log("파이썬에는 없는 화살표 함수. 매우 부러워요.")
}

하지만 1회용이니 당연히 제약이 있다.

  • const 타입 사용이 안된다.
  • this binding

const 타입 사용이 불가능하다.
바꿀 수 없는 변수를 선언할 수 없다.
자주쓰거나 중요한 함수를 위한 기능이 아니기 때문...!

this 용법

const person ={
    name:'kyle',
    sayHello:function(){
        console.log('hello',this.name)
    }
}
person.sayHello() //hello kyle
const callMyName = person.sayHello
callMyName() //hello

this.name이라니 이게 뭔가요?
이거라는 뜻이다.
sayHello가 종속된 person의 객체인 name을 불러올 수 있다.
즉 가까운 scope의 객체를 받아와 소환할 수 있는 문법이다.
당연히 간단하니, 편의성을 위한 기능인 것 같다.
함수의 중첩이 누적되면 this의 용법이 상당히 까다로워지겠죠?
가독성도 좋지 않을 것.

생성자와 class

내가 코딩을 시작하기 전, 먼먼 옛날 (?)
JS 에는 클래스가 없었다한다.
때문에 아래와 같이 함수 기능을 사용하여 생성자를 만들어주고
class와 같이 사용하였다.

생성자

function Coachella(singer,song,order) { // 생성자 함수
	this.singer = singer;
  	this.song = song;
    this.order = order;
  	this.say = function() {
    console.log(this.song);
  };
};

const inspirit = new Coachella("Infinite","Time difference",1) 

과 같은 방식으로 사용할 수 있다.
생성자는 일반함수와 구분해야하니 첫글자를 대문자로 설정하여 이름을 적어주고
new를 연산자 앞에 붙여줘야한다.

이후 아래와 같이 재활용이 가능해진다.

let exo = {
	singer: "Exo",
    song : "Peterpan",
    order : 4
 };

같은 식으로 붕어빵 틀에서 팥붕,슈붕,피붕 나오듯 뽑아낼 수 있다.

클래스(class)

class Coachella{
	constructor(singer,song,order){
    	this.singer = singer;
        this.song = song;
        this.order = order;
  	};
const bap = new Coachella('BAP','Stop it',10);

같이 쓸 수 있고 생성자와 거의 유사하다.
constructor을 통해 객체의 초기값을 설정하여 인자를 전달할 수 있으며
클래스 내부에서 하나만 존재할 수 있다.

클래스 상속은 extends로 가능하다.

class 'infinite' extends Coachella{
	constructor(singer,song,order){
    	super('infinite',song,order);
        this.fan = fan
    }
   };
const inspirit = new infinite('be mine',1,'inspirit')

식으로 상속하여 사용이 가능하다.

이벤트루프

마지막 주제. 이벤트루프다.
JS는 싱글스레드 기반의 언어다.
때문에 동시에 하나의 작업만 을 처리할 수 있다.
그 시절에는 그렇게 설계했다.
그렇다면 어떻게 클릭하면 화면이 바뀌고
일정시간뒤에 화려한 이펙트를 보여줄 수 있는 언어가 되었을까?

이는 비동기 처리 (asaynchronus) 덕분이다.

console.log(1)
	
setTimeout(() => {
	console.log(3)
}, 100)

console.log(4)

출력 순서는 1-4-3으로 대기시간이 있는 것은 뒤로 순서가 밀려 출력된다.
이를 비동기처리라고 한다.
이러한 작업을 웹에서 가능케 해주는 것이 이벤트 루프다.

기본적으로 웹은 아래와 같은 구조다.

  1. 요청한 작업을 call stack에 넣는다

  2. 출력되면 스택의 원소를 제거한다.

  3. set timeout같은 요소가 있다면 일단 call stack에서 지운다.
    3.5 지연 되는 만큼 call back queue에 머문다.

  4. eventloop는 계속 call stack과 call back queue를 순찰한다.
    4.5 call stack이 비거나, call back queue에 해당하는 조건이 충족되면 이를 call stack으로 옮겨 실행시킨 후 요소를 제거한다.

이런 느낌스

첫 게시글 치고 내용이 빵빵한데 사실 배워서 그렇습니다.
아주 잘 정리된 자료를 다시 개판으로 재생산하는 작업이라니
아마 앤디워홀씨는 날 싫어할거야.
다음에도 JS나 FE관련 유익한 지식을 배워
글을 적으러 오겠습니다.

모두 읽어줘서 고마워용:D

profile
어문과 개발. 융합형인재 호소인.

0개의 댓글