์ผ๋ถ ์ฝ๋๋ฅผ ํ ์คํธํ๋ ๋์ ์ฐ๊ฒฐ ํ๋ง์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋ด ๋๋ค ํจ์๊ฐ ๋ช ์ด์ ๊ฑธ์ณ ์์ฒ ๋ฒ ํธ์ถ ๋ ๊ฒ์ผ๋ก ์์ํ๊ณ ๋ด db์ ์ฐ๊ฒฐํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์ฐพ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช๊ณ ์์ต๋๋ค. ๋ค์์ ๋ ธ๋ / ํฌ์คํธ๊ทธ๋ ์ค์ ๋ํ ๋งค์ฐ ์ ์ฌํ ๋ฌธ์ ์ ๋๋ค. ๋ณธ์ง์ ์ผ๋ก ๋ฌธ์ ๋ ํ์ด์๋ ๊ฒฝ์ฐ ํ์์ ์ฐ๊ฒฐ์ ๊ฐ์ ธ์ฌ ์ ์์ด์ผํ์ง๋ง AWS๊ฐ (๋ถ์์ ํ๊ฒ) ์ฌ์ฌ์ฉํ๋ ๋ฐฉ์ ๋๋ฌธ์ ๊ธฐ์กด ํ์ ์์กด ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋๋ค ์ปจํ ์ด๋.
๊ธฐ๋ณธ์ ์ผ๋ก ๋ด๊ฐ ์ฐพ๊ณ ์๋ ๊ฒ์ ๋ด db์ ๋ํ ์ฐ๊ฒฐ์ ์์ ์ ์ผ๋ก ์ป๊ฑฐ๋ ๋ง๋๋ ๋ฐฉ๋ฒ์
๋๋ค. while(!availableConnections) { tryToGetConnection() }
์ ๊ฐ์ ์์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. node-pool
์ (๊ณผ) ์ํธ ์์ฉํด์ผํฉ๋๊น? Knex์์ ์ด๋ป๊ฒ ์ํ ํ ์ ์์ต๋๊น?
Knex ํ๋ง์ ๋์ผํ ๋ ธ๋ ํ๋ก์ธ์ค์์ ์ฐ๊ฒฐ์ด ์ด๋ฃจ์ด์ง ๊ฒฝ์ฐ์๋ง ์๋ํฉ๋๋ค.
AWS ๋๋ค ์ธ์คํด์ค๊ฐ ๊ณต์ ๋ ธ๋ ํ๋ก์ธ์ค๋ฅผ ์คํํ์ง ์๋ ๊ฒฝ์ฐ ๊ฐ ๋๋ค ์ธ์คํด์ค์์ ์ต์ / ์ต๋ ์ฐ๊ฒฐ์ด 1 ์ธ ์ ํ์ ์์ฑํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ฐฑ ๊ฐ์ ๋์ ์ฐ๊ฒฐ์ ํ์ฉ ํ ์์๋ ์ถฉ๋ถํ ์ค์ ์ด ์๊ธฐ๋ฅผ ๋ฐ๋ผ๋ฉด๋ฉ๋๋ค (RDS์์๋ ์ธ์คํด์ค ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ค๋ฆ). ).
์ด https://forums.aws.amazon.com/thread.jspa?threadID=216000์ ์ฝ์ ํ
๋๋ค๊ฐ ์ค์ ๋ก ์ผ๋ถ ํ๋ก์ธ์ค๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ฏ๋ก ์์ฑ ๋ ๋๋ค ์ปจํ ์ด๋์ ์ต๋ ๊ฐ์๋ฅผ ํ์ ํ ์ ์๋ค๋ฉด ์ต์ ์ ํ ํฌ๊ธฐ๋ฅผ ๊ณ์ฐํ ์ ์์ด์ผํฉ๋๋ค (๊ฐ ์ปจํ ์ด๋์๋ ๋ณ๋์ ํ์ด ์์ผ๋ฏ๋ก DB์ ๋ํ ์ด ์ฐ๊ฒฐ์ ํ์ ๋๋ค. ์ต๋ * ์ต๋ ์ปจํ ์ด๋ ์).
์ด์จ๋ ํ์์ ์๋ ์ฐ๊ฒฐ ์์ฒญ์ ํ ํ์๊ฐ ์์ต๋๋ค. knex๋ ์๋์ผ๋ก ์ฐ๊ฒฐ์ ๊ธฐ๋ค๋ฆฝ๋๋ค. ๋ชจ๋ ๊ฒ์ด ๋ช ์ด ์์ ์๋ฃ๋๋ฉด ๊ทธ ์๊ฐ์ ์ด๋ค ํ์ ์์๋ ํธ๋ฆฌ๊ฑฐ๋์ง ์์ต๋๋ค.
์ต๋ ์ฐ๊ฒฐ ์์ ๋๋ฌํ๋ค๋ ์ค๋ฅ๊ฐ DB์์ ๋ฐ์ํ๋ฉด ์ต๋ ํ ํฌ๊ธฐ๋ฅผ ์๊ฒ ๋ง๋ค์ด์ผํฉ๋๋ค.
๋ฌธ์ฅ ์ค๊ฐ์ ์ ์ง๋ฌ์ ๋ฏธ์ ํด์, ์ ์์ด๊ฐ ๋ฐฉ๊ธ 3 ๋ฆฌํฐ์ ๋ฌผ์ ๋ฐ๋ฅ์ ๋์ก์ต๋๋ค.
๋ต์ฅ์ ๋ณด๋ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ฐ๊ฒฐ ์๊ฐ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ํฌ๊ฒ ๋ฌ๋ผ ์ง๋๋ผ๋ ์ต๋ ํ ํฌ๊ธฐ๋ฅผ ์ถ์ ํ๋ ๊ฒ์ด ์ต์ ์ ๋ฐฉ๋ฒ ์ธ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
๋ช ํํ๊ฒ ๋งํ๋ฉด Knex์์ ์ฐ๊ฒฐ์ ๋์ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋ง์ต๋๊น? ์ฐ๊ฒฐ ํ์ ํ๊ดดํ๋ ๊ธฐ๋ฅ ๋ง ์์ต๋๊น? Lambda๊ฐ ๋๋๋ก ์ปจํ ์ด๋๋ฅผ ์ฌ์ฌ์ฉํ๋ค๋ ์ฌ์ค์ ๋ชจ๋ ๊ฒ์ ํฌ๊ธฐํฉ๋๋ค.
์ปค๋ฅ์ ํ์ ํ๊ดดํ๋ฉด ๋ชจ๋ ์ปค๋ฅ์ ๋ ํ๊ดด๋๊ณ (๋จผ์ ์๋ฃ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค) ๋๋ค๊ฐ ์ปจํ ์ด๋๋ฅผ ํ๊ดด ํ ๋ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ ๋ ๋ ์ด๋ ค์๋ ๋ชจ๋ TCP ์์ผ์ด ๋ฌต์์ ์ผ๋ก ๋ซํ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค.
ํ๋ง์ ์ด์ ์ ํ๊ดดํ๊ธฐ ๋๋ฌธ์ ๊ฐ ์์ฒญ ํ์ ๋ช ์ ์ ์ผ๋ก ์ฐ๊ฒฐ์ ๋ซ์์ผํ๋ ์ด์ ๋ฅผ ์ ์ ์์ต๋๋ค. ํฌ๊ธฐ๊ฐ 1 ์ธ ํ์ ๋ง๋ค๊ณ ๋์ค์ ์ ๊ฑฐํ๋ฉด ๋์ผํ ํจ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
์ฌ์ฉํ์ง ์๊ณ ํ์์ ์์ ์ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒฝ์ฐ ์๋์ผ๋ก ์ฐ๊ฒฐ์ ๋ซ๋ ํ์ ๋ํ ์ ํด ์๊ฐ ์ ํ์ ๊ตฌ์ฑ ํ ์๋ ์์ต๋๋ค.
Knex๋ฅผ ์ฌ์ฉํ์ฌ COPY ์ฟผ๋ฆฌ๋ฅผ RedShift ํด๋ฌ์คํฐ์ ๋ณด๋ด๊ณ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์์ ์ ์์ต๋๊น?
pg Pool๋ก์ด ์์ ์ ์ํํ๋ฉด Lambda ํจ์ ๋์ ๋๋ฌํ๋ ์ฆ์ ์ฟผ๋ฆฌ๊ฐ ์ข ๋ฃ๋ฉ๋๋ค.
@BardiaAfshin ๋๋ค ์ปจํ ์ด๋๊ฐ ํ๊ดด๋๊ณ ๋๋ค ํจ์ ๋์ ๋๋ฌํ์ ๋ ๋ชจ๋ ์์ผ์ด ํด์ ๋๋ฉด์ด ๊ฒฝ์ฐ db ์ฟผ๋ฆฌ๋ ์ข ๋ฃ๋๊ณ ์๋ฃ๋์ง ์์ ์ ์์ต๋๋ค.
๊ฒฐ๊ณผ ๊ฐ์ ์ฝ๊ธฐ ์ ์ ์์ ์ ํธ๋์ญ์ ์ด ์๋ฃ๋์ง ์์ COPY ์ฟผ๋ฆฌ๊ฐ ๋กค๋ฐฑ๋๋ ๊ฒฝ์ฐ postgresql์ด ํด๋ผ์ด์ธํธ ์ธก ์ฐ๊ฒฐ ์ข ๋ฃ์ ์ด๋ป๊ฒ ๋ฐ์ํ๋์ง ํ์คํ์ง ์์ต๋๋ค.
์ด์จ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ผ ์ ์๋์ง ์ฌ๋ถ๋ knex์ ๋ฌ๋ ค ์์ง ์์ง๋ง aws lambda ๋ฐ postgresql์ ์๋ ๋ฐฉ์์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค.
๋ด ๊ด์ฐฐ์ ์ฟผ๋ฆฌ๊ฐ RedShift์์ ์ข ๋ฃ๋๊ณ ๋กค๋ฐฑ๋๋ค๋ ๊ฒ์ ๋๋ค.
์ด์จ๋ ํ์์ ์๋ ์ฐ๊ฒฐ ์์ฒญ์ ํ ํ์๊ฐ ์์ต๋๋ค. knex๋ ์๋์ผ๋ก ์ฐ๊ฒฐ์ ๊ธฐ๋ค๋ฆฝ๋๋ค. ๋ชจ๋ ๊ฒ์ด ๋ช ์ด ์์ ์๋ฃ๋๋ฉด ๊ทธ ์๊ฐ์ ์ด๋ค ํ์ ์์๋ ํธ๋ฆฌ๊ฑฐ๋์ง ์์ต๋๋ค.
db๋ก๋ ํ ์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์คํ ์ค์ด๋ฉฐ ์ด๊ฒ์ด ์ฌ์ค์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋์ ์ฐ๊ฒฐ ์๊ฐ 30 ๊ฐ ์ด์์ด๋ฉด ์ฐ๊ฒฐ์ด ์ด๋ ค์์ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ฆ์ ์๊ฐ์ด ์ด๊ณผ๋ฉ๋๋ค.
์ฟผ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ํ์ฌ ์ฌ์ฉ์ค์ธ ์ฐ๊ฒฐ์ ์๋์ผ๋ก ํด์ ํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
AWS Lambda์ ๋ฐฉ๊ธ ๋ค์ด๊ฐ ์ฌ๋๋ค์ ์ํด ๊ณต์ ํ ์์๋ ์์ ์ฝ๋๊ฐ ์์ต๋๊น? ๋๊ตฐ๊ฐ knex / postgres / lambda์ ํจํด ๋ฐ / ๋๋ ์ํฐ ํจํด์ ๊ณต์ ํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๋ด๊ฐ ์ง๊ธ ์ฌ์ฉํ๊ณ ์๋ ๊ฒ์ ์ด๊ฒ์ด ๊ฐ์ ๋ ์ ์๋ค๊ณ ํ์ ํ์ง๋ง, ๋ด๊ฐ ์ฌ๋ฐ๋ฅธ ๊ธธ์ ๊ฐ๊ณ ์๋์ง์ ๋ํด ์ฝ๊ฐ์ ์นํธ๋ฅผ ๊ธฐ๋ํ๊ณ ์์ต๋๋ค.
'use strict';
var pg = require('pg');
function initKnex(){
return require('knex')({
client: 'pg',
connection: { ...details... }
});
}
module.exports.hello = (event, context) =>
{
var knex = initKnex();
// Should I be returning knex here or in the final catch?
knex
.select('*')
.from('my_table')
.then(function (rows) {
context.succeed('Succeeded: ' + JSON.stringify(rows || []));
})
.catch(function (error) {
context.fail(error);
})
.then(function(){
// is destroy overkill? - is there an option for knex.client.release, etc?
knex.destroy();
})
}
๋๋ ๊ฐ์ ๋ฐฐ๋ฅผ ํ๊ณ ์์ต๋๋ค. ๋ง์ ์ธํฐ๋ท ๊ฒ์๊ณผ ํ ์คํธ์๋ ๋ถ๊ตฌํ๊ณ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ์์ง ํ์ ํ์ง ๋ชปํ์ต๋๋ค. ๋ด๊ฐ ์ง๊ธํ๊ณ ์๋ ๊ฒ์ :
const dbConfig = require('./db');
const knex = require('knex')(dbConfig);
exports.handler = function (event, context, callback) {
...
connection = {..., pool: { min: 1, max: 1 },
์ด๋ ๊ฒํ๋ฉด ์ฐ๊ฒฐ (์ปจํ ์ด๋ ๋น ์ต๋ 1 ๊ฐ)์ด ์ ์ง๋์ด ์ปจํ ์ด๋๋ฅผ ์ฝ๊ฒ ์ฌ์ฌ์ฉ ํ ์ ์์ต๋๋ค. ๋๋ ๊ฒฐ๊ตญ ๋ด ์ฐ๊ฒฐ์ ํ๊ดดํ์ง ์์ต๋๋ค.
http://blog.rowanudell.com/database-connections-in-lambda/
์ด๊ฒ์ด ์ต์ ์ ๋ฐฉ๋ฒ์ธ์ง ํ์คํ์ง ์์ง๋ง ์ง๊ธ๊น์ง ๋๋ฅผ ์ํด ์ผํ์ต๋๋ค.
/์ด๊นจ๋ฅผ ์ผ์ฑํ๋ค
์๋ ํ์ธ์.
const knex
๊ฐ ์ ์ธ๋๋ฉด ์ด๋ค ์ผ์ด ๋ฐ์ํ๋์ง ์ ํํ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ด๊ธฐ ์ฐ๊ฒฐ์ด ์ค์ ๋๋ ๊ณณ์
๋๊น? ๋๊ตฐ๊ฐ ๋ช
ํํ ํ ์ ์์ต๋๊น? (dbConfig์ ์ฐ๊ฒฐ ์ ๋ณด๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค)
์ฝ๋์์ ํธ๋ค๋ฌ๊ฐ ํธ์ถ ๋ ๋๋ง๋ค ์ฐ๊ฒฐ ์์ฒด๋ฅผ ๋ฎ์ด ์ฐ๊ณ ๋ค์ ์์ฑํ์ง ์์ต๋๊น?
๊ฐ์ ๋ณดํธ์์๋ ์ฌ๋์๊ฒ ์ฐจ๋ฅผ ์น๋ ๊ฒ๋ง์ผ๋ก๋ ์ปจํ ์ด๋์ ์์์ฅ ํฌ๊ธฐ๋ฅผ ์์ ๋ด๋ ค๊ณ ๋ ธ๋ ฅํ ์ ์ ์ด์ด ์์์ต๋๋ค ( @elhigu ์ ์ ์์ ๋ฐ๋ผ). ๋ด ํด๊ฒฐ์ฑ ์ ๋ชจ๋ ์ฐ๊ฒฐ ํ ํ์ ํ๊ดดํ๋ ๊ฒ์ ๋๋ค (์ต์ ์ด ์๋๋ผ๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค ๐).
const knex = require('knex');
const client = knex(dbConfig);
client(tableName).select('*')
.then((result) => {
return Promise.all([
result,
client.destroy(),
])
})
.then(([ result ]) => {
return result;
});
์์ฝ : ์ฝ๋ฐฑ์ ํธ์ถํ๊ธฐ ์ ์
context.callbackWaitsForEmptyEventLoop = false
ํ๊ธฐ ๋งํ๋ฉด๋ฉ๋๋ค.
AWS Lambda๋ ๋น ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค (๊ธฐ๋ณธ์ ์ผ๋ก). ๊ทธ๋์ ํจ์๋ ์ฝ๋ฐฑ์ด ์คํ ๋์ด๋ Timeout ์ค๋ฅ๋ฅผ ๋์ง ์ ์์ต๋๋ค.
์์ธํ ๋ด์ฉ์ ์๋ ๋งํฌ๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
https://github.com/apex/apex/commit/1fe6e91a46e76c2d5c77877be9ce0c206e9ef9fb
@elhigu @tgriesser์๊ฒ : ์ด๊ฒ์ knex ๋ฌธ์ ๊ฐ ์๋๋๋ค. ์ด๊ฒ์ ํ์คํ ๋๋ค ํ๊ฒฝ์ ๋ฌธ์ ์ ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ์ง๋ฌธ์ ํ๊ทธํ๊ณ ์ข ๋ฃํ๋ ๊ฒ์ด ์ข์ต๋๋ค. :)
@mooyoul yep, ํ์คํ knex ๋ฌธ์ ๋ ์๋์ง๋ง ๋ฌธ์ ๋ฌธ์ ์ผ ์ ์์ต๋๋ค.
์ด ๋งํฌ๋ฅผ ๋ด์ฃผ์ธ์
https://stackoverflow.com/questions/49347210/why-aws-lambda-keeps-timing-out-when-using-knex-js
db ์ฐ๊ฒฐ์ ๋ซ์์ผํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด Lambda๊ฐ ์๊ฐ ์ด๊ณผ ๋ ๋๊น์ง ์คํ๋ฉ๋๋ค.
Lambda์ ํจ๊ป Knex๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ์๋ฒฝํ๊ฒ ์๋ํ๋ ํจํด์ ์ฐพ์ ์ฌ๋์ด ์์ต๋๊น?
์ฐ๊ฒฐ์ ์ ๋๋ก ์ข ๋ฃํ๋ฉด ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
ํผํ๋ ค๋ ๊ฒ์ ์ฐ๊ฒฐ์ ๋ซ๊ณ Lambda ํธ์ถ์์ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋๋ ๊ฒ์ ๋๋ค.
Lambda๊ฐ ํธ์ถ๊ฐ์ ์ํ๋ฅผ ์ ์งํ๋๋ก ํ์ฉํฉ๋๊น?
https://scalegrid.io/blog/how-to-use-mongodb-connection-pooling-on-aws-lambda/ ์ node.js ๋ถ๋ถ์
๋๋ ์ด๋ ๊ฒ ์ค๋ ๋๋ฅผ ๋ถ๋ชํ๋ ๊ฒ์ ์ข์ํ์ง ์์ง๋ง ๋๊ธ์์ ๊ธธ์ ์๊ณ ์๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ์ ์ @mooyoul ์ ๋ต๋ณ ์ด ์ฐ๋ฆฌ์๊ฒ ํฐ ๋์์ด๋์์ต๋๋ค.
ํด๋น ํ๋๊ทธ๋ฅผ false๋ก ์ค์ ํ์ง ์์ผ๋ฉด Lambda๋ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ๋น์ด์์ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ๊ทธ๋ ๊ฒํ๋ฉด ์ฝ๋ฐฑ์ ํธ์ถํ์๋ง์ ํจ์๊ฐ ์คํ์ ์๋ฃํฉ๋๋ค.
์ ์๊ฒ๋ ๋ก์ปฌ ์ปดํจํฐ์์ ์๋ํ์ง๋ง ๋ฐฐํฌ ํ์๋ ์๋ํ์ง ์์์ต๋๋ค. ๋๋ ์คํด๋ฅผ ๋ฐ์๋ค.
RDS ์ธ๋ฐ์ด๋ ์์ค๊ฐ Lambda ํจ์์ ์ด๋ ค ์์ง ์์ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. Stack Overflow ์์ ์๋ฃจ์
์ ์ฐพ์์ต๋๋ค. RDS ์ธ๋ฐ์ด๋ ์์ค๋ฅผ 0.0.0.0/0
ํ๊ฑฐ๋ VPC๋ฅผ ์ฌ์ฉํฉ๋๋ค.
RDS ์ธ๋ฐ์ด๋ ์์ค๋ฅผ ์ ๋ฐ์ดํธ ํ ํ Knex๋ก Lambda๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ด๊ฐ ์ฌ์ฉ์ค์ธ Lambda ๋ฐํ์์ ํจํค์ง์ ํจ๊ป Node.js 8.10
์
๋๋ค.
knex: 0.17.0
pg: 7.11.0
๋น๋๊ธฐ๋ฅผ ์ฌ์ฉํ๋ ์๋ ์ฝ๋๋ ์๋ํฉ๋๋ค.
const Knex = require('knex');
const pg = Knex({ ... });
module.exports. submitForm = async (event) => {
const {
fields,
} = event['body-json'] || {};
return pg('surveys')
.insert(fields)
.then(() => {
return {
status: 200
};
})
.catch(err => {
return {
status: 500
};
});
};
์์ผ๋ก ๊ฐ์ ๋ฌธ์ ๋ฅผ ๋ง๋ ์์๋ ์ฌ๋๋ค์๊ฒ ๋์์ด๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
์ฌ๋๋ค์ ๊ด์ฌ์ ๋๊ณ ์ถ์ ๊ฒ์ serverless-mysql ํจํค์ง๋ก, ํ์ค mysql
๋๋ผ์ด๋ฒ๋ฅผ ๋ํํ์ง๋ง์ด ์ค๋ ๋์์ ์ค๋ช
ํ๋ ์ฐ๊ฒฐ ํ ๊ด๋ฆฌ์ ๊ด๋ จ๋ ๋ง์ ๋๋ค ๊ด๋ จ ๋ฌธ์ ์ ์ ์ฒ๋ฆฌํฉ๋๋ค.
๊ทธ๋ฌ๋ ๋ค๋ฅธ ๋๋ผ์ด๋ฒ๋ก ๋ฐ๊ฟ ์์๋ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ Knex๊ฐ ํ์ฌ serverless-mysql
์์ ์๋ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค ( ์ด ๋ฌธ์ ์ ๋ฐ๋ผ). serverless-mysql
๋ ์ฝ๋ฐฑ ๋์ promise๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋น ํธํ์ฑ์ด์์ ์๋ ์์ต๋๋ค.
๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์๋ง๋ Knex์ ์๋ก์ด ํด๋ผ์ด์ธํธ ๊ตฌํ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค. ์ด ๊ธฐํ๋ฅผ ์ฃผ์๋ฉด ๊ธฐ๊บผ์ดํ์ง๋ง Knex์ ๋ ์ต์ํ ์ฌ๋์ด ํฉ๋ฆฌ์ ์ด๊ณ ์คํ ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํ๋์ง ๋งํด ์ฃผ๋ฉด ์ข๊ฒ ์ต๋๊น?
๋ํ ๊ทธ๋์ Knex๋ฅผ ์ฌ์ฉํ์ฌ MySQL ์ฟผ๋ฆฌ๋ฅผ _build_ํ์ง๋ง _not execute_ ํ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค. ๋ฐ๋ผ์ toSQL()
ํธ์ถํ๊ณ ์ถ๋ ฅ์ serverless-mysql
ํ์ฌ ์คํํฉ๋๋ค.
DB ์ฐ๊ฒฐ์์ด Knex๋ฅผ ๊ตฌ์ฑ ํ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ์ฌ์ฉํ์ง ์์ ์ฐ๊ฒฐ์ ์ฌ๋ ๊ฒ์ ์๋ฏธ๊ฐ ์์ต๋๋ค.
๋ค์์ด ์๋ํฉ๋๊น?
connection = {..., pool: { min: 0, max: 0 ) },
@disbelief ์ฐ๊ฒฐ์์ด knex๋ฅผ ์ด๊ธฐํ ํ ์ ์์ต๋๋ค. https://knexjs.org/#Installation -client ๋ฌธ์์์ด ์น์ ์ ๋ ๋ถ๋ถ์์ด๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ ๊ฐ ์์ต๋๋ค.
const knex = require('knex')({client: 'mysql'});
const generatedQuery = knex('table').where('id',1).toSQL().toNative();
@elhigu ์ ๋ฉ์ง๋ค, ๊ฐ์ฌํฉ๋๋ค. ๊ทธ ์ค๊ฐ์ ๊ธฐํ๋ฅผ ์ค ๊ฒ์ ๋๋ค.
์ ๋ฐ์ดํธ : ์์ ๋ด์ฉ์ด ์๋ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. Knex๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ธฐ์ํ ํธ์ถ์ด์๋ ๊ฒฝ์ฐ์๋ db ์ฐ๊ฒฐ์ ์ค์ ํ ์์๋ ๊ฒฝ์ฐ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค.
@disbelief ๊ทธ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ฐพ์์ต๋๊น?
@fdecampredon ์๋์์ . ์ง๊ธ์ ๋จ์ํ squel์ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ๋ฅผ toString()
๋ฅผ ํธ์ถํ๊ณ serverless-mysql
ํด๋ผ์ด์ธํธ์ ์ ๋ฌํ๊ณ ์์ต๋๋ค.
@disbelief db ์ฐ๊ฒฐ์์ด ์ฟผ๋ฆฌ ์์ฑ์ด ์คํจํ ๊ฒ์ด ๋๋์ต๋๋ค.
knex ํด๋ผ์ด์ธํธ๋ฅผ ๋น๋ํ๋ ๋ฐ ์ฌ์ฉ์ค์ธ ์ฝ๋ ๋ฐ ๊ตฌ์ฑ์ ๊ฒ์ ํด ์ฃผ์๊ฒ ์ต๋๊น? ๋ํ knex ๋ฒ์ .
๋ค์์ ๋๋ฅผ ์ํด ์ ์๋ํฉ๋๋ค.
๋
ธ๋ v8.11.1
mysql
: 2.13.0
knex
: 0.18.3
const k = require('knex')
const client = k({ client: 'mysql' })
console.log('Knex version:', require('knex/package.json').version)
// => 0.18.3
console.log('sql:', client('table').where('id',1).toSQL().toNative())
// => { sql: 'select * from `table` where `id` = ?', bindings: [ 1 ] }
Lambda์ ๋ฆฌ์์ค ์ฌํ์ฉ ์๋ ๋ฐฉ์์ ๋ฐ๋ผ Knex
์ธ์คํด์ค๋ ํญ์ ํจ์ ๋๋ ํด๋์ค ์ธ๋ถ์ ์ ์ง๋์ด์ผํฉ๋๋ค. ๋ํ ํ์ ์ต๋ 1 ๊ฐ๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ๊ฒ :
const Knex = require('knex');
let instance = null;
module.exports = class DatabaseManager {
constructor({ host, user, password, database, port = 3306, client = 'mysql', pool = { min: 1, max: 1 }}) {
this._client = client;
this._poolOptions = pool;
this._connectionOptions = {
host: DB_HOST || host,
port: DB_PORT || port,
user: DB_USER || user,
password: DB_PASSWORD || password,
database: DB_NAME || database,
};
}
init() {
if (instance !== null) {
return;
}
instance = Knex({
client: this._client,
pool: this._poolOptions,
connection: this._connectionOptions,
debug: process.env.DEBUG_DB == true,
asyncStackTraces: process.env.DEBUG_DB == true,
});
}
get instance() {
return instance;
}
}
์ด๋ฌํ ๋ฐฉ์์ผ๋ก Lambda์ ์ฌํ์ฉ์ ์ต๋ํ ํ์ฉํ ์ ์์ต๋๋ค. ์ฆ, ํ์ฑํ ๋ (๊ณ ์ ๋) ๊ฐ ์ปจํ ์ด๋๋ ๋์ผํ ์ฐ๊ฒฐ ๋ง ์ ์งํฉ๋๋ค.
์ฐธ๊ณ ๋ก ๋์ ์ปจํ ์ด๋ ์๋ฅผ ์ ํํ์ง ์์ผ๋ฉด Lambda๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฅ๋๋ค๋ ์ ์ ์ ์ํ์ญ์์ค.
์ ๋ Knex๋ฅผ Lambda์์ ๊ฑฐ์ 1 ๋
๋์ ์๋ฌด ๋ฌธ์ ์์ด ์คํํ์ต๋๋ค. ๋ด Lambda ํจ์ ์ธ๋ถ์์ ๋ด Knex ์ธ์คํด์ค๋ฅผ ์ ์ธํ๊ณ ๋ค๋ฅธ ๊ฒ์๋ฌผ์์ ์ธ๊ธ ํ๋๋ก context.callbackWaitsForEmptyEventLoop = false
๋ฅผ ํ์ฉํ๊ณ ์์ต๋๋ค.
์ฆ, ์ง๋ ํ๋ฃจ ๋์ Postgres์์ ์์ฒญ๋ ์ฐ๊ฒฐ ์คํ์ดํฌ๋ฅผ๋ณด๊ณ ์๋ ๊ฒ์ฒ๋ผ Lambda ์ธก์์ ๋ฌด์ธ๊ฐ ๋ณ๊ฒฝ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฐ๊ฒฐ์ด ๋ซํ ์์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค.
์์ ์ธ๊ธ ํ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ฌ๋์ด ์ง๋ ํ๋ฃจ ๋์ ๊ธฐํ๋ฅผ ๋ณธ ์ ์ด ์์ต๋๊น?
@jamesdixon ์ ๋๋ค์ ๋ํ knex ๊ตฌํ์ ์ผ๋ถ๋ฅผ ๋ฆฌํฉํ ๋งํ๋ฉด์ ์ง๊ธ ์ด๊ฒ์ ์ฝ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ๋ํ ์
๋ฐ์ดํธ๊ฐ ์์ต๋๊น? context.callbackWaitsForEmptyEventLoop = false
์๋์ด ์ค์ง ๋์์ต๋๊น?
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ฌธ์ฅ ์ค๊ฐ์ ์ ์ง๋ฌ์ ๋ฏธ์ ํด์, ์ ์์ด๊ฐ ๋ฐฉ๊ธ 3 ๋ฆฌํฐ์ ๋ฌผ์ ๋ฐ๋ฅ์ ๋์ก์ต๋๋ค.