Node.js에서 파일관리하기
1. path 모듈 : 필요성
path 모듈을 사용하면 경로 구분자를 통일할 수 있습니다! (path 모듈의 중요한 역할 중 하나)
예를 들어, 윈도우와 맥은 경로 구분자가 다르기 때문에 통일해 파일 경로를 다루는 것이 좋은데요.
- 윈도우 – 역슬래시 ( ) 사용
- (예, C:\Users\funco\Desktop\myNode\basics\03\example.txt)
- 맥OS - 슬래시( / ) 사용
- (예, /Users/funnycom/Desktop/basics/03/example.txt)
절대 경로와 상대경로
절대 경로 (파일을 다룰 때, 절대 경로로 표현하는지, 상대 경로로 표현하느냐에 따라 차이가 있음)
- 파일이나 폴더의 위치를 루트(root) 폴더부터 시작해서 파일까지 전부 다 나타내는 것
상대 경로 (현재 파일을 기준으로 파일의 위치를 알아냄)
- 기준이 되는 파일이 있을 경우 사용하는 경로
- 같은 폴더에 있을 경우 ‘./ ’로 표기하고 한 단계 위 부모 폴더에 있을 경우 ‘../ ’ 사용 (하위 경로는 ‘ . ‘ 없이 ‘ / ’ 만 사용)
경로를 다루는 주요 함수 살펴보기
join 함수 – 여러 경로 연결하기
dirname 함수 – 경로만 추출하기
basename 함수 – 파일 이름 추출하기
extname 함수 – 파일 확장자 추출하기
parse 함수 – 경로를 분해해서 객체로 반환하기
2. FS 모듈
파일의 내용을 읽거나 기록하는 등 파일을 관리할 때 사용하는 모듈. File System 모듈. 줄여서 FS 모듈이라 합니다.
비동기 처리 방법에 따라 함수가 달라져요! – 프로미스 함수, 콜백 함수, 그 외 동기 처리 함수
여기서는 콜백함수만 실습합니다.
<FS 모듈 중에서 동기 처리 함수> <FS 모듈 중에서 콜백 처리 함수>
FS 모듈 가져오기 및 함수 사용
현재 디렉터리 읽기
FS 모듈에는 현재 디렉터리 파일을 살펴볼 수 있는 readdirSync 함수와 readdir 함수가 있습니다
(파일을 살펴볼 때 동기/비동기 처리 시 선택)
readdirSync 함수 – 동기 처리로 디렉터리 읽기
readdir 함수 – 비동기 처리로 디렉터리 읽기
3. 파일 관리하기 (아까는 디렉토리였고 지금은 파일!)
파일 읽기– readFileSync, readFile 함수
readFileSync 함수 – 동기 처리로 파일 읽기
readFile 함수 – 비동기 처리로 파일 읽기
파일 기록
writeFileSync 함수 – 동기 처리로 파일에 쓰기
writeFile 함수 – 비동기 처리로 파일에 쓰기
existSync 함수 – 파일 존재 여부 체크하기
flag 옵션 – 기존 파일에 내용 추가하기
- 파일의 기존 내용을 유지하며 새로운 내용을 추가할 경우
- flag 옵션 사용
flag 옵션 – 기존 파일에 내용 추가하기
appendFileSync, appendFile 함수 – 기존 파일에 내용 추가하기
- 기존 파일에 내용을 추가할 때 flag 옵션을 사용하지 않고 위 함수들 사용 가능
파일 삭제하기
unlinkSync 함수 – 동기 처리로 파일 삭제
unlink 함수 – 비동기 처리로 파일 삭제
existsSync 함수 – 파일 존재 여부 체크하고 삭제하기
4. 디렉터리 관리하기
디렉터리 만들기 및 삭제하기
- mkdirSync, mkdir 함수 – 디렉터리 만들기
recursive 옵션 – 여러 계층의 디렉터리 만들기
- recursive 옵션을 true로 지정하면 존재하지 않던 상위 폴더까지 한꺼번에 만들 수 있음
rmdirSync, rmdir 함수 – 빈 디렉터리 삭제하기
- 디렉터리가 비어 있어야 삭제 가능!
rmSync, rm(remove) 함수 – 내용이 있는 디렉터리 삭제하기
- 디렉터리 안에 내용이 있더라도 삭제하고 싶다면 rmSync와 rm 함수 사용
- rmSync와 rm 함수는 디렉터리뿐만 아니라 파일도 삭제 가능
5. 버퍼와 스트림 이해하기
버퍼란? : 데이터 임시 저장 장소
- 메모리에 할당된 일련의 데이터를 나타냅니다. 파일을 읽을 때 한 번에 전체 파일을 읽어서 버퍼에 저장하고, 이후에 메모리에서 처리하는 방식입니다.
- 작은 파일이나 파일 전체가 필요한 경우에 유용합니다. 파일을 읽거나 쓸 때는 데이터를 버퍼에 담아서 처리합니다
- 파일을 읽어 올 때 전체 내용을 한꺼번에 다 가져오지 않음
- 한번에 버퍼 하나 크기 만큼만 가져오고, 버퍼가 가득 차면 그 내용을 전달해 줌
노드의 버퍼는 처음부터 크기가 고정되어 있고 내용이 이진값으로 저장됩니다!
그래서 utf-8 옵션을 사용하거나 data에서 toString()을 사용하여 문자열로 변경해야해요
스트림(stream)이란? : 데이터의 흐름
- 한 곳에서 다른 곳으로 데이터가 이동하는 것, 즉 데이터의 흐름
- 서버에서 클라이언트로 혹은 클라이언트에서 서버로 데이터를 보낼 때 사용하는 방식
- 스트림을 사용하면 파일 전체를 내려받지 않고도 차례로 처리할 수 있어서 시간을 절약할 수 있음
- 메모리 사용도 최소화할 수 있는 만큼 프로그램의 성능도 향상할 수 있음
노드에서 스트림은 크게 리더블 스트림과 라이터블 스트림, 듀플렉스 스트림으로 나눌 수 있습니다.
➡️일반적인 벡엔드 프로그래밍에서 자주 사용하는 것은 리더블 스트림과 라이터블 스트림입니다!
리더블 스트림(readable stream)
- 데이터를 읽기 위한 스트림
- 주로 서버에서 용량이 큰 데이터를 가져올 때 사용
그러면 fs.read와 리더블 스트림의 차이점은 뭔가요?
- fs.read는 파일 내용을 한꺼번에 가져옵니다. 즉, 데이터 전체를 하나의 덩어리로 처리해요!
- 그러나 FS 모듈의 createReadStream 함수 사용, 데이터를 작은 크기로 나누어서 읽어오기 때문에 용량이 큰 데이터를 가져올 때 유용합니다.
자바스크립트는 이벤트 기반 언어입니다. (이벤트 발생 시 그 이벤트를 처리)
노드에서 이벤트 처리 시 on이라는 함수 사용해요.
라이터블 스트림
데이터를 기록하는 스트림
readMe.txt 파일을 청크(chunk) 단위로 읽어와서 다시 청크 단위로 writeMe.txt 파일에 기록
- 청크란 버퍼 크기만큼씩 한 번에 읽거나 쓸 수 있는 데이터를 말함
- 기존 파일에 기록하고 싶다면 flag:”a” 처럼 내용을 추가할 수 있도록 지정하면 됨
파이프(pipe) – 2개의 스트림을 연결하는 파이프
- 노드에서는 리더블 스트림으로 읽어 와서 라이터블 스트림으로 파일에 기록하는 방법을 자주 사용함
- 파이프를 사용하면 이벤트가 발생했을 때 따로 가져오고 기록하던 것을 한꺼번에 처리함
- 이벤트 처리를 하지 않아도 되고, 라이터블 스트림에서 write 함수를 사용해 기록안해도 됨