DevLog__[javascript: 동기와 비동기, 함수 메소드, this]

Jaewon Lee·2020년 10월 8일
1

Javascript

목록 보기
8/12
post-thumbnail

# Intro

갈수록 어렵누....

다른 컴퓨터 언어에서 접해 보지 못했던 비동기호출과 함수 메소드...

처음이라 어색하지만 익숙해지기 위해 거의 1주일 가까이 계속 보았던 것 같다.

정리가 얼추 되었으니, 블로깅을 통해 다시 정리해 보자!

yoyo!!!!!!!!!!!!!!!!!🔥


1. 동기 vs 비동기


1) 동기와 비동기가 뭐지?

동기 호출이란?

  • 요청에 대한 응답이 바로 일어난다.
  • 들어온 요청이 순서에 맞게 하나씩 진행되는 것이다.

비동기 호출이란?

  • 요청에 대한 응답이 바로 이루어지지 않는다.
  • 응답은 특정 이벤트가 준비되었을 때 이루어진다.

동기 호출은 은행, 비동기 호출은 카페

  • 은행 업무는 대기표를 뽑고 한 사람씩 응대하며 일을 진행하고, 일이 끝나기 전까지 다음 사람은 기다려야한다.
  • 반면에, 카페 업무는 다음 사람이 기다릴 필요 없이 차례대로 주문을 한번에 받고, 진동벨을 통해 음료가 완성되었다는 것을 알려 일을 처리한다.

2) 비동기 호출이 왜 필요할까?

이전과는 다르게 글로 설명을 하기 때문에 나도 힘들고, 읽는사람도 힘들 것 같다.😩

그래서 비동기식 호출이 필요한 이유를 하나씩 쪼개서 순서대로 나열해 보려고한다.

1️⃣ javascript는 기본적으로 싱글스레드이다. (싱글스레드 : 한번에 한 가지 일을 처리한다.)


2️⃣ 싱글스레드에 기반하여 프로세스(일, 작업)을 처리하므로, 하나에 일을 처리하기 전까지 다음 일은 대기하고 있어야 한다.


3️⃣ 이 방식은 동기식이랑 똑같쥬?


4️⃣ 동기식은 순서가 정해져 있으므로, 빠른 일처리가 가능하지만 한번에 여러일을 요청받는 것이 불가능!


5️⃣ 그래서 나온 것이 비동기식 뚜둥 탁!


6️⃣ 결론적으로 비동기식 호출은 여러일을 한번에 받기 위해 필요하다!


3) 비동기 흐름(순서)을 처리하는 방식들

앞서 말했듯이, 비동기 호출은 요청을 한번에 받아서 처리할 수 있는 장점을 가진다.

하지만 javascript는 기본적으로 싱글 스레드이다! 요청을 순서대로 한번에 받았으면, 응답도 순서대로 처리해 주어야 한다.

하지만 이 순서, 어떻게 이 순서를 정의하고 처리해 주는거지?

비동기 호출에서는 무엇을 먼저 응답해줘야 될지에 대해서 순서가 불명확하기 때문에, 이러한 순서를 제어해줄 skill이 굉장히 중요하다.

오늘은 이러한 skill들에 대해 간략히 소개만하고, 자세히 공부한 다음에 블로깅을 해보겠다!

1. 콜백

2. promise

3. async / await


4) 비동기 호출은 어디에 사용될까?

비동기 호출이 뭐하는 녀석인지, 왜 사용하는지 알았으니 어디에 사용되는지 알아보자!

1. 타이머API

  • setTimeout(callback, millisecond)
    • 일정 시간 후에 함수를 실행
    • arguments: 실행할 callback 함수, callback 함수 실행 전 기다려야 할 시간 (밀리초)
    • return value: 임의의 타이머 ID
setTimeout(function() {
  console.log('1초 후 실행');
}, 1000);
// return value : 123
// OUTPUT : 1초 후 실행
  • setInterval(callback, millisecond)
    • 일정 시간의 간격을 가지고 함수를 반복적으로 실행
    • arguments: 실행할 callback 함수, 반복적으로 함수를 실행시키기 위한 시간 간격 (밀리초)
    • return value: 임의의 타이머 ID
setInterval(function() {
  console.log('1초마다 실행');
}, 1000);
// return value : 345
// OUTPUT : 1초마다 실행
//	    (1초 후)
//          1초마다 실행....(반복)
  • clearInterval(timerId)
    • 반복 실행중인 타이머를 종료
    • arguments: 타이머 ID
    • return value: 없음
