Developer Holywater Jeong

Recent Posts

  • June 08, 2018

    Node.js에서 mysql을 async/await으로 작성하기

    Node.js로 코드를 작성하다보면 분명히 한 번 이상은 겪게 되는 비동기 코드 문제. 일명 Callback Hell이라고 불리우는 코드 구조를 본다면 진짜 지옥의 구렁텅이로 빠져드는 것만 같다. 다행히도 여러가지의 비동기 코드를 작성하는 방법이 제시되고는 한다. 몇 가지 예를 들자면 async 라이브러리, ES2015의 기능 Promise, ES2017의 기능 async/await, RxJS 등이 있다. 필자는 주로 Promise를 사용했는데 얼마전 사용해본 ES2017의 async/await가 가장 편한 것 같다. 기존까지는 Mysql DB Connection에 있어서 Promise로 작성하던 것을 async/await로 싹 바꿨는데 async/await를 활용하는 방법에 대해 잠깐 소개하고자 한다. (자신의 Node.js 버젼이 async/await이 사용 가능한 버젼인지 찾아보고 참고하길 바란다. node 버젼 별 기능 확인) 설치 먼저 mysql2라는 모듈이 필요하다. Promise를 적용할 수 있는 mysql 라이브러리이다. npm이나 yarn으로 설치를 하면 된다. npm i --save mysql2 or yarn add mysql2 Step 1. DB Pool 생성 설치를 마쳤다면 바로 예제로 넘어가자. 먼저 "mysql2/promise"를 require한다. mysql2만 호출하면 기존과 다를바가 없이 Promise 기능을 사용할 수가 없다. const mysql = require('mysql2/promise'); /* Step 1, create DB Pool */ const pool = mysql.createPool({ host: 'DB_HOST', user: 'DB_USER', password: 'DB_PW', database: 'DBNAME' }); DB Pool 방식으로 소개하려고 한다. 일단 기본적으로 기존 mysql에서 방법과 유사하다. createPool 함수로 Pool을 생성한다. Step 2. Pool에서 Connection 가져오기 백문이 불여일견 주석 Step 2 이후로 추가된 코드를 먼저 살펴보자. const mysql = require('mysql2/promise'); /* Step 1, create DB Pool */ const pool = mysql.createPool({ host: 'DB_HOST', user: 'DB_USER', password: 'DB_PW', database: 'DBNAME' }); /* Step 2. get connection */ const dbTest = async () => { const connection = await pool.getConnection(async conn => conn); }; 먼저 dbTest 함수에 async가 추가된 것이 보일 것이다. async 함수로 선언되어야 원하는 순서대로 흘러가는 함수를 만들 수 있다. 함수 안에서 pool.getConnection 함수는 connection을 가져오는 함수이다. "mysql2/promise" github에서 코드를 참고해보면 getConnection 함수에는 필수적으로 콜백 함수를 실행시켜 connection을 반환한다. 그래서 그 콜백 함수를 이용해야 한다. getConnection 함수 앞에 await만 선언해서 끝나는 것이 아니고, 그 안의 callback 함수도 async 처리를 해야하는 것이 관건이다. 이렇게 async 함수 내에서 또 async한 작업이 필요하면 꼭 안에 있는 함수에도 선언해야하는 것을 기억하고 넘어가자. Step 3. 쿼리 const mysql = require('mysql2/promise'); /* Step 1, create DB Pool */ const pool = mysql.createPool({ host: 'DB_HOST', user: 'DB_USER', password: 'DB_PW', database: 'DBNAME' }); /* Step 2. get connection */ const dbTest = async () => { try { const connection = await pool.getConnection(async conn => conn); try { /* Step 3. */ const ID = 'HELLO'; const PW = 'WORLD'; const [rows] = await connection.query('INSERT INTO MEMBERS_INFO(ID, PW) VALUES(?, ?)', [ID, PW]); connection.release(); return rows; } catch(err) { console.log('Query Error'); connection.release(); return false; } } catch(err) { console.log('DB Error'); return false; } }; connection.query 함수로 쿼리를 실행시키고 결과를 반환 받는데 위와 같이 작성한다. (역시나 await를 써서 해당 결과가 반환 될 때 까지 기다린다.) 배열로 반환 받는 이유는 mysql2/promise 라이브러리에서 쿼리 결과를 반환 받을 때 저렇게 반환 받게 되어있기 때문에 저렇게 작성한다. [rows, fields] 로 선언 시 fields에 대한 정보도 같이 반환 받을 수 있다. error catch의 경우는 try, catch 로 감싸서 처리해준다면 더욱 좋은 코드가 될 것이다. 그리고 connection을 다 활용했을 경우 connection.release 함수를 호출하여 커넥션을 반환한다. etc. Transaction const mysql = require('mysql2/promise'); /* Step 1, create DB Pool */ const pool = mysql.createPool({ host: 'DB_HOST', user: 'DB_USER', password: 'DB_PW', database: 'DBNAME' }); /* Step 2. get connection */ const dbTest = async () => { try { const connection = await pool.getConnection(async conn => conn); try { /* Step 3. */ const ID = 'HELLO'; const PW = 'WORLD'; await connection.beginTransaction(); // START TRANSACTION const [rows] = await connection.query('INSERT INTO MEMBERS_INFO(ID, PW) VALUES(?, ?)', [ID, PW]); await connection.commit(); // COMMIT connection.release(); return rows; } catch(err) { await connection.rollback(); // ROLLBACK connection.release(); console.log('Query Error'); return false; } } catch(err) { console.log('DB Error'); return false; } }; 트랜잭션을 사용할 경우 기존 mysql 라이브러리와 동일하다. beginTransaction 함수를 호출해주고, 성공시 commit을 실패 시 rollback을 사용하면 된다. 끝.

  • June 04, 2018

    React에서 SSR(Server Side Rendering)을 알아보자

    최근 1~2년 간 React에 관심을 많이 가졌다. 그래서 그에 관한 포스트를 가장 처음으로 해보고자 한다. 먼저 React는 Facebook이 만든 Javascript(이하 JS) 라이브러리라는 점 부터 매력적이다. 또한 그 것을 직접 자사 서비스에도 적용시키고 에어비앤비에서도 적극 활용하는 모습을 보여주기에 기술을 따라가는데 있어서 명분이 있다. 그리고 React 커뮤니티는 굉장히 핫하고 여러 라이브러리가 그것도 아주 많이 나온다는 점에서도 취미로 삼기도 좋아 보인다. 더 나아가서는 React Native라는 네이티브 앱을 구현할 수 있는 라이브러리까지 내놓았다. 기존에 React Web Application을 구현하는 것과 같은 방식으로 할 수 있다는 것이 웹 개발자, JS 개발자에게 굉장히 큰 매력으로 다가온다. 물론, 앱에 대한 기본적인 이해가 있을 때 빛이 나는 기술인 것은 맞는 것 같다. 개발하는 입장에서 보자면 JSX로 UI Component를 작성하고 그 컴포넌트들을 재사용 가능하게 구성하는 점, 그 컴포넌트들을 조합하여 사용하기 용이하다는 점이 매력적이다. 그리고 SSR(Server Side Rendering) 기능이 생소했었던 상황에서 React로 SSR을 구현해보며 개념을 이해할 수 있었다. 또한 MVC 아키텍쳐의 단점을 보완하기 위해 직접 Facebook이 만든 단방향 Data Flow의 Flux 아키텍쳐와 그 구현체인 Redux에 대해서도 알아보며 React와 접목시켜 새로운 영역에 대한 지식을 쌓을 수 있는 계기가 됐다. 그 이후 요즘 흥미를 끄는 것은 React의 SSR을 구현하는 Next.js라는 라이브러리이다. SSR(Server Side Rendering) 그래서 앞서 몇 번 언급된 SSR이 무엇인지 알아보자. 서버 사이드 렌더링은 문자 그대로 렌더링을 서버에서부터 하는 것이다. 일반적으로 JS 라이브러리/프레임워크를 사용하면 서버에서는 거의 빈 껍데기만을 제공하고 클라이언트에서부터 페이지를 그리는 것이 일반적이다. 그러나 JS 라이브러리/프레임워크에서 서버 사이드 렌더링이란 개념은 서버에서 JS 라이브러리/프레임워크를 이용하여 미리 페이지를 그려 클라이언트에 보내고, 클라이언트 단에서 바뀔 부분이나 클라이언트에서만 존재하는 기능에 관한 작업을 하게 된다. 이 때 가상DOM을 활용하여 바뀐 부분만 바꿔주는 등 클라이언트에서의 부하는 최소화한다. SSR 장점 어느 부분에서나 장단점은 있다. 장점은 SEO(Search Engine Optimization, 검색 엔진 최적화)이다. JS 라이브러리/프레임워크를 사용하면서 고질적인 문제는 SEO이다. 앞서 말했듯이 그냥 미리 그려지지 않고 빈 껍데기만 제공된다면 검색엔진이 당연하게도 내용을 검색하는데 어려움이 있다.(모든 검색 엔진이 검색하지 못 하는 것은 아니다) 하지만 SSR을 이용한다면 서버에서부터 페이지를 제공할 때 컨텐츠가 담겨있기 때문에 SEO에 대한 걱정을 덜어내게 되는 것이다. 그리고 초기 로딩 속도 이슈에 대한 문제가 해결된다. 브라우저에서 빈 화면을 오랫동안 보여주는 일은 사용자 입장에서 유쾌한 일은 아니다. 그러나 SSR을 사용한다면 미리 그려진 페이지를 제공하기 때문에 처음 사용자가 페이지를 열었을 때 비교적 빠른 시간 내로 컨텐츠가 담긴 페이지를 이용할 수 있다. SSR 단점 SSR이 앞서 말한 장점을 제공하는 만큼 사용하는데에 있어서 어려움과 번거로움이 생기는 것이 사실이다. 먼저 서버 코드에 있어서도 JSX를 사용할 수 있도록 빌드나 변환하는 과정이 필요해진다. 또한 JS 기반인 서버 플랫폼, Node.js로 서버를 할 때, 같은 JS라고 할지라도 클라이언트와 서버가 모든 것을 같이 공유할 수는 없다.(DOM, Document의 URL 등) 이런 부분에 대한 예외 처리는 물론이며 특히 여러가지 라이브러리를 같이 사용하게 되는 경우 더더욱 복잡도는 증가한다. 또한 클라이언트의 부하를 줄였지 서버의 부하는 당연히 일반적인 렌더링보다 더 생긴다. 그래서 웹 서버와 API 서버를 따로 두는 등의 부하를 줄일 작업이 필요할 것으로 생각된다. 결론은 SSR이 만능열쇠는 아니란 소리. 다음 포스팅 예고 그래도 SSR을 사용해보겠다고 마음을 먹었다면 이 번거롭고 귀찮은 SSR을 기왕이면 쉽게 개발하는 것이 당연히 좋을 것이다. 그런 의미에서 Next.js라는 라이브러리가 그 부분을 어느 정도 해결해주는 것 같다. 물론 기존에 'react-dom'의 서버 관련 기능을 이용하여 구성하는 방법과 조금은 다르게 느껴지기 때문에 이 부분이 어떻게 다른지 조금 비교해보며 포스팅을 해볼 예정이다. 끝.

  • May 27, 2018

    깃허브 블로그 첫 개시

    깃허브 블로그를 시작하게 됐다. 다른 플랫폼에서도 몇 번 시도를 해봤지만 개발자는 개발자처럼 사는 게 편한 듯 싶다. "마크다운까지 활용하며 쓰고 싶은대로 쓰리라!", "광고 수익이 주 목적은 절대 아니다!" 하는 다짐으로 넘어온 만큼 꾸준히 써보고 싶지만 다짐이 언제까지 갈지는 모르겠다. 가능한 주기적인 포스팅을 하고자 하는데 한 번에 많은 것을 하려고 하기보다는 조금씩 자세하게 포스팅하는 것이 목표이다. 잘 해낼 수 있기를 :) 끝.