Node.js는 Browser에서 javascript로 할 수 없는 많은 놀라운 일들을 할 수 있게 만들어 주는데, 대표적으로 파일 시스템(File system)에서 파일을 읽고 쓰는 기능이다. Node.js에서 기본으로 제공하는 파일 시스템 모듈(module)을 사용하면 쉽게 구현할 수 있다.
syncFileSystem.js 파일에서 require() 함수를 사용해서 FS 모듈을 호출하면, 모듈 안에 우리가 사용할 수 있는 많은 함수들이 있는 객체가 반환된다. 반환된 객체를 fileSystem 변수에 담아서 파일 시스템에 데이터를 읽고 쓰는 기능이 필요할 때마다 사용할 수 있다.
요청과 그 결과가 동시에 일어난다
동기적 실행으로 파일 시스템에 접근해서 파일을 읽어오는 방식은 좋지 않다.
그 이유는 만약에 밑의 예제와 같이 파일을 읽은 후에 추가적으로 실행되야 하는 코드들이 있다면, 파일을 읽은 작업 동안 실행이 지연되기 때문이다.
각 줄은 나머지 코드의 실행을 차단하기 때문에 특히 느린 작업(파일을 읽는데 오래 걸리는 작업)에서는 문제가 될 수 있다.
요청과 결과가 동시에 일어나지 않을거라는 약속이다.
비동기 함수가 실행되면 작업이 끝날때까지 기다리는 것이 아니라, 백그라운드에 비동기 작업을 위임해주기 때문에 File I/O 작업이 오래 걸리더라도 추가적으로 실행되어야 하는 코드들에 영향을 주지 않는다.
※ 동기와 비동기 모두, 읽기와 쓰기가 목적이다. (파일 I/O작업)
privateInfomation.txt
파일에 접근해서 데이터를 읽고 쓰는 작업
순서
① filesystem 모듈 호출
② filesystem 모듈에 있는 readFileSync 메서드 호출
여기서 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
//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 작업이 오래 걸리더라도 추가적으로 실행되어야 하는 코드들에 영향을 주지 않는다.
readfile 함수를 읽고나서 callback 함수가 실행된다.
그래서 원본 파일이라는 메세지가 출력된다.
결과
그 다음으로 12번째 코드가 실행되고
14번째 코드가 실행되는데, writeFile이라고 하는 함수 역시 비동기적으로 파일을 읽어오는 코드이기 때문에, privateInformation.txt 파일에서 additionalinfo 쓰기작업을 수행한다.
그리고 나서 작업을 완료하면, 그 다음 콜백함수가 실행된다.
따라서, 쓰기 작업이 완전히 끝나고 나서야 다시 파일을 읽는 코드가 실행된다. 성공적으로 정보를 추가했다는 콘솔 메시지가 터미널 창에 출력되는 것이다.
클라이언트에서 사용자의 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] ]
와 같은 형태로 출력된다면, 여기를 참고하자.
후기(2023.01.21) : 이 당시에는 뭐가 뭔지 이해가 전혀가질 않아 과제를 제출하는 것에 급급하여 사실 코드를 따라치는 것에 급급했었다.
하지만 지금와서 코드를 천천히 살펴보니 이 코드가 프로젝트때 어떻게 이용되었어야했는지가 눈에 보인다.
※ 동기, 비동기 함수가 데이터를 읽고 불러올때, 어디서 작동하는지 위치를 알아야 후에 API 작성시 쉽게 이해할 수 있다.