Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

체대출신 코더의 개발자 성장기

TIL 서버 - promise와 async await 본문

카테고리 없음

TIL 서버 - promise와 async await

미토콘크리트 2019. 6. 21. 23:24

오늘은 비동기의 대표적인 처리방식인  promise와 async await을 학습했다.

그전에 어제 필기 해놓은 것들이 다 날아가서..  어제 배운것 부터 오늘 배운것들까지 적어 보겠다.

 

1) require (checkpotint)

 require으로 인해 불려오는 것은 exports.module객체의 주소이다.

 또한 require로 파일을 부르면  파일을 부른 기록(캐시)가 남는다.

따라서 중복으로 같은 파일을 부르는 것을 방지해준다. 

 

2) MVC 패턴

모델 - 뷰 - 컨트롤러 패턴

말만들었을때는 무슨 말이지 잘 와닿지 않았다.

오늘 설명 해 주신 것 으로는 내가 원래 알던  '클라이언트(뷰)-브라우저(컨트롤러)-서버(모델)'의 개념과 비슷해보였다.

 

뷰는 보여지길 원하는 데이터를 요청하고, 받은 데이터를 보여주는 역할을 한다.

컨트롤러는 모델로 부터 데이터를 받아 뷰에게 전해준다

모델은 뷰의 요청에 따라 요청된 데이터를 컨트롤러에게 전달한다.

 

서버에서 라우터를 구분해주는 것에 대해 학습할때 배웠음

따로 구분하지않아도 기능상에 큰 문제는 없으나 

구분을 위해 사용한 디자인 패턴이라고 배웠다.

 

==> 모호한 개념이라 다시 공부 할 것

 

3) app.use(cors())

"OPTIONS" 요청을 처리하는 메서드이다. 

cors의 매개변수로서 메서드들을 필터링 할 수 있다.

이 한줄로 그 동안 길게 작성했던 것들이 모두 처리된다니.. 이 얼마나 위대한가.. 

 

4) express 사용시 http를 사용하지 않는 것에 대한 의문점

express 로 코드를 다시 작성하면서 http를 require해서 쓰지 않는데 왜 제대로 동작하는지에 대한 의문이 있었다.

오늘 세션 때 질문을 드렸었는데, express 모듈 내에 http를 호출하는 기능이 있다고 한다.

express의 위대함을 다시한번 깨달았다.

 

5) 비동기 처리

비동기 처리는 원하는 결과를 원하는때에 출력할 수 없도록 만들지만

동시에 뭔가를 진행할 수 있도록 만들어주기 때문에 시간 측면에서 높은 효율성을 지닌다.

하지만 내가 원하는대로 순서를 정할 수 없다는 단점이 있는데

이것을 커버하기 위해 '콜백 함수'를 이용한다.

 5-1) 콜백함수를 이용한 비동기 순서 처리

 콜백함수B를 비동기 처리하는 A함수가 있다. 

 B안에서 C를 콜백함수를 처리하는 A함수를 만들면 어떻게 될까?

function A(callback) {
	$.get('https://domain.com/products/1', function (response) {
		callback(response); 
        });
}

 

A(response, function (id) {
	B(id, function (result) {
		C(result, function (text) {
			console.log(text);
		});
	});
});

이런식으로 될것이다. 

이게 많아지면 

콜백함수

이렇게 될 것 이다.

 

이렇게 되면 기능상에 문제는 없겠지만, 나중에 협업이나 다시 유지보수하는 과정에서 크게 애먹을 수도 있다.

따라서 

function A(id) {
	auth(id, B);
}
function B(result) {
	display(result, C);
}
function C(text) {
	console.log(text);
}

위와 같이 콜백으로 계속 불러주는 방식으로 간단히 만들어 줄 수 있을 것 이다.

이러한 비동기에 대한 고민을 개발자들이 많이 했나보다.

다음에 다룰 주제는 비동기 콜백을 더 쉽게 표현할수있는 Promise와 async&await이다.

참고자료 : 캡틴판교의 자바스크립트 비동기 처리와 콜백 함수

 

자바스크립트 비동기 처리와 콜백 함수

(중급) 중급 자바스크립트 개발자가 되기 위한 자바스크립트 비동기 처리와 콜백 함수 이해하기. 콜백 지옥과 해결 방법 등

joshua1988.github.io

 

5-2) Promise 

프로미스또한 비동기적인 과정을 처리하는 것인데 우리가 쓰는 언어에 가깝게 만들어졌다.

promise는 new Promise()를 통해 만들 수 있으며, 이안에 들어가는 매개변수는 데이터가 무사히 처리되었을때의 메서드인 

resolve와 에러가 나면 실행될 reject 가 있다. 

function getData(callback) {
  // new Promise() 추가
  return new Promise(function (resolve, reject) {
    $.get('url 주소/products/1', function (response) {
      // 데이터를 받으면 resolve() 호출
      reject(new Error("Request is failed"))
      if(response){
      resolve(response);
      }
    });
  });
}

위의 getdata를 외부에서 사용할 때 resolve에서 실행되는 결과는 .then에서 받아볼 수 있다.

에러가 떳을때 나오는 결과(reject)는 .catch를 통해 받아 볼 수 있다. (항상 마지막에 써줘야함) 

getData()
.then(res => 
console.log(res)) // resolve에서 실행된 결과
.catch(function (err) { //reject에서 에러난 결과
  console.log(err); // Error: Request is failed
});

이런식으로 쓰면 여러가지 프로미스를 다음과 같이 연결하는 것도 가능하다.

이것을 promise channing이라고 한다.

