File System 모듈이라는 뜻으로, 동기식, 비동기식 함수를 따로 구별해서 제공한다.
이번에는 비동기식, 그중에서도 콜백 함수를 사용하는 방법을 몇 가지 알아보려고 한다.
fs 모듈을 사용하기 위해서 require 하는 것을 잊지 말자.
const fs = require("fs");
현재 폴더에 있는 파일을 읽어오는 함수. readdirSync 하게 되면 동기로 처리할 수 있다. 자세한 것은 node.js의 Docs를 참고하면 된다. 이번에 우리가 살펴볼 것은 비동기로 처리하는 방법이다.
fs.readdir(path[, options], callback) = fs.readdir(path[, options], (err, files))
다음과 같이 함수와 매개변수를 배치한다. 우선 경로를 지정하고, 콜백을 지정한다. 옵션이 필요하다면 경로 뒤에 붙일 수 있다. []로 표시된것은 있어도 되고 없어도 된다는 의미이다. 다시 말하면, path와 callback은 반드시 들어가야 하는 매개변수라는 것이다.
callback 함수의 경우, err이라는 에러를 나타내는 변수와 가져온 내용을 저장할 files라는 변수가 매개변수로 사용된다.
const fs = require("fs");
fs.readdir("./", (err, files) => { // 파일이 있는 현재 폴더(./)에서 파일들을 가지고 오려고 한다.
if (err){
console.log(err);
}
console.log(files);
//에러가 나면 에러 메세지, 아니면 경로에 있는 files를 보여달라
});
[
'buffer.js', 'dir-1.js', 'dir-2.js',
'dir-3.js', 'dir-4.js', 'escape.js',
'example.txt', 'file-sol.js', 'list-1.js',
'list-2.js', 'list-3.js', 'myfile-1.js',
'myfile-2.js', 'myfile-3.js', 'path.js',
'read-3.js', 'readMe.txt', 'results',
'sol-1.js', 'sol-2.js', 'sol-3.js',
'stream-1.js', 'stream-2.js', 'unlink-1.js',
'unlink-2.js', 'unlink-3.js', 'write-1.js',
'write-2.js', 'write-3.js', 'write-4.js',
'write-5.js'
]
list-2.js 파일이 있는 폴더에 존재하는 모든 파일들이 나열된 모습을 확인할 수 있다.
이번에는 파일을 읽어오는 것과 파일에 어떤 내용을 저장하는 방법을 알아보자.
이번에도 비동기로 처리할 것이고, readFile과 writeFile이라는 함수를 사용할 것이다.
처음으로 해 볼것은 readFile 함수이다.
fs.readFile(path[, options], callback) = fs.readFile(path[, options], (err, data))
path와 callback 함수가 들어가고, callback에서는 err와 data라는 매개변수를 사용하고 있다.
readFile을 이용한 코드를 작성해보자.
const fs = require("fs");
fs.readFile("./example.txt", (err, data)=>{
if (err){
console.log(err);
}
console.log(data)
});
위 코드는 현재 폴더(./)의 example.txt 파일을 읽어 data에 저장하고, 오류가 발생하면 오류 메세지 아니라면 data로 가져온 값을 출력하라는 의미이다.
해당 코드를 실행한다면?
<Buffer 4e 6f 64 65 2e 6a 73 20 69 73 20 61 6e 20 6f 70 65 6e 2d 73 6f 75 72 63 65 2c 20 63 72 6f 73 73 2d 70 6c 61 74 66 6f 72 6d 20 4a 61 76 61 53 63 72 69 ... 110 more bytes>
이런 식으로 알아볼 수 없는 바이너리 코드로 들어가있다. 이것은 인코딩이라는 것을 지정하지 않았기 때문에 저장한 상태 그대로 가져왔기 때문이다. 이것을 사람이 이해할 수 있는 텍스트로 바꿔서 표현하려면 옵션 값으로 인코딩을 지정해줘야 한다.
인코딩 값은 callback 앞에다가 지정해준다.
fs.readFile("./example.txt", "utf8", (err, data)=>{
if (err){
console.log(err);
}
console.log(data)
});
Node.js is an open-source, cross-platform JavaScript runtime environment.
Node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다.
다음과 같이 "utf8"로 인코딩을 지정하니 txt파일의 내용을 그대로 가져와서 보여준다.
다시 한번 말하지만 인코딩을 지정하지 않으면, buffer라는 메모리 공간에 있는 상태 그대로 가지고 와서 보여준다.
다음으로는 파일을 기록하는 writeFile 함수이다.
기본 형태는 다음과 같다.
fs.writeFile(file, data[, options], callback) = fs.writeFile(file, data[, options], err)
file과 그것을 기록할 data, callback 함수가 들어가고, callback에서는 err라는 매개변수를 사용하고 있다.
자, 위에서 readFile을 통해 읽어 온 내용은 data에 저장되어 있다. 이것을 새로운 파일에 저장해보겠다.
fs.readFile("./example.txt", "utf8", (err, data)=>{
if (err){
console.log(err);
}
console.log(data)
fs.writeFile("./test.txt", data, (err) =>{
if(err){
console.log(err);
}
console.log('test.txt is saved');
})
});
위 코드는 readFile에서 읽어온 example.txt의 내용을 data에 저장하고, test.txt 파일을 새로 생성하여 data의 내용을 test.txt에 기록하는 작업을 한다.
test.txt is saved
실행 시 다음과 같은 메세지가 표시되고, test.txt 파일이 생성된다.
이외에도 다양한 기능을 하는 함수들이 fs모듈에 존재하므로 node.js 페이지에 들어가서 공부 해보는 것도 좋다.
이번에는 http 모듈을 이용해서 직접 서버를 만들어 볼 것이다. 그 전에 알아두어야 할 네트워크 개념에 대해 설명을 하고, 이어서 node.js에 있는 http 모듈을 이용해 서버를 만들어 보도록 하자.
웹은 클라이언트에서 서버로 무언가를 요청을 하면 서버가 그 요청을 처리하고 결과를 클라이언트에게 보내주는 방식으로 동작한다. 이때, 웹에서는 http라는 약속에 따라서 요청을 주고 처리를 한다. http를 어떻게 다루고, 어떠한 규칙을 사용하는지를 알아보게 될 것이다.
http 프로토콜이 어떤 식으로 처리되는지 알아보자.
크롬에서 개발자 도구창을 열어보자. (단축키 : ctrl + shift + i)