var timer = setInterval(function() {
  console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// 더 이상 반복 실행되지 않음

2. 애니메이션 API

3. DOM Element의 Event Handler

4. 서버에 자원요청

  • fetch API
  • AJAX (XHR)

5) 비동기 호출 참고자료

1️⃣ YOUTUBE 드림코딩 by 엘리 (11,12,13편 보면 됨!)

2️⃣ 비동기호출 skill 콜백함수 (다음글에 pomise랑 async/await도 있음)

3️⃣ 비동기호출이 필요한 이유에 대해서 잘 설명해 놓은 블로그

4️⃣ 콜백, promise, aasync/ await를 코드를 통해 설명한 블로그



2. 함수 메소드


1) 함수를 실행시키는 방법

1. function 호출

function print(){
  return 'print()를 통해 함수를 호출합니다.';
}
let result = print();
console.log(result);
// OUTPUT : print()를 통해 함수를 호출합니다.

2. new 키워드를 이용한 호출

let print = function(str){
  return str;
}
let result = new print('new 키워드를 사용하여 함수를 호출합니다.');
console.log(result);     
// OUTPUT : new 키워드를 사용하여 함수를 호출합니다.

3. 함수 메소드를 이용한 호출

let print = function(str){
  return str;
}
let result1 = print.call(null, 'call을 사용하여 함수를 호출합니다.');
let result2 = print.apply(null, ['apply를 사용하여 함수를 호출합니다.']);
let result3 = print.bind(null, 'bind를 사용하여 함수를 호출합니다.');
console.log(result1);
console.log(result2);
console.log(result3());
// OUTPUT : call를 사용하여 함수를 호출합니다.
//          apply를 사용하여 함수를 호출합니다.
//          bind를 사용하여 함수를 호출합니다.
  • call은 보통 함수와 똑같이 인자를 넣고, apply는 인자를 배열로 전달한다.
  • bind는 call이나 apply와 비슷하지만 호출은 하지 않지 않고 함수만 반환한다.
  • 함수 메소드의 첫 번째 인자(위에서 null로 기입)는 this를 의미한다.

2) 함수 메소드를 왜 사용하지?

유사 배열도 배열 메소드를 사용할 수 있게 된다.

  • [javasciprt: 부족한 개념정리] 편에서 rest parameter를 설명하면서 arguments에 대해 언급한 적이 있다. 배열에 형태를 띄지만 배열은 아닌 것을 유사 배열이라고 한다.
  • 이러한 유사 배열은 배열 메소드를 사용할 수 없지만, 함수 메소드(call, apply, bind)를 사용하면 배열 메소드도 사용이 가능하다.
function example() {
  console.log(arguments);
}
example(1, 'string', true);      
// OUTPUT : [1, 'string', true, callee: f...]
function example2() {
  console.log(arguments.join());
}
example2(1, 'string', true); 
// OUTPUT : Uncaught TypeError: arguments.join is not a function
// join은 배열 메소드이므로, 유사배열은 사용하지 못하기 때문에 오류가 발생한다.
function example3() {
  console.log(Array.prototype.join.call(arguments));
}
example3(1, 'string', true); 
// OUTPUT : '1,string,true'

2. 명시적으로 this가 가르키는 객체 변경

  • 기본적으로 this는 window객체를 가르키지만, call과 apply 그리고 bind로 이를 바꿔줄 수 있다.
function Box(w, h) {
  this.width = w;
  this.height = h;
  this.getArea = function() {
    return this.width * this.height;
  }
  this.printArea = function() {
    console.log(this.getArea());
  }
}
let b = new Box(100, 50);
//setTimeout(b.printArea, 2000)
setTimeout(b.printArea.bind(b), 2000)
  • 주석 처리한 부분과 안한 것의 차이에 대해 살피는 것이 핵심
  • b.printArea는 함수 자체를 가져 온 것이다. 뒤에서 this를 다룰 때 자세히 얘기하겠지만 함수의 this가 가르키는 객체는 기본적으로 window다.
  • 위에 코드는 window객체를 bind를 통해 'b'로 변경해 놓은것을 보여준다.
  • 이벤트 핸들러와 같이 내부적으로 함수를 호출할 때 자동으로 this를 바꾸는 것들이 있다. 이런 것은 어쩔 수 없이 외워야 한다...ㅎ

