빙고테이블을 만들어서 사람들의 repo에 README.md파일을 뿌리는게 내 목표였다.
처음엔 숫자를 랜덤으로 뿌려서 테이블에 적용시키면 되는거네?하고 그냥 쉽게 생각했는데
md파일에 랜덤 만드는 js문법을 쓸 수도 없고 어쩌지?? 하고 발만 동동 구르고 있었는데
정답은 node 에 있었다.
허선생님의 도움으로 해결쓰..ㅠㅠ
빙고 table을 만들어보자.
코드를 간략하게 하기위해 utils에 필요한 함수들을 저장해서 불러왔다.
utils는 map과 같은 array method들 뿐만 아니라 랜덤한 값을 뽑아내는 shuffle method를 포함쓰
//table.js
const utils = require('./utils');
const makeTable = utils.pipe(
() => Array(25),
(arr) => arr.fill(),
utils.map((e, i) => i + 1),
utils.shuffleArray,
(arr) =>
utils.pipe(
(arr) => arr.fill(),
utils.map((e, i) => i),
utils.reduce((acc, curr) => {
const index = curr * 5;
return [...acc, arr.slice(index, index + 5)];
}, [])
)(Array(5)),
utils.map((row) => {
return [
'<tr>',
row.map((cell) => ` <td>${cell}</td>`).join('\n'),
'</tr>',
].join('\n');
}),
(arr) => ['<table>', '<tbody>', ...arr, '</tbody>', '</table>'],
(arr) => arr.join('\n')
);
module.exports = { makeTable };
코드를 하나하나 살펴보자.
1~25까지의 숫자가 들어간 배열 만들기
// 파이프라인의 첫 시작
() => Array(25),
arr => arr.fill(),
utils.map((e, i) => i + 1),
Array(25)
를 이용해 빈 배열에 25개의 값이 들어갈 자리를 만들어주고fill()
을 이용해서 빈 공간을 undefined로 채우기map
의 index number를 이용해 배열을 숫자로 채우기
위의 코드는 파이프라인에 들어가는 거라 쉼표로 길게 쓴 거지만 만약에 파이프에 들어가지 않고 따로 썼다면 한줄로도 가능쓰!
Array(25).fill().map((e,i)=>i+1)
요렇게!
배열 속 25개 숫자들을 섞어주기
stackoverflow를 찾다보면 괜찮은 랜덤함수들이 많다.
내가 짜는건 머리아플 수 있으니 다른 사람이 짜놓은 좋은 로직의 함수를 저장해서 써먹자!
그리하여 간단하게 utils.shuffleArray,
요렇게 끝!
여기까진 쉬울수도 있다. 하지만 내가 해야할 것은 테이블에 숫자를 넣는건데
<tr></tr>
태그로 감싸야 하기 때문에 숫자 5개를 각각의 tr태그 안에 넣어야 한다.
여기서 난 멘붕을 당했고, 허선생님은 간단하게 파이프를 한번 더 썼다…ㅋㅋ ㅠㅠ
위에서 만든 배열 속 숫자를 다섯개씩 끊어주기
arr => utils.pipe(
arr => arr.fill(),
utils.map((e, i) => i),
utils.reduce((acc, curr) => {
const index = curr * 5
return [
...acc,
arr.slice(index, index + 5),
]
}, []),
파이프를 한번 더 써주는데 아까처럼 fill
을 이용해 배열의 빈 공간을 확보해놓고
map
의 index number를 이용해서 0부터 4까지의 숫자를 뽑아냈고(배열 5개 필요하니깐)
reduce
부분은 넘 헷갈려서 콘솔을 찍어봤다.
숫자를 5개씩 끊어야해서 slice
를 써주는데 이를 쉽게하기 위해 index를 선언해주었고
acc는 빈배열에서 숫자가 채워지는 형태로, curr은 현재 배열이 속한 index를 가리켰다.
다시 보니 reduce 쪽이 잘 이해가 되지 않는다… ㅠㅠ
여튼 slice를 이용해서 5개씩 자른 배열을 만든다고 대충 이해 했고..
자른 숫자에 테이블 태그 적용하기
let row = [4, 9, 14, 22, 16];
['<tr>', row.map((cell) => ` <td>${cell}</td>`).join('\n'), '</tr>'].join(
'\n'
);
정확한 로직은 제일 위의 코드 참고!
나는 일단 이게 잘 적용 되는지 확인하고 싶어서 임의의 배열을 row 변수에 대입했다.
사실 안쪽의 join은 안 써도 상관없긴 한데 확실이 indent가 있으니 보기 편하다!
결과물은 이렇게…
이걸 이제 <table>
태그와 <tbody>
태그 안에 넣어주는건 완전 쉽다!
html 태그를 배열을 이용해서 적용하는건 생각지도 못했는데 정말 신박한 방법이였다ㅠㅠ
커링 두 번 쓴 것보다 html태그 적용한게 더 신기했다.. 와 ㅠㅠ
이제 fs에 적용을 해야하는데..
node file system
// fs.js
const fs = require('fs');
const read = (path) =>
new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', (err, data) => {
if (err) return reject(err);
return resolve(data);
});
});
const write = (path, data) =>
new Promise((resolve, reject) => {
fs.writeFile(path, data, (err) => {
if (err) return reject(err);
return resolve(true);
});
});
module.exports = {
read,
write,
};
여기서 중요한 건 읽기모드와 쓰기모드 둘 다 적용시켜야 한다는 점!
일단 fs 형식을 위의 코드와 같이 써주고 우리는 이걸 index.js에서 적용시킬 예정쓰
md파일 생성하기
아! 이 전에 template md 파일을 만들어야 하는데!
title~~
<<<table>>>
description....
빙고판을 중간에 낑겨넣고 싶어서 일단 꺽쇠를 이용해서 영역표시(?)를 해주고…
const fs = require('./fs');
const path = require('path');
const { makeTable } = require('./table');
fs.read(path.join(__dirname, './README.template.md'))
.then((data) => {
const newContent = data.replace('<<<table>>>', makeTable());
return newContent;
})
.then((content) => {
fs.write(path.join(__dirname, '../README.md'), content).then(() => {
console.log('README 저장됨~~😆');
});
});
replace를 이용해 <<<table>>>
이라는 글씨를 우리가 만든 빙고로 대체해준다.
그리고 path 설정을 잘 해줘야 하는데..!
첫번째 인자에 __dirname이 들어가지 않으면 작동이 안됐던 기억이..
두번째 인자는 경로와 파일이름과 형식이 들어가게 된다.
처음에는 이렇게 node server를 켤 때마다 파일을 하나씩 생성하는 로직이었는데
우리의 능력자 허선생님이 로직을 바꿔서 각폴더에 각 md파일이 들어가게끔 해서
서버 한 번 켰을때 39개의 폴더와 md파일들이 한번에 생성되도록 만들어주었다.
한 1초? 늦어도 1.5초 걸렸을까..?
이래서 노드를 쓰나보다.. 정말 정말 빠르고 편리하다..
노드의 매력에 점점 빠지고 있는 요즘이다.
아.. 공부 진짜 열심히 하자ㅠㅠ 갈 길이 멀었다!!!
Reference
- 허선생님의 손길