PHP -> Node.js 컨버팅 회고

2024. 5. 20. 21:45·🔍 Tech 🔍/Back-End

매주 약 18만 개의 숫자 조합을 생성하고 DB에 저장해야 하는 업무가 있다.

Kotlin으로 짜인 앱에서 숫자 조합을 생성 요청을 보내면 서버에 있는 PHP 코드가 해당 로직을 확인한 뒤 숫자 조합을 생성하고 DB에 저장하게 된다.

하지만  요구사항에 실시간으로 스크래핑한 후 몇 가지 알고리즘 조건을 지켜야 했기에 18만 개의 조합을 모두 DB에 저장되기까지 약 4시간 정도의 긴 시간이 걸렸다.

 

앞으로 계속 사용해야 할 코드이기 때문에 Javascript로 컨버팅하기로 했다.

 

1. cheerio

https://cheerio.js.org/docs/intro

 

Welcome to Cheerio! | cheerio

Let's get a quick overview of Cheerio in less than 5 minutes.

cheerio.js.org

제일 먼저 웹 스크래핑을 위한 라이브러리를 찾아보았다. 그 중 Node 환경에서 사용 가능한 cheerio 라이브러리를 확인했고, url에서 HTML을 가져와 특정 태그의 ID 값으로 value를 가져오는 방식으로 스크래핑했다.

  

const cheerio = require('cheerio');
const html = '<div class="content"><h1>Hello, Cheerio!</h1><p>This is an example HTML document.</p></div>';

const $ = cheerio.load(html);

const contentText = $('.content').text();
console.log(contentText);


// Hello, Cheerio!This is an example HTML document.

위의 예시에선 html에 직접 하드코딩 하였지만 실제론 아래 방식으로 url을 통해 가져오게 된다.

// async

const response = await axios.get(url);
const html = response.data;
const $ = cheerio.load(html);

https://github.com/cheeriojs/cheerio

 

GitHub - cheeriojs/cheerio: The fast, flexible, and elegant library for parsing and manipulating HTML and XML.

The fast, flexible, and elegant library for parsing and manipulating HTML and XML. - cheeriojs/cheerio

github.com

 

2. mysql2

mysql은 Node에서 RDB중 하나인 MYSql과 연결 및 쿼리를 주고받을 수 있는 라이브러리인데, mysql에서 부족한 성능을 향상하기 위해 기본적으로 비동기 기능을 추가하고 Promise 문법을 사용 가능하게 한 다음 버전이 mysql2이다.

mysql2가 나온지 10년이 되어가기 때문에 mysql 라이브러리를 사용해 본 적이 없기 때문에 직접 비교는 불가능할 것 같다.

https://www.npmjs.com/package/mysql2

 

mysql2

fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS. Latest version: 3.9.7, last published: a month ago. Start using mysql2 in your project by running `npm i mysql2`. There are 4366 other projects in the npm r

www.npmjs.com

import mysql from 'mysql2/promise';

try {
  // DB 연결을 위해 생성
  const connection = await mysql.createConnection({
    host: 'localhost',
    user: 'root',
    database: 'test',
  });

  // prepare와 query를 호출
  const [results, fields] = await connection.execute(
    'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
    ['Rick C-137', 53]
  );

  console.log(results);
  console.log(fields);
} catch (err) {
  console.log(err);
}

mysql2 공식 문서에 있는 Promise 사용 예제

 

3. pool

connection pool을 이해하기 위해 아래 글을 참고하였다.

https://velog.io/@isntkyu/Nodejs-mysql-vs-mysql2-Connection-Pool

 

[Nodejs] mysql vs mysql2 , Connection Pool

여러가지 성능 개선을 위한 차이점이 존재함.나는 promise 지원 여부에 대한 차이와준비된 명령문(prepared statements) 지원의 차이를 확실히 기억하고 넘어가려한다.지적받은 내 service 함수.쿼리 결과

velog.io

 

Connection pools help reduce the time spent connecting to the MySQL server by reusing a previous connection, leaving them open instead of closing when you are done with them.
This improves the latency of queries as you avoid all of the overhead that comes with establishing a new connection.

연결 풀은 이전 연결을 재사용하여 MySQL 서버에 연결하는 데 소요되는 시간을 줄이는 데 도움이 되며, 작업이 끝났을 때 연결을 닫는 대신 열어 두는 데 도움이 됩니다. 이렇게 하면 새 연결을 설정할 때 발생하는 모든 오버헤드를 피할 수 있으므로 쿼리 대기 시간이 향상됩니다.

https://sidorares.github.io/node-mysql2/docs#using-connection-pools

 

const mysql = require('mysql2/promise');

// Connection pool 설정
const pool = mysql.createPool({
  host: 'localhost', // 데이터베이스 호스트
  user: 'yourusername', // 데이터베이스 사용자 이름
  database: 'yourdatabase', // 사용할 데이터베이스 이름
  waitForConnections: true,
  connectionLimit: 10, // 최대 연결 수
  queueLimit: 0
});

