반응형

프로젝트를 진행하다보면 HTTP 통신을 통해 데이터를 가져와야할 경우가 있습니다. 기본적으로 HTTP통신은 비동기적으로 이루어집니다. 그렇다보니 데이터를 받아오기전에 Rendering이 이루어지는 경우도 있고 미리 연산처리를 해버려 에러를 발생시키는 경우도 빈번하게 발생합니다.

이번 포스팅에서는 위와 같은 일을 방지하기 위해 Javascript 에서의 비동기를 동기로 실행하는 방법에 대해서 알아보려합니다 👍

📋비동기 / 동기

우리는 카페에가서 음료를 주문하고 진동벨을 받아옵니다. 자리에가서 앉아 있다 진동벨이 울리면 커피를 받아옵니다. 이를 ‘비동기 처리’에 비유할 수 있습니다.

각자의 일을 처리하다 자신의 차례가 오면 자신의 일을 수행합니다. 서로에게 영향을 주지 않습니다.

진동벨이 없다고 생각해보세요 카페에가서 음료를 시키고 음료가 나올때까지 카운터에서 기다려야한다면 우리는 커피가 나오기전까지는 자리에 앉아 업무를 볼 수 없을거에요 이처럼 앞의 일이 끝나야 다음일을 처리할 수 있는 것을 ‘동기의 처리’에 비유할 수 있습니다.

📋비동기를 동기로 동작시키는법

자바스크립트에서의 비동기를 동기로 동작시키는 대표적인 3가지의 방법을 알아보겠습니다.

Callback Function

Promise

Async / Await

Generator (이 포스트에서는 다루지 않습니다)

📋 1. Callback

첫번째로 Callback을 이용한 방법을 알아보겠습니다.

기본적인 Callback의 사용법은 위와 같습니다 😉

a 는 callback 즉 function을 받는 함수입니다.

a 는 받은 함수에 ‘i am A’ 라는 값을 넣어줍니다.

b 는 a에서 넘겨준 ‘i am A’ 라는 값을 받아 console 에 찍어줍니다.

위의 코드의 동작을 이해하셨다면 비동기를 동기로 바꾸는 코드도 쉽게 이해하실 수 있습니다.

두개의 함수가 있습니다.

step1은 실행 후 2초가 걸리고, step2는 1초가 걸립니다.

우리는 step1이 실행되고 step2 가 실행되기를 바랍니다.

위의 코드를 실행해보면 우리가 원했던 결과가 나오지 않습니다.

step2 가 실행하고 step1 이 실행됩니다.

어떻게 하면 우리가 원하는대로 실행시킬 수 있을까요 ? 바로 ‘Callback’ 을 이용하면 됩니다.

step1 은 함수를 인자로 받는 함수입니다.

step1 은 받은 함수를 실행해주는 역할을 합니다.

우리가 의도한대로 step1 이 실행된 후 step2 가 실행됩니다.

위와 같은식으로 Callback을이용하면 비동기를 동기처럼 동작하게 할 수 있습니다.

하지만 지금은 함수가 2개 뿐이지만 함수가 많아질 수록 함수의 깊이가 깊어집니다. 표현방법 2 처럼 말이죠 함수안에 함수 함수안에 함수…. 그안에 또 함수 … 다들 한번쯤 들어보셨을만한 Callback Hell 이 되는 것이죠 .. 그래서 조금더 깔끔하게 처리할 방법이 필요했습니다.

그것이 2번째 방법인 Promise 입니다.

📋2. Promise

기본적인 Promise 객체의 사용법 입니다.

foo 는 Promise 객체를 Return 합니다. 그렇기 때문에 foo().then 처럼 이어갈 수 있습니다.

foo().then 에서 then은 foo의 동작이 마무리된 후 동작합니다. Promise resolve 안에 넣어준 값이 들어옵니다.

then 을 계속 이어쓸 수 있습니다

Callback 으로 해결했던 것을 Promise 로 변경해보겠습니다.

a는 Promise 객체를 반환합니다. 그렇기 때문에 a().then 을 통해 순서를 제어할 수 있습니다. then 은 a의 동작이 마무리된 후 실행됩니다.