그리고 이곳에는 다음과 같이 네트워크라는 탭이 있다.
그리고 새로고침을 누르면?

그림과 같이 무언가 후다닥 지나간다. 이는 이 네트워크를 통해서 어떤 파일들이 오갔는지를 한눈에 확인할 수 있는것이다. 화면을 보여주기 위해서 서버에서 어떠한 파일들이 다운로드 되었는지를 보여주는 것이다.
여기서 www.google.com이라는 document를 눌러보면 다음과 같이 나온다.


요청 헤더라는 것은 우리가 화면을 보여달라고 www.google.com을 입력 후 enter를 눌러 서버로 요청이 전송되면 어떤 정보들이 이 헤더에 함께 담겨 전송된다.
여기서 중요하게 볼 것은 method인데 이는 요청 방식을 말한다. 여기서는 GET형식으로 요청했다. path는 경로를 말한다. 루트(/) 경로를 통해 GET방식으로 요청했다는 것을 알 수 있다.
응답 헤더는 뭘까? 우리가 www.google.com 사이트를 보내달라고 서버에 요청을 하면 서버에서 그 구글 사이트에 있는 파일들을 클라이언트로 보내주는데, 그 중 google.com 이라는 문서는 클라이언트로 보내지면서 여러가지 정보를 담고 있다. 그 정보들이 응답 헤더에 포함되어 있는 것이다.
일반 이라고 되어있는 것은 전체적인 네트워크 상태를 요약해서 보여주는 것이다.
요청 url, 요청 메서드, 상태 코드에 대해서는 앞으로 천천히 알아볼 것이다.

