동기와 비동기

HS K·2022년 12월 6일
0

Built-in modules - File system module

Node.js는 Browser에서 javascript로 할 수 없는 많은 놀라운 일들을 할 수 있게 만들어 주는데, 대표적으로 파일 시스템(File system)에서 파일을 읽고 쓰는 기능이다. Node.js에서 기본으로 제공하는 파일 시스템 모듈(module)을 사용하면 쉽게 구현할 수 있다.

syncFileSystem.js 파일에서 require() 함수를 사용해서 FS 모듈을 호출하면, 모듈 안에 우리가 사용할 수 있는 많은 함수들이 있는 객체가 반환된다. 반환된 객체를 fileSystem 변수에 담아서 파일 시스템에 데이터를 읽고 쓰는 기능이 필요할 때마다 사용할 수 있다.


1. 동기

요청과 그 결과가 동시에 일어난다

동기적 실행으로 파일 시스템에 접근해서 파일을 읽어오는 방식은 좋지 않다.
그 이유는 만약에 밑의 예제와 같이 파일을 읽은 후에 추가적으로 실행되야 하는 코드들이 있다면, 파일을 읽은 작업 동안 실행이 지연되기 때문이다.
각 줄은 나머지 코드의 실행을 차단하기 때문에 특히 느린 작업(파일을 읽는데 오래 걸리는 작업)에서는 문제가 될 수 있다.


2. 비동기

요청과 결과가 동시에 일어나지 않을거라는 약속이다.

비동기 함수가 실행되면 작업이 끝날때까지 기다리는 것이 아니라, 백그라운드에 비동기 작업을 위임해주기 때문에 File I/O 작업이 오래 걸리더라도 추가적으로 실행되어야 하는 코드들에 영향을 주지 않는다.


※ 동기와 비동기 모두, 읽기와 쓰기가 목적이다. (파일 I/O작업)


3. 예시

privateInfomation.txt 파일에 접근해서 데이터를 읽고 쓰는 작업


순서

① filesystem 모듈 호출
② filesystem 모듈에 있는 readFileSync 메서드 호출

  • 여기서 readFileSync의 첫번째 인자는 파일이 위치한 경로, 두번째는 인코딩을 정의하기 위해 필요한 인자이다.


1. 동기 : fileSystem.readFileSync()

동기적으로 실행된다는 의미이며, 함수가 호출되어 실행된 후에 값을 반환할 때까지 기다린 후에 다음 코드를 실행하게 된다. 아래와 같이 코드가 순차적으로 실행되는 것을 확인할 수 있다.

$ node syncFileSystem.js

===== Before written =====
Name : Harry Potter
Age  : 22

===== Successfully File written! =====

===== After written =====
Name        : Harry Potter
Age         : 22
PhoneNumber : 010-7777-0000
Modified at : 1653178357269

===== 추가적으로 실행되어야 하는 코드 =====
추가적으로 실행되어야 하는 코드 1
추가적으로 실행되어야 하는 코드 2
추가적으로 실행되어야 하는 코드 3
추가적으로 실행되어야 하는 코드 4
// privateInfomation.txt
// after written!

Name        : Harry Potter
Age         : 22
PhoneNumber : 010-7777-0000
Modified at : 1653178357269

Node.js는 브라우저와 다르게 운영체제에서 기본적으로 제공하는 주된 서비스(예를 들어서, 파일 I/O 작업)들에 바인딩할 수 있는 기능을 제공해준다는 것을 확인할 수 있다.

바인딩 : 프로그램에 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는 행위
ex)

int num = 123;
  • num 는 변수의 이름
  • int 는 변수의 자료형
  • 123 은 변수의 자료값

    이라는 변수의 속성의 구체적인 값이다.
    위와 같이 이름, 자료형, 자료값에 각각 num, int, 123 이라는 구체적인 값을 할당하는 각각의 과정을 바인딩이라고 한다.


    출처 : https://medium.com/pocs/바인딩-binding-4a4a2f641b27

2. 비동기 : readFileSync()

//zsh
$ node asyncFileSystem.js

===== 추가적으로 실행되어야 하는 코드 =====
추가적으로 실행되어야 하는 코드 1
추가적으로 실행되어야 하는 코드 2
추가적으로 실행되어야 하는 코드 3
추가적으로 실행되어야 하는 코드 4

===== Before written =====
Name : Harry Potter
Age  : 22

===== Your file has been written =====

===== After written =====
Name        : Harry Potter
Age         : 22
PhoneNumber : 010-7777-0000
Modified at : 1653192110477