async function queryDatabase() {
  let conn;
  try {
    // Pool로부터 연결을 가져옵니다.
    conn = await pool.getConnection();
    
    // 쿼리 실행
    const [rows, fields] = await conn.query('SELECT * FROM yourtable');

    // 결과 출력
    console.log(rows);
  } catch (err) {
    console.error('데이터베이스 쿼리 중 오류 발생:', err);
  } finally {
    // 연결을 pool로 반환
    if (conn) conn.release();
  }
}

connection pool을 사용하면 DB에 대한 연결을 만들고 해제하는 번거로움을 줄일 수 있고 동시에 여러 연결을 효율적으로 관리할 수 있기에 성능을 향상할 수 있다.

동일한 DB에 여러 요청이 발생할 경우 생길 수 있는 문제를 해결하기 위한 기능인 것 같다. 

connection pool 사용 장점

- 성능 향상 : DB와 연결을 재사용할 수 있기 때문에 매번 연결을 생성하고 해제하지 않아도 됨
- 동시성 관리 : 여러 클라이언트 요청에 대해 동시에 관리 가능
- 자원 관리 : 사용이 완료된 연결을 다시 pool에 반환하여 자원 최적으로 활용
- 대기 시간 최소화 : 이미 생성된 연결을 사용하기 때문에 요청이 처리될 때까지 새로운 연결을 기다리지 않아도 됨
- 안정성 향상 : 연결 오류를 자동으로 처리하고 새로운 연결 생성
- 성능 튜닝 : 최대 연결 수, 대기열 크기 등 설정 가능

 

4. 결과

PHP 코드를 Node.js로 컨버팅/리펙터링 후 데이터를 실제로 출력해 봤을 때 생각보다 더 많은 성능 개선을 느낄 수 있었다.

기존에 약 40분 ~ 60분 정도 걸리던 작업이 약 2분 ~ 4분으로 단축되었다. 아마 스크래핑 과정에선 큰 차이가 없고 Node와 MYSql 연결 시 사용했던 connection pool 그리고 Node의 논 블로킹 IO 비동기 방식이 큰 차이를 가져온 것 같다.

DB에 연결 후 데이터를 주고 받을 때 조건에 맞는 알고리즘 유효성 확인 작업이 끊기지 않고 계속 처리되었기에 많은 시간을 단축할 수 있었다.

 

https://nodejs.org/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking

 

Node.js — Overview of Blocking vs Non-Blocking

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

https://www.youtube.com/watch?v=wB9tIg209-8
'🔍 Tech 🔍/Back-End' 카테고리의 다른 글
  • Expo Node.js FCM 푸시 알림 보내기
  • Python -> Node.js 컨버팅 회고
  • PHP와 Node.js
Yeonhub
Yeonhub
✨ https://github.com/yeonhub 📧 lsy3237@gmail.com
  • Yeonhub
    비 전공자의 Be developer
    Yeonhub
  • 전체
    오늘
    어제
    • 전체보기 (169)
      • 🔍 Tech 🔍 (19)
        • Front-End (11)
        • Back-End (4)
        • AI (1)
        • Server (1)
        • Etc (2)
      • 💡 원티드 프리온보딩 챌린지 💡 (14)
        • PRE-ONBOARDING_AI (11월) (1)
        • PRE-ONBOARDING_FE (2월) (2)
        • PRE-ONBOARDING_FE (1월) (2)
        • PRE-ONBOARDING_FE (12월) (9)
      • 🔥 부트캠프-웹 개발 🔥 (118)
        • HTML5 (7)
        • CSS3 (21)
        • JavaScript (27)
        • JavaScript_advanced (9)
        • React (24)
        • Next (1)
        • MYSql (5)
        • Node (5)
        • 오늘하날(개인프로젝트) (12)
        • 이젠제주투어(팀프로젝트) (7)
      • 💻 CS 💻 (1)
        • 알고리즘 (1)
      • ⚡ 코딩테스트 ⚡ (11)
        • JavaScript (11)
      • 📚 Books 📚 (6)
        • 클린 아키텍처 (2)
        • 인사이드 자바스크립트 (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    expo fcm push
    Node
    node cron
    rn admob
    react native analytics
    expo admob
    expo node fcm
    expo 지도
    expo 길찾기
    bottom sheet
    javascript fcm
    python node
    expo deep linking
    node fcm
    react native expo fcm
    프론트엔드 테스트코드
    node crontab
    php node
    expo google map
    rn bottom sheet
    컴파운드 컴포넌트 패턴
    expo fcm
    react native bottom sheet
    react native admob
    react native firebase analytics
    node.js fcm
    react vite
    expo map
    라스콘
    라스콘4
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Yeonhub
PHP -> Node.js 컨버팅 회고
상단으로

티스토리툴바