top

현재시간 ( 04:55:15), 시스템이 작동된 시간 ( 2 days 1:56 ), 로그인해 있는 유저 수 ( 3 users ) 

1 분 , 5분, 15분의 load average ( 0.00, 0.00, 0.00 ) : 

* load average : cpu 나 disk I/O 을 기다리고 있는 프로세스의 평균수, 시스템이 얼마나 바쁜지를 측정하는 것

 

Tasks

총 113 프로세스가 있고, 1 개가 실행 중, 112 개는 대기 중, 0개 중지, 0 좀비

* zombie process :  실행이 끝났는데 여전히 프로세스 테이블에 존재하는 프로세스

 

%Cpu(s) : cpu가 사용된 시간의 비율

표현  의미
0.0 us (user) 유저 프로세스를 실행하는데 cpu 가 사용 시간의 비율 (%) 
0.0 sy (system) 시스템 프로세스 
0.0 ni (nice) 우선순위가 낮춰진 사용자 프로세스를 실행하는데 사용된 cpu 시간의 비율
100.0 id (idle) 사용되지 않는 CPU의 비율, 현재 어떠한 작업도 처리하고 있지 않음
0.0 wa (wait) I/O 작업을 완료하기 위해 대기하는 동안 사용된 CPU 시간의 비율
0.0 hi (hardware IRQ :Interrupt request) 하드웨어 인터럽트를 처리하는 데 사용된 CPU 시간의 비율
0.0 si (software IRQ) 소프트웨어 인터럽트를 처리하는 데 사용된 CPU 시간의 비율
0.0 st (steal) 가상화 환경에서 다른 가상 머신으로부터 '도둑질된' 가상 CPU의 CPU 시간 비율

 

Memory Usage

MiB (mebibyte) Mem : 총 물리적인 메모리 957.4, 68 여유, 878.6 사용 중, 쓰기위해 버퍼링된 정보의 양 162.4

MiB Swap : 총 가상 메모리 0.0 , ....,  swapping 없이 새로운 어플리케이션을 시각하기위해 가능한 메모리양 78.9

 

PID USER PR NI VIRT RES
프로세스 아이디 프로세스를 소유하고 있는 유저 프로세스의 우선순위 Nice value 프로세스가 사용하고 있는 가상 메모리 가상메모리의 하위집합, 현재 작업이 사용중인 비스왑된 물리적 메모리
SHR S %CPU %MEM TIME+ COMMAND
공유된 메모리 사이즈 프로세스 상태
'S' : sleeping
프로세스에 의해서 사용되고 있는 cpu 비율 프로세스에 의해서 사용되는 메모리의 비율 총 cpu 사용 시간 프로세스를 시작하는데 사용되는 명령이름 또는 명령줄

 

PR  값의 범위 -[ -100, 39 ]

    [ -100, -2 ] : realtime process, 

    [ 0, 39 ] : 상대적으로 우선순위가 낮은 프로세스

 

NI 값의 범위 [-20 , 19 ] -  유저가 지정가능

 

 

 

참고자료

https://www.redhat.com/sysadmin/interpret-top-output

https://www.baeldung.com/linux/top-command

https://unix.stackexchange.com/questions/390518/what-do-the-buff-cache-and-avail-mem-fields-in-top-mean

async 함수

async는 function 앞에 위치합니다.

function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환합니다. 

async function f(){
   return 1;
}

 

// 위와 같은 함수
async function f() {
  return Promise.resolve(1);
}

await 함수

await async 함수 안에서만 동작합니다. await는 말 그대로 프라미스가 처리될 때까지 함수 실행을 기다리게 만듭니다. 처리되면 그 결과와 함께 실행이 재개됩니다.

프라미스가 처리되길 기다리는 동안엔 다른 일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않습니다.

 

예시

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("완료!"), 1000)
  });

  let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)

  alert(result); // "완료!"
}

f();

 

 

await promise.then보다 좀 더 세련되게 프라미스의 result 값을 얻을 수 있도록 해주는 문법입니다.

 

promise .then 을   async/await 로 변환 예시

 

promise chaning 에서의 예시