a 가 실행되며 console.log(‘a run …..’) 이 제일 먼저 실행되고

resolve를 통해 then 으로 (str === ‘a run …..’) 을 넘겨줍니다.

a의 실행이 끝나고 then 에서 b를 실행하며 str을 넘겨줍니다. 이때 console.log(‘b run …..’) 이 찍히게 됩니다.

마지막으로 1초 후 console.log(‘넘겨받은 값: ’, str) 이 찍히게 됩니다.

또 여러개의 비동기 작업이 있을때 비동기 작업이 모두 완료된 후에 어떤 작업이 이루어져야 할때도 Promise를 이용할 수 있습니다.

2개의 작업이 있습니다. 한가지 작업은 1초가 걸리고 다른 한가지 작업은 2초가 걸립니다. 우리가 원하는 것은 두개의 작업이 ‘모두’ 마무리 된 후에 다른 작업이 이루어지기를 바랍니다.

Promise.all 에 [첫번째 Promise, 두번째 Promise] 의 형태로 넘겨주면 모든 Promise의 작업이 끝난후 then 에 결과값을 배열형태로 넘겨줍니다

어떤가요 Callback 보다는 편리해졌나요 ? 하지만 Promise 또한 깊이가 깊어진다면 가독성이 현저히 떨어질 수 있습니다. 사실 Promise를 사용하는데 보기가 너무 힘들고 불편한 현상이 생겼다면 (본인의 코드를 의심해봐야 될 수 있습니다…😉)

📋3. Async / Await

마지막으로 살펴볼 방법은 Async / Await 입니다.

Async /Await 은 말그대로 동작을 일시정지 시킨것처럼 보이게 해줍니다. Promise 나 Callback 보다는 직관적인 코드 패턴을 가질 수 있습니다. (Async 와 Promise 의 차이점에 대해서는 후에 포스트에서 다뤄볼 예정입니다)

async 함수 표현식을 이용합니다.

async 함수 내부에서는 promise 객체들의 순서를 await을 이용하여 순서 조절이 가능합니다.

foo 는 async 함수입니다.

foo 를 실행가된다면 console.log(‘foo run….’) 이 가장 먼저 찍히게되고 아래 await 을 만나게 됩니다.

promise() 은 Promise 객체입니다. promise() 을 실행하면서 console.log(‘promise run ….’) 이 찍히게 되고 2초 후에 resolve(10) 을 실행하게됩니다. 앞에서 살펴봤던 Promise 에서는 then으로 10 으로 들어가지만 await 을 이용하게되면 10 이 return 됩니다. 즉 const num = 10 이 됩니다.

promise() 종료 후 num 에 10이 들어오고 console.log(‘num’, 10) 이 실행된 후 종료됩니다.

📢마무리

비동기를 동기처럼 사용할 수 있는 3가지 방법에 대해서 알아봤습니다. 어떤 것이 좋고 어떤 것이 안 좋다고 말하기에는 저의 경험과 지식이 아직 부족하기도 하고 상황마다 필요한 것들이 다르기 때문에 감히 말할 수는 없습니다.

Promise와 Async 는 디버깅 시 에러가 걸리는 포인트가 다르기도 하고 개인의 취향에 따라 어떤 것이 더 보기 편하다 나쁘다 등등 굉장히 많은 이야기가 오가는 것으로 알고 있습니다. 이에 대한 이야기는 자료를 더 수집한 후 뒤에 포스터에서 정리해보려 합니다. 😉

-출처 https://medium.com/@appear.ko/javascript-async-to-sync-157c57208598

 

반응형
반응형

📢JAVASCRIPT THROW 예외처리

▼ 내용
throw 에 에러가 걸리면 이하 구문은 실행안하고 catch문으로 들어간다

💻코드

function getRectArea(width, height) {
  if (isNaN(width) || isNaN(height)) {
    console.log("시작 1");
    throw "Parameter is not a number!";
    console.log("시작 2");
  }
  console.log("시작 3");
}

console.log("시작 4");

try {
  getRectArea(3, 'a');
  console.log("시작 5");
}
catch(e) {
  console.log("에러22"+e);
  // expected output: "Parameter is not a number!"
}

