[nodejs] 7. csv 데이터를 활용하여 html 값 만들기

2024. 2. 2. 17:46cs및 소프트스킬/nodejs

728x90
반응형
SMALL

안녕하세요 지난 포스팅에 이어 nodejs 에서 api 연동까지 진행을 해보았지만 이번 시간에는 csv에 있는 데이터를 가공하여 표 형태로 게시판을 읽어드리는 코드를 작성하고자 합니다.

 

Github : https://github.com/BerkleyLim/basic_nodejs

 

GitHub - BerkleyLim/basic_nodejs: 이 프로젝트는 node.js 입문을 위한 프로젝트 중 하나입니다.

이 프로젝트는 node.js 입문을 위한 프로젝트 중 하나입니다. Contribute to BerkleyLim/basic_nodejs development by creating an account on GitHub.

github.com

 

 

 

0. 시작하기

- 다음은 아래처럼 npm으로 설치해줍니다.

$ npm install body-parser --save
$ npm install cors --save
$ npm install csvtojson --save
$ npm install express --save

 

 

- main.csv 파일

bno,title,contents
1,홍길동 자기소개,안녕하세요 만나서 반갑습니다. 저는 홍길동 입니다.
2,Berkley 자기소개,안녕하세요 만나서 반갑습니다. 저는 Berkley 입니다.
3,Sara 자기소개,안녕하세요 만나서 반갑습니다. 저는 Sara 입니다.

 

 

 

1. 환경 설정

{
  "name": "ver07",
  "version": "1.0.0",
  "description": "ver07",
  "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"
  }
}

 

 

2. index.js 설정

<src/main/index.js>

- 아래는 nodejs 환경에서 csv 환경에 설정하기 위해 작업 진행 실시

// express 선언
const express = require("express");

// POST에 request body 넣기 위해 실행
const bodyParser = require('body-parser')

// express에 app 넣고, 포트 지정
const app = express();
const PORT = 300;
const http = require('http').createServer(app);

// api 지정 (router)
const routes = require('./controller')

// body - parser
app.use(bodyParser.json())

app.use(routes)
// 서버 실행시 화면 표시
const consoleListening = () => {
  console.log(`server start : http://localhost:${PORT}`);
}

// 서버 실행
// main 화면입니다. 결과 뜨고,
// console에 server start : http://localhost:300 올리기
http.listen(PORT, consoleListening);

 

 

 

3. csv util 만들기

- src/main/service/csvLogicProcessService.js

- 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;
}


// 파일 스기
// 파일을 작성하려면 writeFile메서드를 사용한다. 생성할 파일 경로(확장자 까지 입력)와 내용을 포함한다.
// fs.writeFile('./resource/README2.md', '## Heading2');

// 기존 내용이 있는 파일에 writeFile을 해버린다면 아예 덮어씌워지기 때문에 기존 내용뒤에 덧붙이려면 appendFile() 메서드를 사용하면 된다.
// fs.appendFile('../resource/README2.md', '### hello Express!');

 

 

 

4. 각 controller에서 경로 설정

// 이부분 router를 지정하여 각 사용할 api 지정
const router = require('express').Router();
const MainViewController = require('./MainViewController');

// cors 해결
const cors = require('cors');


// 각각 api 접근 허용을 위해 cors()를 추가해줍니다.
router.get('/', cors(), MainViewController.mainView)

module.exports = router;

 

 

 

5. MainViewController 설정

const fs = require('fs');

const {processCsvToJsonList, jsonToCSV} = require('../service/csvLogicProcessService')

exports.mainView = (request, response, next) => {
  try {
    const main = processCsvToJsonList('src/resource/csv/main.csv')
    // 데이터 가공 작업 끝

    if (!main) console.log(`file read err : ${err}`); // debug

    let html = `
      <div style="display:flex; width:800px; text-align:center">
        <table>
          <thead>
            <tr style='border: 1px solid'>
              <th width="50px" style='border: 1px solid'>bno</th>
              <th width="150px" style='border: 1px solid'>title</th>
              <th width="600px" style='border: 1px solid'>contents</th>
            </tr>
          </thead>
          <tbody>
          ${
            // tbody()
            main?.map((data, index) => 
              `
              <tr key=${index} style='border: 1px solid'>
                <td width="50px" style='border: 1px solid'>${data?.bno}</td>
                <td width="150px" style='border: 1px solid'>${data?.title}</td>
                <td width="600px" style='border: 1px solid'>${data?.contents}</td>
              </tr>
              `
            )

          }
          </tbody>
        </table>
      </div>
    `;
    console.log(html)
    // response.send(main);
    response.send(html);
  } catch (err) {
    console.log(`err with csv : ${err}`);
  }
};

 

 

 

6. 결과 값

- 이렇게 다음과 추출 가능합니다.

- react 개발 방식 그대로 리터럴 템플릿 중 하나인 백틱(``)기호로 이용하여 적용해보고, ',' 가 아쉽지만 다시 한번 고민해봐야겠다

 

 

 

7. 마치며

- nodejs를 이용하여 유사 SSR로 만들어 보았다.

- 하지만, 나는 개인적으로 이런 방식은 하드코딩 느낌이 들어 별로 만족스러운 코딩 방법은 아니지만 다시한번 고민을 해보고자 한다.

 

728x90
반응형
LIST