실행 결과를 확인해보면, 코드가 위에서부터 순차적으로 실행되는 것이 아니라 마지막에 있는 코드가 먼저 실행되고, 파일 읽기/쓰기 작업은 나중에 출력되는 것을 확인 할 수 있다.

비동기 함수가 실행되면 작업이 끝날때까지 기다리는 것이 아니라 백그라운드에 비동기 작업을 위임해주기 때문에 File I/O 작업이 오래 걸리더라도 추가적으로 실행되어야 하는 코드들에 영향을 주지 않는다.


4. 코드 패턴 이해하기

[읽기]

readfile 함수를 읽고나서 callback 함수가 실행된다.

그래서 원본 파일이라는 메세지가 출력된다.

결과


[쓰기]

그 다음으로 12번째 코드가 실행되고

14번째 코드가 실행되는데, writeFile이라고 하는 함수 역시 비동기적으로 파일을 읽어오는 코드이기 때문에, privateInformation.txt 파일에서 additionalinfo 쓰기작업을 수행한다.

그리고 나서 작업을 완료하면, 그 다음 콜백함수가 실행된다.

따라서, 쓰기 작업이 완전히 끝나고 나서야 다시 파일을 읽는 코드가 실행된다. 성공적으로 정보를 추가했다는 콘솔 메시지가 터미널 창에 출력되는 것이다.


5. 과제

클라이언트에서 사용자의 id, first_name, last_name, mobile_number와 각 사용자가 작성한 게시물 정보(게시물 id, title, content, userId)를 요청한 경우, users.csv와 posts.csv를 열어서 아래와 같은 결과를 만들어서 출력할 수 있는 코드를 작성해주세요.

  // 기대하는 결과
[
   {
      id: '1',
      firstName: 'Rebekah',
      lastName: 'Johnson',
      mobileNumber: '010-4600-3048',
      posts: [
	        {
                    id: '1', 
                    title: '위코드1일차', 
                    content: 'HTML과CSS익숙해지기',
                    userId: '1'
                },
                { 
                    id: '2', 
                    title: '위코드2일차', 
                    content: 'Javascript기본문법',
                    userId: '1'
                },
                {
                    id: '3', 
                    title: '위코드3일차', 
                    content: '웹서비스의역사와발전',
                    userId: '1'
                }
             ]
   },
   {
      id: '2',
      firstName: 'Fabian',
      lastName: 'Predovic',
      mobileNumber: '010-8529-4227',
      posts: [
                {
                    id: '5', 
                    title: '자료구조1번', 
                    content: 'BigONotation이란무엇',
                    userId: '2'
                },
                {
                    id: '6', 
                    title: '자료구조2번', 
                    content: '시간복잡도와공간복잡',
                    userId: '2'
                }
             ]
  },
  {
     id: '3',
     firstName: 'Elenor',
     lastName: 'Gottlieb',
     mobileNumber: '010-7876-2287',
     posts: [
               {
                   id: '7', 
                   title: '프론트개발입문', 
                   content: '프론트입문HTML이란',
                   userId: '3'
               }
            ]
   },
   {
      id: '4',
      firstName: 'Madge',
      lastName: 'Ledner',
      mobileNumber: '010-5153-1051',
      posts: []
   }
]

※ console.log() 함수를 사용해서 터미널상에 결과를 출력했는데, posts: [ [Object], [Object], [Object] ] 와 같은 형태로 출력된다면, 여기를 참고하자.


6. 풀이

후기(2023.01.21) : 이 당시에는 뭐가 뭔지 이해가 전혀가질 않아 과제를 제출하는 것에 급급하여 사실 코드를 따라치는 것에 급급했었다.
하지만 지금와서 코드를 천천히 살펴보니 이 코드가 프로젝트때 어떻게 이용되었어야했는지가 눈에 보인다.


  1. console을 통해 ("\n===== 성공적으로 정보 추가! ===== \n");
    를 확인하자.
  2. 블로킹 : 동기의 경우 파일을 읽은 후에 추가적으로 실행되어야 되는 중용한 코드들이 있다면 파일을 읽는동안 작업실행이 지연됨

※ 동기, 비동기 함수가 데이터를 읽고 불러올때, 어디서 작동하는지 위치를 알아야 후에 API 작성시 쉽게 이해할 수 있다.

profile
주의사항 : 최대한 정확하게 작성하려고 하지만, 틀릴내용이 있을 수도 있으니 유의!

0개의 댓글