fetch('/article/promise-chaining/user.json')
  .then(response => response.json()) // json 읽기
  .then(user => fetch(`https://api.github.com/users/${user.name}`)) // 사용자 정보 읽기
  .then(response => response.json())
  .then(githubUser => new Promise(function(resolve, reject) { // 아바타 보여주기
    let img = document.createElement('img');
    img.src = githubUser.avatar_url;
    img.className = "promise-avatar-example";
    document.body.append(img);

    setTimeout(() => {
      img.remove();
      resolve(githubUser); // 
    }, 3000);
  }))
  // 3초 후 동작함
  .then(githubUser => alert(`${githubUser.name}의 이미지를 성공적으로 출력하였습니다.`));

 

async / await  로 변환

async function showAvatar() {

  // JSON 읽기
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // github 사용자 정보 읽기
  let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
  let githubUser = await githubResponse.json();

  // 아바타 보여주기
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // 3초 대기
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
}

showAvatar();

 

 

 

다른 사용예시들

(async () => {
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();
  ...
})();

 

 

에러 핸들링

try{ ... } catch { ... } 를 이용

async function f() {

  try {
    let response = await fetch('http://유효하지-않은-주소');
    let user = await response.json();
  } catch(err) {
    // fetch와 response.json에서 발행한 에러 모두를 여기서 잡습니다.
    alert(err);
  }
}

 

 

다시던지기를 이용한 코드 예시

 

.then 이용

class HttpError extends Error {
  constructor(response) {
    super(`${response.status} for ${response.url}`);
    this.name = 'HttpError';
    this.response = response;
  }
}

function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new HttpError(response);
      }
    })
}

// 유효한 사용자를 찾을 때까지 반복해서 username을 물어봄
function demoGithubUser() {
  let name = prompt("GitHub username을 입력하세요.", "iliakan");

  return loadJson(`https://api.github.com/users/${name}`)
    .then(user => {
      alert(`이름: ${user.name}.`);
      return user;
    })
    .catch(err => {
      if (err instanceof HttpError && err.response.status == 404) {
        alert("일치하는 사용자가 없습니다. 다시 입력해 주세요.");
        return demoGithubUser();
      } else {
        throw err;
      }
    });
}

demoGithubUser();

async/ awiat 이용

class HttpError extends Error {
  constructor(response) {
    super(`${response.status} for ${response.url}`);
    this.name = 'HttpError';
    this.response = response;
  }
}

async function loadJson(url) {
  let response = await fetch(url);
  if (response.status == 200) {
    return response.json();
  } else {
    throw new HttpError(response);
  }
}

// 유효한 사용자를 찾을 때까지 반복해서 username을 물어봄
async function demoGithubUser() {

  let user;
  while(true) {
    let name = prompt("GitHub username을 입력하세요.", "iliakan");

    try {
      user = await loadJson(`https://api.github.com/users/${name}`);
      break; // 에러가 없으므로 반복문을 빠져나옵니다.
    } catch(err) {
      if (err instanceof HttpError && err.response.status == 404) {
        // 얼럿 창이 뜬 이후에 반복문은 계속 돕니다.
        alert("일치하는 사용자가 없습니다. 다시 입력해 주세요.");
      } else {
        // 알 수 없는 에러는 다시 던져집니다.
        throw err;
      }
    }
  }


  alert(`이름: ${user.name}.`);
  return user;
}

demoGithubUser();

 

예제

 

aysnc / await 이용하여 코드변경

function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new Error(response.status);
      }
    })
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404

 

      변경

async function loadJson(url) { // (1)
  let response = await fetch(url); // (2)

  if (response.status == 200) {
    let json = await response.json(); // (3)
    return json;
  }

  throw new Error(response.status);
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404 (4)

 

 

참고자료

https://ko.javascript.info/async-await

프라미스화

콜백을 받는 함수를 프라미스를 반환하는 함수로 바꾸는 것을 '프라미스화(promisification)'라고 합니다.

이는 자바스크립트에서 비동기 작업을 더 깔끔하게 처리할 수 있게 해줍니다.

따라서 콜백보다는 프라미스가 더 편리하기 때문에 콜백 기반 함수와 라이브러리를 프라미스를 반환하는 함수로 바꾸는 게 좋은 경우가 생깁니다.

 

예시 코드

 콜백

function loadData(callback) {
  setTimeout(() => {
    callback('데이터 로드 완료');
  }, 1000);
}

loadData(data => {
  console.log(data); // 데이터 로드 완료
});

 

 프라미스화

function loadData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('데이터 로드 완료');
    }, 1000);
  });
}

loadData().then(data => {
  console.log(data); // 데이터 로드 완료
});

 

f가 두 개를 초과하는 인수를 가진 콜백, callback(err, res1, res2, ...)을 받는경우 처리하는 방법

