2021-12-13 BE

블로그 내 코드 자료 출처
Node.js 교과서 개정2판(지음이 조현영)

복습

노드 내장 모듈

아래 내용은 현재 우선순위 아래에 있다. 다음에 자습하자.

util

worker_threads

노드에서 멀티 스레드 방식으로 작업하는 방법

child_process

노드에서 다른 프로그램을 실행하고 싶거나 명령어를 수행하고 싶을 대 사용하는 모듈.

  • exec의 첫 번째 인수로 명령어를 넣는다.
    실행하면 현재 폴더의 파일 목록들이 표시된다.
    결과는 stdout, stderr

공부

파일 시스템 접근

fs

fs모듈은 파일 시스템에 접근하는 모듈이다. 즉, 파일을 생성하거나 삭제하고, 읽거나 쓸 수 있다. 폴더도 만들거나 지울 수 있다.

const fs = require('fs') // 모듈을 불러온다.
fs.readFile("./readme.txt", (err, data) => {
  if(err) {
    throw err //error처리
  }
  console.log(data) //Buffer형태 data
  console.log(data.toString())
})

  • promise를 사용한 방법, 자주사용한다.
const fs = require('fs').promises;

fs.writeFile('./writeme.txt', '글이 입력됩니다')
.then(() => {
  return fs.readFile('./writeme.txt');
})
.then((data) => {
  console.log(data.toString());
})
.catch((err) => {
  console.error(err);
});

  • writeFile
  • writeFile 응용
const fs = require('fs').promises

fs.writeFile('./writeme.txt','파일을 쓰겠어요!') // 파일경로와 입력할 data
.then(() => {
  return fs.readFile('./writeme.txt')
})
.then((data) => {
  console.log(data.toString())
})
.catch((err) => {
  console.log(err)
})

fs 실습

// const fs = require('fs')

// fs.readFile('./readme.txt',(err,data) => {
//   if(err) throw err
//   console.log(data)
//   console.log(data.toString())
// })
////////////////////////////////////////////////////////
// const fs = require('fs')

// fs.readFile('./readme1.txt',(err,data) => {
//   if(err) throw err
//   console.log(data)
//   console.log(data.toString())
// })
////////////////////////////////////////////////////////
// const fs = require('fs').promises

// fs.writeFile('./writeme.txt','writeme 입니다!')
// .then((result) => {
//   return fs.readFile('./writeme.txt')
// })
// .then((result) => {
//   console.log(result.toString())
// })
// .catch((err) => {
//   console.log(err)
// })
////////////////////////////////////////////////////////
const fs = require('fs').promises
const path = require('path')

fs.writeFile('./writeme1.txt', path.join(__dirname))
.then((result) => {
  return fs.readFile('./writeme1.txt')
})
.then((result) => {
  console.log(result.toString())
})
.catch((err) => {
  console.log(err)
})

동기 메서드와 비동기 메서드 p.140

비동기적인 특성으로 실행할 때마다 결과 순서가 다르다.

const fs = require('fs')
console.log('시작')
fs.readFile('./readme.txt',(err,data) => {
  if(err) throw err
  console.log('1번 실행', data.toString())
})

fs.readFile('./readme.txt',(err,data) => {
  if(err) throw err
  console.log('2번 실행', data.toString())
})

fs.readFile('./readme.txt',(err,data) => {
  if(err) throw err
  console.log('3번 실행', data.toString())
})


console.log('끝')

  • 콜백을 사용한 동기적 활용
const fs = require('fs')

console.log('시작')
fs.readFile('./readme.txt', (err,data) => {
  if(err) throw err
  console.log('1번', data.toString())
  fs.readFile('./readme.txt', (err,data) => {
    if(err) throw err
    console.log('2번', data.toString())
    fs.readFile('./readme.txt', (err,data) => {
      if(err) throw err
      console.log('3번', data.toString())
      fs.readFile('./readme.txt', (err,data) => {
        if(err) throw err
        console.log('4번', data.toString())
        console.log('끝')
      })
    })
  })
})

  • 프라미스promises를 사용한 동기적 활용
const fs = require('fs').promises

console.log('시작')

fs.readFile('./readme.txt')
.then(result => {
  console.log('1번', result.toString())
  return fs.readFile('./readme.txt')
  })
