상세 컨텐츠

본문 제목

callback 함수 활용하기 / 자바스크립트

언어/Javascript + Typescript

by moonionn 2020. 9. 16. 08:15

본문

콜백함수의 필요성

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'data', 'users.json');

const getUsersFromFile = () => {

  fs.readFile(filePath, (error, fileContent) => {
  
    if (error) return [];
    else return JSON.parse(fileContent);
    
  });
  
};

위 코드는 유저들의 정보를 get 하는 코드입니다.

이렇게 봐서는 아무 문제도 없어 보입니다.

하지만 만약 이 코드가 100줄이 넘는 텍스트의 일부라고 가정해봅시다.

그렇다면, 예상치 못한 결과를 마주할 수도 있습니다.

 

왜?!

javascript는 싱글스레드이자, 논블로킹 I/O의 성격을 지니고 있기 때문입니다.

자세한 내용은 여기...

 

위에서 쓴 fs.readFile()과 같은 기능은 파일 데이터 크기에 따라

오래 걸릴 수도 있는 작업이기 때문에 작업순서가 뒤로 밀려납니다.

따라서 우리가 원하는 결과를 얻지 못하게 됩니다.

 

 

콜백함수 이용

이런 난감한 상황을 해결하기 위해 callback 함수를 이용합니다.

아까 생성했던 코드 중 getUsersFromFile() 에 callback 인자를 추가합니다.

그리고 불러올 데이터를 callback()의 인자로 넣습니다.

const path = require('path');

const filePath = path.join(__dirname, 'data', 'users.json');

// 👇함수 인자에 callback
const getUsersFromFile = (callback) => {

  fs.readFile(filePath, (error, fileContent) => {
  
    //👇callback()의 인자에 불러올 데이터
    if (error) return callback([])
    else return callback(JSON.parse(fileContent));
    
  });
  
};

 

고작 그런걸로 뭐가 달라지나요?

이해를 도와줄 새로운 함수를 생성해보겠습니다.

deleteUser()getUsersFromFile() 을 이용해 파일 안에서 특정 user를 삭제한 뒤 다시 저장하는 함수입니다.

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, 'data', 'users.json');


const getUsersFromFile = (callback) => {

  fs.readFile(filePath, (error, fileContent) => {
  
    if (error) return callback([])
    else return callback(JSON.parse(fileContent));
    
  });
  
};


const deleteUser = () => {

  getUsersFromFile((users) => {
  
    const leftUsers = users.filter(user => user.name !== 'moonionn');
    
    fs.writeFile(filePath, JSON.stringify(leftUsers), (error) => {
      if (error) console.log(error);
    });
    
  });
  
};

 

아래 deleteUser() 함수 안에서 호출되고 있는 getUsersFromFile()의 인자를 자세히 보면

인자가 함수의 형태라는 걸 알 수 있습니다. 즉, 익명함수가 인자로 들어오게 되는 것이죠.

따라서 우리가 getUsersFromFile()에 넣어둔 인자 callback이 곧 스크롤된 영역의 함수가 됩니다.

 

자 이제 순서를 다시 보면

  1. deleteUser() 실행
  2. 내부에서 getUsersFromFile(callback) 실행
  3. getUsersFromFile(callback) 실행도중 내부에서 callback() 코드 맞닥뜨림
  4. callback()이 호출되면 인자로 들어온 익명함수 실행

이렇게 함수들이 호출되는 순서가 정해져 있기 때문에

비동기 함수를 제어할 수 있습니다.

 

 

따라서 [], 혹은 JSON.parse(fileContent)

익명 함수의 인자(여기서는 users)로 들어옵니다.

 

 

실행결과

JSON 파일

// 기존 파일

[
  {
    name: 'moonionn',
    age: 26,
    married: false
  }, {
    name: 'joe jay',
    age: 24,
    married: true
  } 
]

// -------------------------- //

// 변경 후

[
  {
    name: 'joe jay',
    age: 24,
    married: true
  } 
]

 

관련글 더보기

댓글 영역