새롭게 만든 함수를 promisify(f, true)형태로 호출

// 콜백의 성공 결과를 담은 배열을 얻게 해주는 promisify(f, true)
function promisify(f, manyArgs = false) {
  return function (...args) {
    return new Promise((resolve, reject) => {
      function callback(err, ...results) { // f에 사용할 커스텀 콜백
        if (err) {
          reject(err);
        } else {
          // manyArgs가 구체적으로 명시되었다면, 콜백의 성공 케이스와 함께 이행 상태가 됩니다.
          resolve(manyArgs ? results : results[0]);
        }
      }

      args.push(callback);

      f.call(this, ...args);
    });
  };
};

// 사용법:
f = promisify(f, true);
f(...).then(arrayOfResults => ..., err => ...)

 

 

참고자료

https://ko.javascript.info/promisify

프라미스 API

Promise.all( promises )

주어진 배열에 있는 모든 프로미스가 이행될 때까지 기다렸다가 그 결과값을 주어진 배열의 순서에 따라 반환합니다.

 예시

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(alert); // [1,2,3] 반환

 

배열 속 프로미스중 하나라도 실패를 하면 promise.all  전체가 거부되고 에러가 반환됩니다.

   예시

Promise.all([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("에러 발생!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).catch(alert); // Error: 에러 발생!

Promise.allSettled( promises )

최근에 추가된 문법

Promise.all 과 다르게 여러개의 요청 중에 하나가 실패해도 다른 성공된 결과와 함께 반환

여러 요청 중 하나가 실패해도 다른 요청 결과는 여전히 필요한 경우에 유용한 메서드

     

요청 예시

let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/Violet-Bora-Lee',
  'https://no-such-url'
];

Promise.allSettled(urls.map(url => fetch(url)))
  .then(results => { // (*)
    results.forEach((result, num) => {
      if (result.status == "fulfilled") {
        alert(`${urls[num]}: ${result.value.status}`);
      }
      if (result.status == "rejected") {
        alert(`${urls[num]}: ${result.reason}`);
      }
    });
  });

 

결과 예시

[
  {status: 'fulfilled', value: ...응답...},
  {status: 'fulfilled', value: ...응답...},
  {status: 'rejected', reason: ...에러 객체...}
]

 

만약에 브라우저가 promise.allSettled 를 지원하지 않는다면 폴리필을 구현

   폴리필? 브라우저에서 지원하지 않는 코드를 사용한 가능한 코드나 프롤그인으로 변환 한 코드를 의미합니다.

if(!Promise.allSettled) {
  Promise.allSettled = function(promises) {
    return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({
      status: 'fulfilled',
      value
    }), reason => ({
      status: 'rejected',
      reason
    }))));
  };
}

 

Promise.race( promises )

Promise.all과 비슷하지만 가장 먼저 처리되는 프라미스의 결과(혹은 에러)를 반환합니다.

 예시