google.com 문서를 가져왔을 때 헤더 부분을 보면 원격 주소라고 되어있는 알 수 없는 숫자 표시를 볼 수 있는데, 이것이 ip 주소이다.인터넷 상에는 수많은 컴퓨터가 있기 때문에 어떠한 서버를 찾아가려면 주소가 필요하다. 이 서버 컴퓨터를 구별하기 위해 4개의 숫자로 구별해놓은것을 말한다.
서버에는 수많은 프로그램들이 존재하기 때문에 단순히 서버 컴퓨터를 찾는 것만으로는 부족하다. 앞의 ip 주소가 서버 컴퓨터를 찾아가는 주소였다면, 뒤의 443은 서버 안의 여러 프로그램 중 특정한 하나의 프로그램을 찾아가는 번호이다. 이를 포트 번호라고 한다.
포트를 지정을 할 때는 ip 주소 뒤에 :를 붙이고 뒤에 포트 번호를 적는다.
포트 번호는 미리 약속된 몇 가지 번호가 있다. 예를 몇가지 들자면
파일 전송 관련 : 20번, 21번
메일 관련 : 25번
웹 접속 관련 : 80번
그러나 우리는 공부하며 3000번, 5000번 등 약속 되어있지 않은 포트 번호를 사용할 것이다.
네트워크에 대한 기본 개념을 좀 확인했으니, 이제 직접 서버를 만들어 보도록 하자.
서버를 만들기 위해서는 node.js에 있는 http 모듈을 가져와서 사용하게 될 것이고, 그 http 모듈의 함수를 이용해서 만들게 될 것이다.
http 모듈에서는 서버를 만들 때, createServer라는 함수를 사용한다.
createServer : 모듈에서 서버를 만들 때 사용하는 함수
이 서버는 요청과 응답에 의해서 동작한다. 이 안에 callback함수를 하나 넣는다. req(요청)에 관한 변수와 res(응답)에 관한 변수를 사용할 것이다.
const http = require("http");
const server = http.createServer((req, res)=>{
console.log("요청 발생");
});
아직 request, response에 대한 처리를 하지 않고 콘솔 창에 표시하는 것만 넣어봤다.
이렇게 만든 서버로 끝인가?
아니다. 서버를 만들기는 했지만, 이를 실행 시켜주어야 한다.
서버를 실행시키기 위해서는 서버에 listen이라는 함수를 사용해주어야 한다.
listen : 서버를 실행시키기 위한 함수
실행을 시킬 때, 포트 번호를 지정해 주어야 한다.
server.listen(3000, () => {
console.log("서버가 실행 중");
});
서버 안의 여러개 프로그램 중 내가 만들고 있는 서버는 3000번 포트에서 실행해 달라는 의미이다. 또 서버가 실행 된 후 서버가 실행 중이라고 표시해 보겠다.
그러면 위에서 만든 코드를 합쳐서 실행시켜보자
const http = require("http");
const server = http.createServer((req, res)=>{
console.log("요청 발생");
});
server.listen(3000, () => {
console.log("서버가 실행 중");
});
PS C:\Users\user\Desktop\doit-node\basics\04> node server-1
서버가 실행 중
다음과 같이 서버가 만들어져서 실행 중인것을 확인할 수 있다.
그렇다면 "요청 발생"은 어디서 확인해야 할까? 우선 요청이 발생해야 한다.요청을 발생시키기 위해서는 웹 브라우저에서 내가 만든 서버로 무엇인가 보여 달라고 지정을 하면 된다. 바로 해보도록 하자.
웹 브라우저 창에서 localhost를 주소창에 입력하자.
localhost : 사용자 컴퓨터에 만들어진 서버를 가리키는 키워드
우리가 만든 서버를 가리키는 것이 바로 이 localhost이다. 우리가 만든 포트번호는 3000이었으니 localhost 뒤에 : 와 3000을 붙여주자.

이렇게 입력 후 enter를 누르면 지금 요청을 보낸것이다. 요청을 어떻게 처리할 것인지는 지정하지 않았기 때문에 브라우저 창에는 변화가 없다.
PS C:\Users\user\Desktop\doit-node\basics\04> node server-1
서버가 실행 중
요청 발생
다음과 같이 요청 발생이 표시된 것을 확인할 수 있다.
실행 중인 서버를 중지시키려면 ctrl + c를 눌러주면 된다. 이는 윈도우 Mac 모두 동일하다.
이번에는 요청과 응답이 어떻게 생겼는지 살펴보자. req가 어떤 정보를 담고 있는지 궁금하니 한번 열어보자.
const http = require("http");
const server = http.createServer((req, res)=>{
console.log(req);
});
server.listen(3000, () => {
console.log("서버가 실행 중");
});
"요청 발생" 대신 req를 넣었다.
localhost:3000을 실행하면 req안에 들어있는 여러 정보들이 출력된 것을 확인할 수 있을 것이다.
이번에는 응답 객체를 확인해보자.
응답 객체 안은 헤더와 본문으로 구성되는데 갖고 오는 정보, 즉 파일의 종류가 많기 때문에 가져올 때 어떤 자료, 파일을 가져오는지 헤더 안에서 처리해 줘야한다.
이번에는 웹 브라우저 창에 텍스트를 보여주는 코드를 작성해보자.
const http = require("http");
const server = http.createServer((req, res)=>{
res.setHeader("Content-type", "text/plain");
res.write("Hello Node");
res.end();
});
server.listen(3000, () => {
console.log("서버가 실행 중");
});
처리하려고 하는 것이 .txt 파일이기 때문에 응답 객체 res에 setHeader 함수를 사용해서 내가 사용할 콘텐츠 타입이 무엇인지 지정한다. text/plain은 일반 순수한 텍스트라는 의미이다.
화면에 뭔가를 표시해주려고 할 때는 응답 객체 res에 write 함수를 사용한다.
응답이 끝났을 때는 res.end();를 통해 끝이라는 것을 알려주면 된다.

이러면 localhost:3000을 실행했을 때, 웹 페이지에 다음과 같이 표시된 것을 확인할 수 있다.
이렇게 응답 객체(res)에 write라는 명령을 이용해서 브라우저 창에 내용을 표시해 보았다.
이렇게 createServer 안에 있는 callback 함수를 이용해 요청, 응답을 처리할 수 있다.