.then(result => {
  console.log('2번',result.toString())
  return fs.readFile('./readme.txt')
})
.then(result => {
  console.log('3번',result.toString())
  console.log('끝')
  //return fs.readFile('./readme.txt')
})
.catch(err => {
  console.log(err)
})

동기 메서드와 비동기 메서드 - 실습

const fs = require('fs')

fs.readFile('./readmeMany.txt',(err,data) =>{
  console.log(data.toString())
})

const readme = (number) => {
  fs.readFile('./readmeMany.txt',(err,data) =>{
    if(err) throw err
    console.log(number,data.toString())
  })
}

console.log('시작')
readme(1)
readme(2)
readme(3)
readme(4)
console.log('끝')

  • fs.readFileSync('파일경로') - 동기용법p.142
const fs = require('fs')

console.log('시작')
let data = fs.readFileSync('./readme.txt') // readme.txt를 동기형태로 읽는다.
console.log('1번', data.toString())
data = fs.readFileSync('./readme.txt') // readme.txt를 동기형태로 읽는다.
console.log('2번', data.toString())
data = fs.readFileSync('./readme.txt') // readme.txt를 동기형태로 읽는다.
console.log('3번', data.toString())
console.log('끝')

// 내 답
const fs = require('fs')

let data = fs.readFileSync('./readmeMany.txt')

const readme = (number) => {
  data = fs.readFileSync('./readmeMany.txt')
  fs.readFile('./readmeMany.txt',(err,data) => {
    if(err) throw err
    console.log(number, data.toString())
  })
}

console.log('시작')
readme(1)
readme(2)
readme(3)
readme(4)
console.log('끝')
// 선생님 답
const fs = require('fs')
const readme = (number) => {
  let data = fs.readFileSync('readmeMany.txt')
  console.log(number, data.toString())
}
console.log('시작')
readme(1)
readme(2)
readme(3)
readme(4)
console.log('끝')

// const fs = require('fs')

// console.log('시작')

// fs.readFile('./readmeMany.txt',(err,data) => {
//   if(err) throw err
//   console.log('1번',data.toString())
//   fs.readFile('./readmeMany.txt',(err,data) => {
//     if(err) throw err
//     console.log('2번',data.toString())
//     fs.readFile('./readmeMany.txt', (err,data) => {
//       if(err) throw err
//       console.log('3번', data.toString())
//       fs.readFile('./readmeMany.txt',(err,data) => {
//         if(err) throw err
//         console.log('4번', data.toString())
//         console.log('끝')
//       })
//     })
//   })

// })

const fs = require('fs').promises
console.log('시작')

fs.readFile('./readmeMany.txt',(err,data) => {
  console.log('1번', data.toString())
  return fs.readFile('./readmeMany',(err,data))
})

버퍼와 스트림 이해하기

const buffer = Buffer.from('저를 버퍼로 바꿔 보세요')

console.log(buffer)

  • 버퍼길이 확인 length:

  • 버퍼형태를 볼 수 있는 data로 변환 toString() :

  • 버퍼 합치기 concat() :

  • 빈 버퍼 생성하기 alloc() 바이트를 인수로 넣는다 :

  • 스트림 읽기

const fs = require('fs')
const readStream = fs.createReadStream('readme.txt',{highWaterMark: 16})
const data = []

readStream.on('data',(chunk) => { 
  // 두번째 파라미터 값에다 callback형식을 준다. 조각조각난 chunk라는 데이터다.
  data.push(chunk)
  console.log('data: ', chunk, chunk.length)
})

readStream.on('end', () => {
  console.log('end : ', Buffer.concat(data).toString())
})

readStream.on('error', (err) => {
  console.log('eroor : ', err)
})


  • 스트림 쓰기
const fs = require('fs')
const writeStream = fs.createWriteStream('write-stream.txt')

writeStream.on('finishi',() => {
  //이벤트 이름이 'finishi'다.
  console.log('파일 쓰기 완료')
})

writeStream.write('이 글을 씁니다. \n')
writeStream.write('한번 더 씁니다.')

writeStream.end() // 파일 쓰기 완료. end()를 사용하면 'finishi'가 된다.

const fs = require('fs')
const readStream = fs.createReadStream('./readme.txt')
const writeStream1 = fs.createWriteStream('write-stream-copy.txt')