3. bind로 커링을 구현할 수 있다.

  • bind는 함수를 실행하지 않은 상태, 함수 자체를 변수에 할당해줄 수 있기 때문에 커링을 구현하는데에 용이하다고 한다.
  • 하지만 아직 무지한 나로써는, 표현의 차이정도를 느꼈고,
  • 함수 안에 함수를 작성하지 않고 평소대로 함수를 작성해도 되니 약간의 편안함이 느껴진다!
//bind로 구현
function introduce(name, money) {
  return `hi my name is ${name}, and i have &{money} won!`;
}
let me = introduce.bind(null, 'leejaewon');
console.log(me(10000))
// OUTPUT : `hi my name is leejaewon, and i have 10000 won!`
//걍 일반 커링 구현
function introduce(name) {
  return function(money) {
    return `hi my name is ${name}, and i have &{money} won!`;
  }
}
let me = introduce('leejaewon');
console.log(me(10000))
// OUTPUT : `hi my name is leejaewon, and i have 10000 won!`


3. this


1) this가 무엇?

  • this는 모든 함수 스코프내에서 자동으로 설정되는 특수한 식별자
  • execution context의 구성 요소 중 하나로, 함수가 실행되는 동안 이용할 수 있다.

2) this는 크게 5가지 경우를 외우자!

1. global invocation

  • this : window
var myname = 'leejaewon'
console.log(this)
console.log(this.myname)
// OUTPUT : window
//          leejaewon
  • var를 통해 window 객체에 myname이라는 변수 선언.
  • 전역이기 때문에 this는 window 객체를 나타내고, window내부에 myname을 선언했으므로 조회 가능

2. function invocation

  • this : window
var num = 1;
function foo() {
  console.log(this === window);
  console.log(this.num);
}
foo();
// OUTPUT : true
//          1

3. method invocation

  • this : 부모 object
let obj = {foo: function(){
  	console.log(this);
	}
}
obj.foo();
// OUTPUT : {foo:f}  ->  obj를 말한다.

4. construction mode(생성자 함수)

  • new 연산자로 생성된 function 영역의 this
  • this : 새로 생성된 객체
function Car(brand, name, color) {
  this.brand = brand;
  this.name = name;
  this.color = color;
  console.log(this);
}
let avante = new Car('hyundai', 'avante', 'black')
// OUTPUT : Car('hyundai', 'avante', 'black')   ->   this = avante라는 뜻

5. .call / .apply / .bind

  • this : call, apply의 첫 번째 인자로 명시된 객체
let obj1 = {order:'first', func: function() {console.log(this)}};
let obj2 = {order: 'second'};
obj1.func();
obj1.func.call(obj2);
// OUTPUT : {order: 'first', func: f}    ->    this = obj1 이라는 뜻
//          {order: 'second'}            ->    this = obj2 라는 뜻


4. 더 깊게 공부해 봐야할 것



# Work Off


이번 블로깅은 왜이렇게 어렵고 힘든지....쓰는데만 엄청 오래 걸렸네...ㅠㅠ약간 게을러진 것 같은데, 동기부여가 필요한 시점인것 같음.... 뭘하면 동기 부여가 될까싶네...허허

내가 가고싶은 회사 탐방 이런거 있으면 좋을 것 같은데...

오늘 갑자기 백엔드와 프론트엔드에 대해서 고민을 해봤는데, 내 적성은 프론트엔드에 맞지 않을까 라는 생각이 들었다.

잠깐의 생각일수도...

모든 코딩이 그렇겠지만 백엔드는 특히나 더 논리적인 로직을 생각하고 수기로 작성하여 이를 토대로 코드를 작성하는 것 같다.

뭔가 좀 두렵달까...내가 생각한 논리적인 구조가 정답이 아닐수도 있고...아무것도 안보이는 곳에서 마라톤을 하는 느낌일 것 같다.

반면에 프론트엔드는 코드를 짜면서 눈에 보이는 것이 있으니...훨씬 심적으로 안정감이 있지 않을까 싶다.

그리고 나는 그렇게 안생겼어도, 미적 요소에 상당히 관심이 많고 섬세하기 때문에 디자인적인 요소가 많이 들어가는 프론트엔드의 특성에 잘 맞지 않을까??

하하 아직 코딩찐찌라서 잘 모르겠다. 그냥 느낌일 뿐!

자기전에 유튜브에 프론트엔드 현직자 정보좀 캐봐야겠다!!

빨리자고 내일부터는 토이 프로젝트 해야지ㅎㅎ 오늘도 고생했다....

기본기가 탄탄한 풀스택 개발자가 되는 그날까지 🔥🔥🔥

profile
Communication : any

0개의 댓글