//console.log 에러일경우
> "시작 4"
> "시작 1"
> "에러22Parameter is not a number!"

//console.log 정상일경우
> "시작 4"
> "시작 3"
> "시작 5"
반응형
반응형





◎ => (애로우 함수)

▼ 내용

ECMA6 들어서면서 => 애로우 함수를 사용할수 있따.

const handleListening = () =>{ console.log('ㅎㅇ'); } // 위에 는 const handleListening = function () { console.log('ㅎㅇ'); } //이거랑 같다

◎ import , export

▼ 내용

import 문은 외부 모듈이나 다른 스크립트 등으로부터 export 된 기능을 가져오는데 사용됩니다.

(함수,변수 모듈화 class화?)

자바스크립트는 호이스팅이 되는 관계로 변수나 함수가 전역에서 사용할 수 있었기 때문에 이름으로 충돌을 일으키는 경우가 많아서 이용하기 어려웠다. (CommonJS로 사용할 수는 있었음)

ES6부터는 모듈 시스템을 사용할 수 있게 만들었다.

하지만 브라우저에서 지원이 되지 않고있기때문에 webpack같은 모듈 번들러를 사용해야만 모듈시스템(import, export)을 사용할 수 있다.

문법.. import name from "module-name"; import * as name from "module-name"; import { member } from "module-name"; import { member as alias } from "module-name"; import { member1 , member2 } from "module-name"; import { member1 , member2 as alias2 , [...] } from "module-name"; import defaultMember, { member [ , [...] ] } from "module-name"; import defaultMember, * as alias from "module-name"; import defaultMember from "module-name"; import "module-name";

export const pi = Math.PI; export function square(x) { return x * x; } export class Person { constructor(name) { this.name = name; } }

export 키워드로 변수, 함수, 클래스를 외부의 스크립트로 모듈화 시킬 수 있다.

외부로 보내고 싶은 것들에 일일이 키워드를 붙여도 되고 아래처럼 한번에 export해도된다.

const pi = Math.PI; function square(x) { return x * x; } class Person { constructor(name) { this.name = name; } } export { pi, square, Person };
import {userRouter} from "./router"; //export const userRouter = express.Router(); import app from "./app"; //export default app;

또한 export default app; 이렇게 할경우엔 바로 import app 할수 있지만

(export default 파일명 한다는건 안에있는 모든걸 export 해준다는것)

export const userRouter 이렇게 할경우엔 가져올때 {} 를 붙혀서 써줘야한다.

// main.js import { pi, square, Person } from './lib'; console.log(pi); // 3.141592653589793 console.log(square(10)); // 100 console.log(new Person('Lee')); // Person { name: 'Lee' }

반대로 가져오는 방법은 위와 같이 "import" 키워드를 사용하고 from 으로 해당 모듈의 js파일을 가리키면 된다.

import * as lib from './lib'; console.log(lib.pi); // 3.141592653589793 console.log(lib.square(10)); // 100 console.log(new lib.Person('Lee')); // Person { name: 'Lee' }

위와 같이 "as"를 사용해서 일일이 모듈을 불러오지 않고 한번에 사용할 수 있다.


◎ 구조 분해 할당 ( destructuring assignment )

▼ 내용

객체 또는 배열을 소인수분해 하듯이 분해하여 할당할수 있다.

const searchingBy = req.query.term //기존방식 const { query: {term : searchingBy} //req.query.term 의값을 searchingBy 할당 } = req;

솔직히 이걸 작성하면서 대략적인 느낌만 이해가간다.. 하지만 왜 구지 보기힘들게 이렇게쓰나 싶다.. 나중에 이해더가면 추후작성하기로하고 mdn 주소를 남긴다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

새로운 변수 이름에 할당

객체 구조분해를 사용하여 새로운 변수 이름에 값을 할당할 수 있습니다.

var o = {p: 42, q: true}; var {p: foo, q: bar} = o; console.log(foo); // 42 console.log(bar); // true






반응형
반응형

◎ PM2 란?

▼ node js를 실행하는 프로세스를 제어할수있다.