new Promise(function(resolve, reject){
  setTimeout(function() {
    resolve(1);
  }, 2000);
})
.then(function(result) {
  console.log(result); // 1
  return result + 10;
})
.then(function(result) {
  console.log(result); // 11
  return result + 20;
})
.then(function(result) {
  console.log(result); // 31
});

 

프로미스는 비동기적인 상태를 다루기 때문에 그 상태를 세가지로 구분한다.

pending ,  fulfilled, rejected 인데 

pending :  말그대로 대기 상태이다. 비동기적인 동작이 시행하는 상태로서 이때 resolve와 reject메서드를 이용해서 제어하는 것이다.

또한 이때의 값을 콘솔로 찍으면 {<Pending..>} 뭐 이런식으로 뜨는데. Assume .. 어쩌고 하면서 값은 찍힌다.

처음에 콘솔이 제대로 찍히는 줄 알았지만, 예전에 배열이나 객체가 나중값을 미리 보여줘서 고생했던 것 처럼 비동기 처리가 끝나면 이런식으로 나온다.. 라는 뜻으로 뭔가 떳던 거지, 실제 자바스크립트가 사용할 수 있는 상태는 아닌 것 이다.

이 상태를 해제해주기 위해서는 Promise.all([value]) 의 기능이 필요하다. 

대기상태인 값들을 배열의 상태로 Promise.all 에 인자로 넣어주면, 넘겨진 배열내의 대기상태가 모두 풀린다.

 

fulfilled : 대기상태가 풀려서 실제로 자바스크립트에서 사용할 수 있는 상태를 말한다.

then을 통해 resolve값을 받아오면 이상태이고, 방금 언급한 Promise.all을 이용해서도 fulfilled상태로 만들 수 있다.

여기서 기억할 것은 then내에서는 가공한 값을 return 해줘야 fulfilled된 상태로 다음then으로 넘어갈 수 있다.

 

rejected : reject메서드가 실행되면 생기며, catch를 이용해서 어디서 오류가 났는지 확인이 가능하다. 

 

 * util의 기능중에 라는 기능이 있는데

   util.promisty 하면 가져온 파일을 자동으로 프로미스화 시켜주는 것 같다. 대단한 자바스크립트...

https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original

 

참고자료 : 캡틴판교 님 블로그

 

자바스크립트 Promise 쉽게 이해하기

(중급) 자바스크립트 입문자를 위한 Promise 설명. 쉽게 알아보는 자바스크립트 Promise 개념, 사용법, 예제 코드. 예제로 알아보는 then(), catch() 활용법

joshua1988.github.io

참고자료2 : 프로미스 메소드 기능 

 

Promise API

 

javascript.info

참고자료3 :프로미스all의 기능에 대해 자세히 알아보자

 

5-3) async await

then을 이용한 channing현상을 방지할 수 있고, 가독성이 매우 뛰어나다는 장점이 존재한다.

const fetchUsersAndWriteToFileAsync = async (readFilePath, writeFilePath) => {
  //*******************************************************************
  //1. userId를 받아온다.
  let userId = await getDataFromFilePromise(readFilePath);
  //2. 주소와 Id를 합쳐 객체를 받아올 수 있는 주소를 만들어 준다.
  userId = userId.map(url => BASE_URL + url);
  //*******************************************************************

  //3.반복문을 통해 메소드로 주소를 넣어주고, 주소에 맞는 객체를 받아온다.
  //  반복문 사용시 다음과 같이 async 와 await을 붙혀 사용해준다.
  let getUrl = userId.map(async url => await getBodyFromGetRequestPromise(url));
  //4. 위의 상태로 받아온 배열은 현재 pending상태이므로, Promise.all을 이용해 Pending상태를 해제해준다.
  getUrl = await Promise.all(getUrl);
  //*******************************************************************

  //5. 케이스에서 원하는 형식으로 배열을 변형시킨뒤, fs에 write해준다.
  let getName = getUrl.map(info => info.name + "\n");
  getName = getName.join("").split();
  return writeFilePromise(writeFilePath, getName);
};

스프린트를 진행하면서 사용한 코드인데

반복문을 사용할때 저런식으로 사용하는게 의아해서 조사를 해보니 함수앞에 async를 달아주고 비동기적인 작동을 시킬 메서드 앞에 await을 붙혀 줘야한다고 한다.

처음에 await자체가 뭔가 멈추는 기능이라 원하는 값이 잘 나올 줄 알았는데

결과는 pending중인 배열이 나왔다..

따라서 해결방법은 여러가지가 있겠지만 나는 await Promise.all(value)를 사용해 pending상태를 모두 풀어주었다.

이전의 코드는 모두 20줄 가까이 되고 사용해야할 모듈이 많아 가독성도 떨어지고 귀찮은게 이만저만이 아니었는데

이렇게 간편한 방법이 있어 참 신기했다.

참고자료 : https://javascript.info/async-await

 

Async/await

 

javascript.info

참고자료2 : async await에서 반복을 처리하는 방법

https://lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795/

 

JavaScript loops - how to handle async/await

How to run async loops in sequence or in parallel? Before doing asynchronous magic with loops I want to remind you how we write classical…

lavrton.com

 

6) 원래 request는 http와 연동되어 쓰는 줄 알았는데

  독자적으로 만들어진 도구가 있었다.  url을 통해 서버의 데이터를 받아오는게 가능하다.

참고 자료

https://medium.com/harrythegreat/node-js%EC%97%90%EC%84%9C-request-js-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-28744c52f68d

 

Node.js에서 Request.js 사용하기

네트워크 더 간결하게 작성하자!

medium.com

 

쓰고 싶은게 더 있는데 집에 가야하니 여기서 줄이겠다..

Comments