2024. 2. 11. 14:17ㆍcs및 소프트스킬/nodejs
지난 포스팅에서는 nodejs를 이용하여 csv로 데이터를 읽어들이고, 잘 저장되어지는지의 대해 csv -> json, json -> csv로 변환하면서 결과적으로 잘 적용 되는지의 대해 로직과 테스트까지 작업을 해 보았다.
이번 시간에는 ver07에서 기반으로 하여 추가 개발과 Back-End API 개발을 위한 작업을 진행하도록 한다.
ver08 버전 참조
https://github.com/BerkleyLim/basic_nodejs
0. 시작하기 전
package.json
{
"name": "ver08",
"version": "1.0.0",
"description": "ver08",
"main": "src/main/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/main/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"csvtojson": "^2.0.10",
"express": "^4.18.2"
}
}
1. 사용 API
[읽기]
- API : /readBoard
- Method : GET
- Request Parameter : {}
- Response Parameter : [
{
"bno": "1",
"title": "제목1",
"contents": "내용1",
}, .......
]
[쓰기]
- API : /createBoard
- Method : POST
- Request Parameter : {
"title":"제목2",
"contents:"제목2",
}
- Response Parameter : [
{
"bno": "1",
"title": "제목1",
"contents": "내용1",
}, .......
{
"bno": "4",
"title": "제목2",
"contents": "내용2",
}
]
[삭제]
- API : /createBoard
- Method : POST
- Request Parameter : {
"bno": "1"
}
- Response Parameter : [
// bno 제거
{
"bno": "2",
"title": "제목2",
"contents": "내용2",
}, .......
]
[수정]
- API : /createBoard
- Method : POST
- Request Parameter : {
"bno": "1",
"title": "제목변경",
"contents": "내용변경"
}
- Response Parameter : [
{
"bno": "1",
"title": "제목변경",
"contents": "내용변경",
}, .......
]
2. csv 파일
src/resource.csv/main.csv
bno,title,contents
1,홍길동 자기소개,안녕하세요 만나서 반갑습니다. 저는 홍길동 입니다.
2,Berkley 자기소개,안녕하세요 만나서 반갑습니다. 저는 Berkley 입니다.
3,Sara 자기소개,안녕하세요 만나서 반갑습니다. 저는 Sara 입니다.
3. csv -> json 변환, json -> csv 변환 관련 로직
const fs = require('fs');
// 1) csv 가공하는 단 - 리스트 출력 - json 형식 반환
exports.processCsvToJsonList = (path) => {
let csv = fs.readFileSync(path).toString('utf-8');
// let csvData = csv.replaceAll('\r', '').replaceAll(' ', '').split("\n");
let csvData = csv.replaceAll('\r', '').split("\n");
let key = csvData[0].split(',');
let dataSet = {}
for (let i = 0; i < key.length; i++) {
dataSet = {
...dataSet,
[key[i]]: ''
}
}
let csvToJSON = new Array();
for (let gagongDataIndex = 1; gagongDataIndex < csvData.length; gagongDataIndex++) {
let processData = csvData[gagongDataIndex].split(',');
for (let i = 0; i < key.length; i++) {
dataSet = {
...dataSet,
[key[i]]: processData[i]
}
}
csvToJSON.push(dataSet)
}
console.log(csvToJSON)
return csvToJSON
}
// 2) csv 가공하는 단 - 객체 출력 - json 형식 반환
exports.processCsvToJsonObject = (path) => {
let csv = fs.readFileSync(path).toString('utf-8');
let csvData = csv.replaceAll('\r', '').replaceAll(' ', '').split("\n");
let key = csvData[0].split(',');
let dataSet = {}
for (let i = 0; i < key.length; i++) {
dataSet = {
...dataSet,
[key[i]]: ''
}
}
return dataSet;
}
// 3) json -> csv로 변환하여 저장
exports.jsonToCSV = (json_data) => {
// 1-1. json 데이터 취득
const json_array = json_data;
// 1-2. json데이터를 문자열(string)로 넣은 경우, JSON 배열 객체로 만들기 위해 아래 코드 사용
// const json_array = JSON.parse(json_data);
// 2. CSV 문자열 변수 선언: json을 csv로 변환한 문자열이 담길 변수
let csv_string = '';
// 3. 제목 추출: json_array의 첫번째 요소(객체)에서 제목(머릿글)으로 사용할 키값을 추출
const titles = Object.keys(json_array[0]);
// 4. CSV문자열에 제목 삽입: 각 제목은 컴마로 구분, 마지막 제목은 줄바꿈 추가
titles.forEach((title, index)=>{
csv_string += (index !== titles.length-1 ? `${title},` : `${title}\r\n`);
});
// 5. 내용 추출: json_array의 모든 요소를 순회하며 '내용' 추출
json_array.forEach((content, index)=>{
let row = ''; // 각 인덱스에 해당하는 '내용'을 담을 행
for(let title in content){ // for in 문은 객체의 키값만 추출하여 순회함.
// 행에 '내용' 할당: 각 내용 앞에 컴마를 삽입하여 구분, 첫번째 내용은 앞에 컴마X
row += (row === '' ? `${content[title]}` : `,${content[title]}`);
}
// CSV 문자열에 '내용' 행 삽입: 뒤에 줄바꿈(\r\n) 추가, 마지막 행은 줄바꿈X
csv_string += (index !== json_array.length-1 ? `${row}\r\n`: `${row}`);
})
console.log(csv_string)
// 6. CSV 문자열 반환: 최종 결과물(string)
return csv_string;
}
4. CRUD 로직 수행
src/main/controller/board/BoardController.js
const fs = require('fs');
const {processCsvToJsonList, jsonToCSV} = require('../../service/csvLogicProcessService')
// 전체 읽기
exports.readBoard = (request, response, next) => {
try {
const main = processCsvToJsonList('src/resource/csv/main.csv')
// 데이터 가공 작업 끝
if (!main) console.log(`file read err : ${err}`); // debug
// csv로 변환 - 파일 테스트용
// const csvResult = jsonToCSV(main);
// fs.writeFile('src/resource/csv/test.csv', csvResult, err => {
// if (err) {
// console.log(err.message);
// throw err;
// }
// console.log('data written to file');
// });
response.json(main);
} catch (err) {
console.log(`err with csv : ${err}`);
}
};
// 생성
exports.createBoard = (request, response, next) => {
try {
let params = request?.body;
if (!!!params?.title || !!!params?.contents) {
response.json("데이터 누락");
return;
}
let main = processCsvToJsonList('src/resource/csv/main.csv')
// 데이터 가공 작업 끝
if (!main) console.log(`file read err : ${err}`); // debug
console.log(params)
// 가장 마지막 uno의 +1 더하여 추가
let lastUno = (parseInt(main[main.length-1].bno)+1).toString();
// 배열 생성할 데이터 형식 추가
const createMainInterface = {
bno: lastUno,
title: params?.title,
contents: params?.contents
}
main.push(createMainInterface)
// csv로 변환
const csvResult = jsonToCSV(main);
fs.writeFile('src/resource/csv/test.csv', csvResult, err => {
// fs.writeFile('src/resource/csv/main.csv', csvResult, err => {
if (err) {
console.log(err.message);
throw err;
}
console.log('data written to file');
});
response.json(main);
} catch (err) {
console.log(`err with csv : ${err}`);
}
};
// 삭제
exports.deleteBoard = (request, response, next) => {
try {
let params = request?.body;
if (!!!params?.bno) {
response.json("데이터 누락");
return;
}
let main = processCsvToJsonList('src/resource/csv/main.csv')
// 데이터 가공 작업 끝
if (!main) console.log(`file read err : ${err}`); // debug
console.log(params)
// 삭제 수행
main = main.filter(data => data?.bno != params?.bno)
// csv로 변환
const csvResult = jsonToCSV(main);
fs.writeFile('src/resource/csv/test.csv', csvResult, err => {
// fs.writeFile('src/resource/csv/main.csv', csvResult, err => {
if (err) {
console.log(err.message);
throw err;
}
console.log('data written to file');
});
response.json(main);
} catch (err) {
console.log(`err with csv : ${err}`);
}
};
// 갱신
exports.updateBoard = (request, response, next) => {
try {
let params = request?.body;
if (!!!params?.bno || !!!params?.title || !!!params?.contents) {
response.json("데이터 누락");
return;
}
let main = processCsvToJsonList('src/resource/csv/main.csv')
// 데이터 가공 작업 끝
if (!main) console.log(`file read err : ${err}`); // debug
console.log(main)
console.log(params)
// 배열 생성할 데이터 형식 추가
const createMainInterface = {
bno: params?.bno,
title: params?.title,
contents: params?.contents
}
// 바꾸기
for (let i = 0; i < main.length; i++) {
// 아래는 일부로 형 고려하지 않고 조건 검사하라고 == 라고 둠
if (main[i].bno == params?.bno) {
// 아래는 바꾸기
main.splice(i,1,createMainInterface)
break;
}
}
// csv로 변환
const csvResult = jsonToCSV(main);
fs.writeFile('src/resource/csv/test.csv', csvResult, err => {
// fs.writeFile('src/resource/csv/main.csv', csvResult, err => {
if (err) {
console.log(err.message);
throw err;
}
console.log('data written to file');
});
response.json(main);
} catch (err) {
console.log(`err with csv : ${err}`);
}
};
- fs.writeFile 부분
test.csv -> main.csv로 변경하면 실제 DB처럼 질의어 조작하여 내용 변경이 가능합니다.
이부분은 test 용도로 결과 값을 수행하기 위해 보는 용도로 사용되었습니다.
차후, 실제로 운영한다고 가정하고 쓰인다고 생각하고 진행할경우 main.csv로 변경하여 사용 할 것!
5. API 등록
// 이부분 router를 지정하여 각 사용할 api 지정
const router = require('express').Router();
const MainViewController = require('./MainViewController');
const BoardController = require('./board/BoardController');
// cors 해결
const cors = require('cors');
// 아래는 특정 host만 허용 (리액트 프로젝트 적용전)
// const corsOption = {
// origin: 'http://example.com',
// optionsSuccessStatus: 200
// }
// 각각 api 접근 허용을 위해 cors()를 추가해줍니다.
router.get('/readBoard', cors(), BoardController.readBoard)
// post를 이용하여 데이터 불려오기
router.post('/createBoard', cors(), BoardController.createBoard)
router.post('/deleteBoard', cors(), BoardController.deleteBoard)
router.post('/updateBoard', cors(), BoardController.updateBoard)
module.exports = router;
6. postman Test
[읽기 : /readBoard]
[쓰기 : /createBoard]
[삭제 : /deleteBoard]
[수정 : /updateBoard]
7. 마치며
DB에 적용 전 csv를 이용하여 데이터 조작처리를 할 수 있었다.
현재 postman으로 테스트를 진행 하였지만, 차후, DB를 연동하여 진행해보도록 한다.
이 작업은 실제 현업에서 SM 업무를 담당하거나 실제 작업 시 DB 접근 제한이 있는 경우 목업형식으로 테스트 할 때 쓰는 용도로 사용 되기도 한다. 테스트 방식은 이 방식 말고도 json으로 사용하여 적용하는 방식이 있지만 아직까지 필자는 json으로 기존에 저장된 내용을 데이터 조작하는 방식은 연구 중이기도 한다.
이 부분은 실제 프로젝트 환경과 본인이 맞는 방식으로 찾아 진행하는 것으로 추천드린다.
'cs및 소프트스킬 > nodejs' 카테고리의 다른 글
[nodejs] - 10. nestjs에서 DB 연동하기 (0) | 2024.04.30 |
---|---|
[nodejs] - 9. nestjs의 대한 입문 (0) | 2024.04.29 |
[nodejs] 7. csv 데이터를 활용하여 html 값 만들기 (0) | 2024.02.02 |
[nodejs] 6. 프론트엔드 샘플 html을 테스트로 만들고, nodejs 연동하기 (0) | 2023.11.28 |
[nodejs] 5. nodejs + express 프로젝트 구성하여 리팩토링 (0) | 2023.11.26 |