다중으로 실행 , 끄기 , 강제로종료해도 프로세스가 다시살아나기 등등을 할수 있는 패키지이다


◎ PM2 패키지 설치법

▼ 내용.

npm install pm2 -g //global 이란 뜻이다. 어디서든 사용할수 있다는 옵션이다

◎ PM2 패키지 사용법

▼ 내용

아래와 같이 실행하면 아래 사진처럼 현재 status를 알려준다

실행되고 다시 콘솔로 오는거 같다

pm2 start app.js pm2 start app.js --watch // 실행할 js파일을 --watch 옵션으로 실행하면 소스 수정후 저장하면 // 자동으로 node를 재시작해줘서 소스적용이 된다. pm2 start app.js --watch --no-daemon //백그라운드로 실행되는 프로그램을 데몬이라고 부릅니다. //nodaemon을 치면 백그라운드 실행이아니라서 실행후 바로 log를 볼수있게됩니다. pm2 start app.js --watch --ignore-watch="(파일경로)" --no-daemon //이렇게 실행할경우 해당 파일경로에 파일들이 수정될때는 서버가 재시작 하지 않는다


◎ PM2 모니터링

▼ 내용

pm2 모니터링 왼쪽 창이 현재 실행중인 프로세스의 목록이다

pm2 monit


◎ pm2 list 확인

▼ 내용

pm2 의 현재 실행중인 프로세스 status 확인

pm2 list



◎ pm2 프로세스 종료

▼ 내용

pm2로 실행한 프로세스를 종료할수 있다.

pm2 stop [App name] // pm2 list 로 확인한 appname 이름을 써주면된다. pm2 kill // pm2 로 시작한 모든 프로세스를 죽인다


◎ pm2 로그확인

▼ 내용

pm2로 실행할경우 console에 아무것도 안찎혀 로그를 안남기는데

실시간으로 log를 보여주는 명령어다

pm2 log




반응형
반응형


◎ 함수의 선언

▼ 내용

함수 선언식 - Function Declarations

일반적인 프로그래밍 언어에서의 함수선언과 비슷한 형식이다.

// 예시 function funcDeclarations() { return 'A function declaration'; } funcDeclarations(); // 'A function declaration'

함수 표현식 - Function Expressions

일반적인 프로그래밍 언어에서의 함수선언과 비슷한 형식이다.

var funcExpression = function () { return 'A function expression'; } funcExpression(); // 'A function expression'

◎ 함수의 구분 (객체 안에 함수)

▼ 내용

객체안에 함수가 들어있으면 메소드 입니다.

var a = { b : function (){ return '3'; } } // a.b() = 3 // function 의 익명함수는 메소드 function ag(){ return '3'; } // 위의 함수는 함수

◎ 콜백함수 (변수 = 전부 객체)

▼ 내용

함수 , 변수들은 전부 객체 입니다.

그렇기 때문에 함수는 값으로도 사용할수있습니다.

function ab(){ return 3; } var abcd = 3+ab(); console.log(abcd); //abcd = 6

​이렇게 ab()함수는 값으로 사용할수 있습니다. 이거와 비슷하게 함수는 값이기 때문에

인자로 전달 받을수도 있습니다.

function cal(func,num){ return func(num); } function increase(num){ return num+1; } console.log(cal(increase,2)); //3

위 처럼 cal 안에 또다른 함수를 넣는것을 콜백함수라 부릅니다.

또한 함수는() 이렇게 쓰면 실행이되지만 그냥 함수의 이름만 넣어줄경우엔

함수의 글자들만 넘어가서 마더함수가 실행될경우 로직에따라 콜백함수를 실행합니다.

또한 함수도 값이기 때문에 콜백함수도 값으로 취급하여 계산식등을 사용할수 있습니다.

함수는 이처럼 변수 , 매게변수 , 리턴값에 사용할수있는데 이러한 것들을

프로그래밍에서는 first-class citizen 또는 first-class object 등 뭐 이렇게 부릅니다.


◎ 클로저

▼ 내용

클로저는 (closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.

내부함수는 외부함수의 지역변수에 접근 할 수 있는데 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근 할 수 있다. 이러한 메커니즘을 클로저라한다.



반응형

+ Recent posts