readStream.pipe(writeStream1) //복사가 된다. 옛방식

  • buffer 방식과 stream방식의 차이를 memory관점에서 확인하자
    buffer방식의 경우 전후 차이가 매우크다 약 40배
    stream방식의 경우 자습하자 여튼 2배 내외
const fs = require('fs')

const file = fs.createWriteStream('./bigfile.txt')

for(let i=0; i<= 10000000; i++){
  file.write('안녕하세요, 큰파일을 만들거에요, 용량 없으면 하지마!\n')
}
file.end()

버퍼와 스트림 이해하기 - 실습

const buffer = Buffer.from('버퍼로 바뀔 꺼에요.')
console.log('from() : ' , buffer)
console.log('length() : ' , buffer.length)
buffer.toString()
const array = 
[Buffer.from('버퍼 하나'),
Buffer.from('버퍼 둘'),
Buffer.from('버퍼 마지막')]

const buffer2 = Buffer.concat(array)
console.log('concat() : ', buffer2)

const buffer3 = Buffer.alloc(10)

const fs = require('fs')
const readStream = fs.createReadStream('readmeStream.txt', {highWaterMark:16})

const data=[]

readStream.on('data',(chunk) => {
  data.push(chunk)
  console.log('data : ', chunk, chunk.length)
})

readStream.on('end', (Chunk => {
  console.log('end : ', Buffer.concat(data).toString())
}))

readStream.on('error',(chunk) => {
  console.log('error : ', err)
})

fs 기타 메서드 p.152

  • fs.access
  • fs.mkdir
  • fs.open
  • fs.rename

아래 코드를 보면 return Promise.reject로 작성되어 있다.
이경우 다른 인자 없이 바로 reject하겠다는 뜻이며 가장 가까운 .catch로 넘어간다.
동일하게 return Promise.resolve로 되어있다면 가장 가까운 .then으로 바로 넘어간다.

const fs = require('fs').promises;
const constants = require('fs').constants;

fs.access('./folder', constants.F_OK | constants.W_OK | constants.R_OK)
//폴더가 없으면 constants.F_OK에 걸린다. err라고 처리한다.
  .then(() => {
    return Promise.reject('이미 폴더 있음');
  })
  .catch((err) => { //예외처리 중
    if (err.code === 'ENOENT') { // 여기서 err.code와 err과는 다르다 그래서 바로
      console.log('폴더 없음');
      return fs.mkdir('./folder');
    }
    return Promise.reject(err); //여기로 넘어오고 맨아래 .catch로 넘어간다.
  })
  .then(() => {
    console.log('폴더 만들기 성공');
    return fs.open('./folder/file.js', 'w');
  })
  .then((fd) => {
    console.log('빈 파일 만들기 성공', fd);
    fs.rename('./folder/file.js', './folder/newfile.js');
  })
  .then(() => {
    console.log('이름 바꾸기 성공');
  })
  .catch((err) => {
    console.error(err);
  });

쓰레드 풀

설정한 쓰레드 풀 갯수 대로 동시 처리가 가능하다.
아래 사진은 하드웨어에서 제공하는 쓰레드 개수이다. 프로그램과 맞춰 놓으면 최적화하여 사용 가능하다.

이벤트

스트림을 배울 때 .on('data',콜백) 또는 .on('end',콜백)을 사용했었다.
바로 data라는 이벤트와 end라는 이벤트가 발생할 때 콜백 함수를 호출하도록 이벤트를 등록한 것이다.
createReadStream같은 경우 내부적으로 알아서 data와 end 이벤트를 호출하지만, 우리가 직접 이벤트를 만들 수도 있다 :

const EventEmitter = require('events')
const myEvent = new EventEmitter()

myEvent.on('event1',() => {
  console.log('이벤트1 발생!')
})
myEvent.on('event1', () => {
  console.log('이벤트 1 추가 발생')
})
myEvent.emit('event1')

  • .once('이벤트',콜백) 한번만 실행하도록 하였다 :
const EventEmitter = require('events')
const myEvent = new EventEmitter()

myEvent.on('event1',() => {
  console.log('이벤트1 발생!')
})
myEvent.on('event1', () => {
  console.log('이벤트 1 추가 발생')
})

myEvent.once('event2', () => {
  console.log('이벤트 2 발생')
})
myEvent.emit('event1')
myEvent.emit('event2')
myEvent.emit('event2')

좋은 웹페이지 즐겨찾기