Promise.race([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("에러 발생!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert); // 1

 

Promise.resolve( value )

주어진 값을 이용하여 이행 상태의 프라미스를 만듭니다.

Promise.reject( error )

주어진 에러를 사용해 거부 상태의 프라미스를 만듭니다

 

* 메서드 Promise.resolve Promise.reject async/await 문법이 생긴 후로 쓸모없어졌기 때문에 근래에는 거의 사용하지 않습니다.

 

참고자료

https://ko.javascript.info/async

프라미스와 에러 핸들링

암시적 try…catch

체인 마지막의 .catch는 try..catch와 유사한 역할을 합니다.

 .then 핸들러를 원하는 만큼 사용하다 마지막에 .catch 하나만 붙이면 .then 핸들러에서 발생한 모든 에러를 처리할 수 있습니다.

 

.catch 는 프라미스에서 발생한 모든 에러를 다룹니다. reject()가 호출되거나 에러가 던져지면 .catch에서 이를 처리합니다.

 

예시

new Promise((resolve, reject) => {
  resolve("OK");
}).then((result) => {
  throw new Error("에러 발생!"); // 프라미스가 거부됨
}).catch(alert); // Error: 에러 발생!
new Promise((resolve, reject) => {
  resolve("OK");
}).then((result) => {
  blabla(); // 존재하지 않는 함수
}).catch(alert); // ReferenceError: blabla is not defined

예시에서 보듯 .catch는 첫번째 핸들러일 필요가 없고 하나 혹은 여러 개의 .then 뒤에 올 수 있습니다.

 

사이트에는 아무런 문제가 없지만 응답으로 받은 JSON의 형식이 잘못된 경우를 살펴봅시다.

가장 쉬운 에러 처리 방법은 체인 끝에 .catch 를 붙이는 것입니다.

fetch('/article/promise-chaining/user.json')
  .then(response => response.json())
  .then(user => fetch(`https://api.github.com/users/${user.name}`))
  .then(response => response.json())
  .then(githubUser => new Promise((resolve, reject) => {
    let img = document.createElement('img');
    img.src = githubUser.avatar_url;
    img.className = "promise-avatar-example";
    document.body.append(img);

    setTimeout(() => {
      img.remove();
      resolve(githubUser);
    }, 3000);
  }))
  .catch(error => alert(error.message));

 정상적인 경우라면 .catch 는 절대 트리거 되지 않습니다. 하지만, 네트워크 문제, 잘못된 형식의 JSON 등으로 인해 위쪽 프라미스 중 하나라도 거부 되면 .catch 에서 에러를 잡게 됩니다.

 

다시 던지기

 try..catch에선 에러를 분석하고, 처리할 수 없는 에러라 판단되면 에러를 다시 던질 때가 있습니다.

프라미스에도 유사한 일을 할 수 있습니다.

.catch 안에서 throw 를 사용하면 제어 흐름이 가장 가까운 곳에 있는 에러 핸들러로 넘어갑니다.

여기서 에러가 성공적으로 처리되면 바로 다음 .then 핸들러로 제어 흐름이 넘어가 실행이 이어집니다.

 

예시

new Promise((resolve, reject) => {

  throw new Error("에러 발생!");

}).catch(function(error) {

  alert("에러가 잘 처리되었습니다. 정상적으로 실행이 이어집니다.");

}).then(() => alert("다음 핸들러가 실행됩니다."));

    - catch 에서 정상적으로 종료되었기 때문에 다음 성공핸들러 .then 이 호출 되것을 확인 가능합니다.

 

catch 에서 에러를 처리하지 못한 예시

 // 실행 순서: catch -> catch
new Promise((resolve, reject) => {

  throw new Error("에러 발생!");

}).catch(function(error) { // (*)

  if (error instanceof URIError) {
    // 에러 처리
  } else {
    alert("처리할 수 없는 에러");

    throw error; // 에러 다시 던지기
  }

}).then(function() {
  /* 여기는 실행되지 않습니다. */
}).catch(error => { // (**)

  alert(`알 수 없는 에러가 발생함: ${error}`);
  // 반환값이 없음 => 실행이 계속됨

});

 

처리되지 못한 거부

에러를 처리해줄 핸들러가 없으면 에러가 갇혀버리게 됩니다.

  예시

new Promise(function() {
  noSuchFunction(); // 존재하지 않는 함수를 호출하기 때문에 에러가 발생함
})
  .then(() => {
    // 성공상태의 프라미스를 처리하는 핸들러. 한 개 혹은 여러 개가 있을 수 있음
  }); // 끝에 .catch가 없음!

 이런 경우 스크립트가 죽고 자바스크립트 엔진은 전역 에러를 생성합니다.

이떄 콘솔 창을 열어 확인하면 전역 에러를 확인 가능합니다.

브라우저 환경에서는 이러한 에러를 unhandledrejection 이벤트로 처리할 수 있습니다.

window.addEventListener('unhandledrejection', function(event) {
  // unhandledrejection 이벤트엔 두 개의 특수 프로퍼티가 있습니다.
  alert(event.promise); // [object Promise] - 에러를 생성하는 프라미스
  alert(event.reason); // Error: 에러 발생! - 처리하지 못한 에러 객체
});

new Promise(function() {
  throw new Error("에러 발생!");
}); // 에러를 처리할 수 있는 .catch 핸들러가 없음

     이런 에러는 회복할 수 없기 때문에 최선의 방법은 사용자에게 문제 상황을 알리고 가능하다면 서버에 에러 정보를 보내는 것입니다.

 

.catch 가 실행되지 않는 예제

new Promise(function(resolve, reject) {
  setTimeout(() => {
    throw new Error("에러 발생!");
  }, 1000);
}).catch(alert);

  위 예시에서는 executer 가 실행되는 동안이 아니라 나중에 에러가 발생합니다. 그래서 프라미스는 에러를 처리 할 수 없습니다.

 

참고자료

https://ko.javascript.info/async

+ Recent posts