๐ํค์๋: ์๋ฒ, ๋ฐฐํฌ, ๊นํ๋ธ, AWS, GCP
1. morgan๊ณผ express-session
- ๋ฏธ๋ค์จ์ด๋ค์ ๋ฐฐํฌ์ฉ์ ์ค์ ํ๋ค.
//app.js
...
sequelize.sync({ force: false })
.then(() => {
console.log('๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ฑ๊ณต');
})
.catch((err) => {
console.error(err);
});
if (process.env.NODE_ENV === 'production') {
app.enable('trust proxy');
app.use(morgan('combined'));
app.use(
helmet({
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false,
crossOriginResourcePolicy: false,
}),
);
app.use(hpp());
} else {
app.use(morgan('dev'));
}
app.use(express.static(path.join(__dirname, 'public')));
...
-> process.env.NODE_EW๋ ๋ฐฐํฌ ํ๊ฒฝ์ธ์ง ๊ฐ๋ฐ ํ๊ฒฝ์ธ์ง๋ฅผ ํ๋จํ ์ ์๋ ํ๊ฒฝ ๋ณ์์ด๋ค.
->combined ๋ชจ๋๋ dev ๋ชจ๋์ ๋นํด ๋ ๋ง์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ก๊ทธ๋ก ๋จ๊ธฐ๋ฏ๋ก ์ถํ ๋ฒ๊ทธ๋ฅผ ํด๊ฒฐํ ๋ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
- express-session์ ๋ฐฐํฌ์ฉ์ผ๋ก ์ค์ ํ๋ค.
//app.js
...
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
store: new RedisStore({ client: redisClient }),
};
if (process.env.NODE_ENV === 'production') {
sessionOption.proxy = true;
// sessionOption.cookie.secure = true;
}
app.use(session(sessionOption));
app.use(passport.initialize());
...
->๋ฐฐํฌ ํ๊ฒฝ์ผ ๋๋ proxy์ cookie.secure๋ฅผ true๋ก ๋ฐ๊พผ๋ค.
2. ์ํ๋ผ์ด์ฆ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋ฐฐํฌ ํ๊ฒฝ์ผ๋ก ์ค์ ํ๋ค.
- ์ํ๋ผ์ด์ฆ์์ ๋น๋ฐ๋ฒํธ๊ฐ ํ๋ ์ฝ๋ฉ ๋์ด์๊ธฐ ๋๋ฌธ์ json์ ์ง์ฐ๊ณ js๋ฅผ ์์ฑํ๋ค.
//config/config.js
require('dotenv').config();
module.exports = {
development: {
username: 'root',
password: process.env.SEQUELIZE_PASSWORD,
database: 'nodebird',
host: '127.0.0.1',
dialect: 'mysql',
},
test: {
username: "root",
password: process.env.SEQUELIZE_PASSWORD,
database: "nodebird_test",
host: "127.0.0.1",
dialect: "mysql"
},
production: {
username: 'root',
password: process.env.SEQUELIZE_PASSWORD,
database: 'nodebird',
host: '127.0.0.1',
dialect: 'mysql',
logging: false,
},
};
->JS ํ์ผ์ด๋ฏ๋ก dotenv ๋ชจ๋์ ์ฌ์ฉํ ์ ์๋ค.
โป username ์์ฑ์ด๋ host ์์ฑ์ ๊ฐ๊ฐ ์์ด๋์ DB์๋ฒ ์ฃผ์ ์ญํ ์ ํ๋ฏ๋ก ์จ๊ธฐ๋ ๊ฒ ์ข๋ค.
โป ๋ฐฐํฌ ํ๊ฒฝ์์๋ ์ด๋ค ์ฟผ๋ฆฌ๊ฐ ์ํ๋๋์ง ์จ๊ธฐ๋ ๊ฒ์ด ์ข๋ค.
//.env
COOKIE_SECRET=nodebirdsecret
KAKAO_ID=5d4daf57becfd72fd9c919882552c4a6
SEQUELIZE_PASSWORD=nodejsbook
REDIS_HOST=redis-18954.c92.us-east-1-3.ec2.cloud.redislabs.com
REDIS_PORT=18954
REDIS_PASSWORD=JwTwGgKM4P0OFGStgQDgy2AcXvZjX4dc
->๋ฐ์ดํฐ๋ฒ ์ด์ค ๋น๋ฐ๋ฒํธ๋ .env ํ์ผ์ ์
๋ ฅํ๋ค.
3. cross-env
- cross-env ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ ์ผ๋ก process.env(ํ๊ฒฝ ๋ณ์)๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
//package.json
{
"name": "nodebird",
"version": "0.0.1",
"description": "์ต์คํ๋ ์ค๋ก ๋ง๋๋ SNS ์๋น์ค",
"main": "server.js",
"scripts": {
"start": "cross-env NODE_ENV=production PORT=80 pm2 start server.js -i 0",
"dev": "nodemon server",
"test": "jest"
},
...
->์๋ฒ ์คํ์ ์ํ npm ์คํฌ๋ฆฝํธ๋ฅผ ๋ ๊ฐ๋ก ๋๋๋ค.
->npm start(๋ฐฐํฌ ํ๊ฒฝ), npm run dev(๊ฐ๋ฐ ํ๊ฒฝ) ์คํฌ๋ฆฝํธ์ด๋ค.
4. sanitize-html, csurf
- sanitize-html๊ณผ csurf ํจํค์ง๋ ๊ฐ๊ฐ XSS, CSRF ๊ณต๊ฒฉ์ ๋ง๊ธฐ ์ํ ํจํค์ง์ด๋ค.
- XXS๋ ์
์์ ์ธ ์ฌ์ฉ์๊ฐ ์ฌ์ดํธ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฝ์
ํ๋ ๊ณต๊ฒฉ์ด๋ค.
->์
์ฑ ์ฌ์ฉ์๊ฐ ๊ฒ์๊ธ์ด๋ ๋๊ธ ๋ฑ์ ์
๋ก๋ํ ๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ํฌํจ๋ ํ๊ทธ๋ฅผ ์ฌ๋ฆฌ๋ฉด, ๋์ค์ ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ๊ทธ ๊ฒ์๊ธ์ด๋ ๋๊ธ์ ๋ณผ ๋ ํด๋น ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋์ด ์๊ธฐ์น ๋ชปํ ๋์์ ํ๊ฒ ๋๋ค. (์๋ฒ์์๋ ์ฌ์ฉ์๊ฐ ๊ฒ์๊ธ์ ์
๋ก๋ํ ๋ ์คํฌ๋ฆฝํธ๊ฐ ํฌํจ๋์ด ์๋์ง ๊ฒ์ฌํด์, ์กด์ฌํ๋ค๋ฉด ์ ๊ฑฐํด์ผ ํ๋ค.)
const sanitizeHtml=require('sanitize-html');
const html="<script>location.href='https://gilbut.co.kr'</script>";
console.log(sanitizeHtml(html));
->์ฌ์ฉ์๊ฐ ์
๋ก๋ํ HTML์ sanitize-html ํจ์๋ก ๊ฐ์ธ๋ฉด ํ์ฉํ์ง ์๋ ํ๊ทธ๋ ์คํฌ๋ฆฝํธ๋ ์ ๊ฑฐ๋๋ค.
- CSRF๋ ์ฌ์ฉ์๊ฐ ์๋์น ์๊ฒ ๊ณต๊ฒฉ์๊ฐ ์๋ํ ํ๋์ ํ๊ฒ ๋ง๋๋ ๊ณต๊ฒฉ์ด๋ค.
-> ex) ํน์ ํ์ด์ง์ ๋ฐฉ๋ฌธํ ๋ ์ ์ ๋ก ๋ก๊ทธ์์๋๊ฑฐ๋ ๊ฒ์๊ธ์ด ์จ์ง๋ ํ์์ ์ ๋ํ ์ ์๋ค.
->๊ณต๊ฒฉ์ ๋ง๊ธฐ ์ํด์ ๋ด๊ฐ ํ ํ๋์ด ๋ง๋ค๋ ์ฌ์ค์ ์ธ์ฆํด์ผ ํ๊ณ , ์ด๋ CSRF ํ ํฐ์ด ์ฌ์ฉ๋๋ค.
โป ์ํฉ์ ๋ฐ๋ผ CSRF ํ ํฐ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ด ๋ค๋ฅด๋ฏ๋ก ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ๋ค.
5. pm2
- pm2๋ ์ํํ ์๋ฒ ์ด์์ ์ํ ํจํค์ง์ด๋ค.
- ๊ฐ์ฅ ํฐ ๊ธฐ๋ฅ์ ์๋ฒ๊ฐ ์๋ฌ๋ก ์ธํด ๊บผ์ก์ ๋ ์๋ฒ๋ฅผ ๋ค์ ์ผ์ค๋ค.
- ๋ฉํฐ ํ๋ก์ธ์ฑ์ ์ง์ํด ๋
ธ๋ ํ๋ก์ธ์ค ๊ฐ์๋ฅผ ํ ๊ฐ ์ด์์ผ๋ก ๋๋ฆด ์ ์๋ค.
ex) ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์์ฒญ์ด ์ฌ ๋ ์์์ ์์ฒญ์ ์ฌ๋ฌ ๋
ธ๋ ํ๋ก์ธ์ค์ ๊ณ ๋ฅด๊ฒ ๋ถ๋ฐฐํ๋ค.
- ๋จ์ ์ผ๋ก๋ ๋ฉํฐ ์ค๋ ๋ฉ์ด ์๋๋ฏ๋ก ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ ์์์ ๊ณต์ ํ์ง๋ ๋ชปํ๋ค. (๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ์ง ๋ชปํด์ ํ๋ก์ธ์ค ๊ฐ์ ์ธ์
์ด ๊ณต์ ๋์ง ์๊ฒ ๋๋ค.)
->์ธ์
์ ๊ณต์ ํ ์ ์๊ฒ ํด์ฃผ๊ธฐ ์ํด ๋ฉค์ผ์๋(Memcached)๋ ๋ ๋์ค(Redis) ๊ฐ์ ์๋น์ค๋ฅผ ์ด์ฉํ๋ค.
->npm i pm2(pm2 ์ค์น)
-> nodemon ๋์ pm2๋ฅผ ์ฐ๋๋ก npm start ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํ๋ค.
->node๋ nodemon ๋ช
๋ น์ด์๋ ๋ค๋ฅด๊ฒ ๋
ธ๋ ํ๋ก์ธ์ค๊ฐ ์คํ๋ ํ ์ฝ์์ ๋ค๋ฅธ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ ์ ์๋ค.
- ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋๊ณ ์๋ ๋
ธ๋ ํ๋ก์ธ์ค๋ฅผ ํ์ธํ ๋ฐฉ๋ฒ: npx pm2 list
->ํ์ฌ ํ๋ก์ธ์ค ์ ๋ณด ํ์
- pm2 ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃํ๊ณ ์ถ๋ค๋ฉด ์ฝ์์ npx pm2 kill ์
๋ ฅํ๋ค.
- ์๋ฒ๋ฅผ ์ฌ์์ํ๊ณ ์ถ๋ค๋ฉด npx pn2 reload all์ ์
๋ ฅํ๋ค. (๋ค์ดํ์์ด ๊ฑฐ์ ์์ด ์๋ฒ๊ฐ ์ฌ์์๋์ด ์ข๋ค.)
- ๋
ธ๋์ cluster ๋ชจ๋์ฒ๋ผ ํด๋ฌ์คํฐ๋ง์ ๊ฐ๋ฅํ๊ฒ ํ๋ pm2์ ํด๋ฌ์คํฐ๋ง ๋ชจ๋๋ฅผ ์ฌ์ฉํ๋ค.
//package.json
{
"name": "nodebird",
"version": "0.0.1",
"description": "์ต์คํ๋ ์ค๋ก ๋ง๋๋ SNS ์๋น์ค",
"main": "server.js",
"scripts": {
"start": "cross-env NODE_ENV=production PORT=80 pm2 start server.js -i 0",
"dev": "nodemon server",
"test": "jest"
},
->pm2 start server.js ๋์ pm2 start server.js -i 0 ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ๋ค. (0์ ํ์ฌ CPU ์ฝ์ด ๊ฐ์๋งํผ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ๋ค๋ ๋ป์ด๋ค)
โป npx pm2 kill && npm start ์ฐ๋ฌ์ ์คํ ๊ฐ๋ฅํ๋ค.
- npx pm2 monit ๋ก ํ์ฌ ํ๋ก์ธ์ค๋ฅผ ๋ชจ๋ํฐ๋ง ๊ฐ๋ฅํ๋ค.
6. winston
- ์ค์ ์๋ฒ๋ฅผ ์ด์ํ ๋ console.log์ console.error๋ฅผ ๋์ฒดํ๊ธฐ ์ํ ๋ชจ๋์ด๋ค.
- console ๊ฐ์ฒด์ ๋ฉ์๋๋ค์ ์ธ์ ํธ์ถ๋์๋์ง ํ์
ํ๊ธฐ ํ๋ค ๋ฟ๋ง ์๋๋ผ ์๋ฒ๊ฐ ์ข
๋ฃ๋๋ ์๊ฐ ๋ก๊ทธ๋ค๋ ์ฌ๋ผ์ ธ๋ฒ๋ฆฐ๋ค. -> ์ด์ ๊ฐ์ ์ํฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ก๊ทธ๋ฅผ ํ์ผ์ด๋ ๋ค๋ฅธ ๋ฐ์ดํฐ ๋ฒ ์ด์ค์ ์ ์ฅํ๋ winston์ ์ฌ์ฉํ๋ค.
- npm i winston ์ค์น
//logger.js
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
level: 'info',
format: format.json(),
transports: [
new transports.File({ filename: 'combined.log' }),
new transports.File({ filename: 'error.log', level: 'error' }),
],
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new transports.Console({ format: format.simple() }));
}
module.exports = logger;
->winston ํจํค์ง์ createLogger ๋ฉ์๋๋ก logger๋ฅผ ๋ง๋ ๋ค.
->์ธ์ logger์ ๋ํ ์ค์ ์ผ๋ก level, format, transports ๋ฑ์ด ์๋ค.
->logger ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ค๋ฅธ ํ์ผ์ ์ฌ์ฉํ ์ ์๋ค. (info, warn, error ๋ฑ์ ๋ฉ์๋)
- ๊ฐ๋ฐ์ฉ ์๋ฒ๋ฅผ ์คํํ ํ http://localhost:8001/abcd์ ์ ์ํ๋ฉด 404 Not Found ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
->๋ก๊ทธ๋ฅผ ์ฝ์์๋ง ์ถ๋ ฅํ๋ ๊ฒ์ด ์๋๋ผ, ํ์ผ๋ก๋ ์ ์ฅํ ์ ์๋ค.
โป winston-daily-rotate-file์ด๋ผ๋ ๋ก๊ทธ๋ฅผ ๋ ์ง๋ณ๋ก ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ฃผ๋ ํจํค์ง๋ ์๋ค. (๊ณต์ ๋ฌธ์ ์ฐธ์กฐ)
7. helmet, hpp
- ์๋ฒ์ ๊ฐ์ข
์ทจ์ฝ์ ์ ๋ณด์ํด์ฃผ๋ ํจํค์ง์ด๋ฉฐ, ์ต์คํ๋ ์ค ๋ฏธ๋ค์จ์ด๋ก์ ์ฌ์ฉํ ์ ์๋ค.
- npm i helmet hpp (๊ฐ๋ฐ ํ๊ฒฝ์์๋ ์ฌ์ฉํ ํ์๊ฐ ์์ผ๋ฏ๋ก ๋ฐฐํฌ ํ๊ฒฝ์ผ ๋๋ง ์ ์ฉํ๋ฉด ๋๋ค.)
โป helmet๊ณผ hpp๊ฐ ๋ฐฉ์ดํด์ฃผ๋ ์ทจ์ฝ์ ๋ชฉ๋ก์ ๊ฐ๊ฐ์ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ์กฐํ๋ค. (๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐฐํฌ ์ ์ ์ด ๋ ํจํค์ง๋ฅผ ๋ฃ์ด์ฃผ๋ ๊ฒ์ด ์ข๋ค.)
8. connect-redis
- ๋ฉํฐ ํ๋ก์ธ์ค ๊ฐ ์ธ์
๊ณต์ ๋ฅผ ์ํด ๋ ๋์ค์ ์ต์คํ๋ ์ค๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ํจํค์ง์ด๋ค.
- ๊ธฐ์กด์๋ ์๋ฒ๊ฐ ์ข
๋ฃ๋์ด ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ ์๊ฐ๋ฉด ์ ์์๋ค์ ๋ก๊ทธ์ธ์ด ๋ชจ๋ ํ๋ ค๋ฒ๋ฆฐ๋ค.
-> ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ธ์
์์ด๋์ ์ค์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๋ค.
- npm i redis connect-redis (๋ ๋์ค๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด connect-redis ํจํค์ง๋ฟ๋ง ์๋๋ผ ๋ ๋์ค ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค์นํด์ผ ํ๋ค.)
โป ์ฑ
694-698์ ์ฐธ๊ณ ํด ์ค์นํ๋ค.
//app.js
...
const hpp = require('hpp');
const redis = require('redis');
const RedisStore = require('connect-redis').default;
dotenv.config();
const redisClient = redis.createClient({
url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`,
password: process.env.REDIS_PASSWORD,
});
redisClient.connect().catch(console.error);
const pageRouter = require('./routes/page');
...
const sessionOption = {
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
store: new RedisStore({ client: redisClient }),
};
...
-> connect-redis ํจํค์ง๋ก๋ถํฐ RedisStore ๊ฐ์ฒด๋ฅผ requireํ๋ค.
->redis ํจํค์ง์ crateClient ๋ฉ์๋๋ก redisClient ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
->express-session ๋ฏธ๋ค์จ์ด์๋ store ์ต์
์ ์ถ๊ฐํ๋ค.
=>์ธ์
์ ๋ณด๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ ๋์ค์ ์ ์ฅ๋์ด ๋ก๊ทธ์ธ ํ ์๋ฒ๋ฅผ ๊ป๋ค ์ผ๋ ๋ก๊ทธ์ธ์ด ์ ์ง๋๋ค.
9. nvm, n
- nvm-setup.zip์ ๋ด๋ ค๋ฐ์ ์์ถ ํด์ ํ ํ ์คํ์์ผ ์ค์นํ๋ฉด ์ฝ์์ nvm ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ ์ ์๋ค.
โป ๋งฅ, ๋ฆฌ๋
์ค์์๋ n ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ค.
- ๋
ธ๋ ๋ฒ์ ์ ์
๊ทธ๋ ์ด๋ ํ ํ ๊ธฐ์กด npm ํจํค์ง๋ค์ด ๋์ํ์ง ์๋ ๊ฒฝ์ฐ npm rebuild ๋ช
๋ น์ด๋ก ํด๊ฒฐํ ์ ์๋ค.
- AWS์ GCP์ ์์ค ์ฝ๋๋ฅผ ์
๋ก๋ ํ๊ธฐ ์ํด ๊น์ ์ด์ฉํ๋ค.
- ๊น(Git): ๋ถ์ฐํ ๋ฒ์ ๊ด๋ฆฌ ์์คํ
/ ๊นํ๋ธ(GitHub): ๊น์ผ๋ก๋ถํฐ ์
๋ก๋ํ ์์ค ์ฝ๋๋ฅผ ์๋ฒ์ ์ ์ฅํ ์ ์๋ ์๊ฒฉ ์ ์ฅ์์ด๋ค.
- ๊น์ ํ๋์ ์ปดํจํฐ์์ ์ฝ๋๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ ์ฌ์ฉํ์ง๋ง, ๊นํ๋ธ์ ์์ค ์ฝ๋๋ฅผ ์
๋ก๋ํ๋ฉด ์ฌ๋ฌ ์ฌ๋์ด ์ฝ๋๋ฅผ ๊ณตํต์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
1. ๊น ์ค์นํ๊ธฐ
- ๊น์ ์ค์นํ ๋ค์ ์ ๋๋ก ์ค์น๋์๋์ง ํ์ธํ๊ธฐ ์ํด ์ฝ์์ git --version ๋ก ๊น ๋ฒ์ ์ ํ์ธํ๋ค.
//.gitignore
node_modules
uploads
*.log
coverage
โป ์ค์ ์๋น์ค์์๋ .env ํ์ผ๋ ๊น์ ์ถ๊ฐํ์ง ๋ง์์ผ ํ๋ค. ๋ฐฐํฌ์ฉ ์๋ฒ์์ ์ง์ .env ํ์ผ์ ์์ฑํด ๋น๋ฐ ํค๋ฅผ ์ ์ด์ฃผ๋ ๊ฒ์ด ๋ฐ๋์งํ๋ค.
2. ๊นํ๋ธ ์ฌ์ฉํ๊ธฐ
- ํ์๊ฐ์
, ๋ก๊ทธ์ธ ํ ๋ฆฌํฌ์งํฐ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
- ์์ค ์ฝ๋๋ฅผ ๊น์ ์ถ๊ฐํ๊ธฐ ์ํด git init -> git add . (๋ชจ๋ ํ์ผ์ ์ถ๊ฐํ๊ฒ ๋ค๋ ์๋ฏธ) -> git config --global user.email " "
-> git config --global user.name " " -> git commit -m "Initial commit"
- ๋น๋ฐ๋ฒํธ ์ฉ๋๋ก ์ฌ์ฉํ ํ ํฐ์ ๋ฐ๊ธ๋ฐ์ git remote add origin https://์์ด๋:ํ ํฐ@github.com/์์ด๋/node-deploy
- ํ ๊นํ๋ธ์ ์
๋ก๋ ํ๋ค.
โป ํ ํฐ์ ์์ฑ ํ ํ ๋ฒ๋ง ๋ณด์ฌ์ฃผ๋ฏ๋ก ๋ฐ๋์ ๋ณต์ฌํด๋ฌ์ผ ํ๋ค.
- git push origin master ๋ก ์์ค ์ฝ๋๋ฅผ ๊นํ๋ธ์ ์
๋ก๋ํ๋ค.
- ์๋น์ค๋ฅผ ํด๋ผ์ฐ๋์ ๋ฐฐํฌํ๋ค.
- AWS ๊ณ์ ์ ์์ฑํ๊ณ ๊ฒฐ์ ์ ๋ณด๋ฅผ ๋ฑ๋กํ ํ ํ์ ๊ฐ์
์ ์๋ฃํ๋ค.
โป ์์ธํ ๋ฐฉ๋ฒ์ 713-718p๋ฅผ ์ฐธ๊ณ ํ๋ค.
- ๊ณ์ ์ ๋ง๋ ํ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
โป ์์ธํ ๋ฐฉ๋ฒ์ 719-721p๋ฅผ ์ฐธ๊ณ ํ๋ค.
โป ์ค์ต์ ๋ง์น๊ณ ๋๋ฉด, Delete ๋ฉ๋ด์์ ์ธ์คํด์ค๋ฅผ ์ญ์ ํด ์๊ธ์ด ๋ถ๊ณผ๋์ง ์๋๋ก ํด์ผํ๋ค.
->์ธ์คํด์ค ํ๋ฉด์์ Connect using SSH ๋ฒํผ์ ๋๋ฅธ๋ค.
->SSH๋ Lightsail ์ธ์คํด์ค์ ์ฐ๊ฒฐ๋์ด ์๋ค.
- MySQL์ ์ค์นํ๊ณ ๋น๋ฐ๋ฒํธ๋ฅผ ์ค์ ํ๋ค. (์ฑ
724-725p๋ฅผ ์ฐธ๊ณ ํ๋ค)
- MySQL ์ค์น๊ฐ ์๋ฃ๋ ํ, git clone ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํด ๊นํ๋ธ์ ์ฌ๋ ธ๋ ์์ค ์ฝ๋๋ฅผ ๋ด๋ ค ๋ฐ๋๋ค.
git clone https://github.com/์์ด๋/node-deploy
- ์๋ฒ๋ฅผ ์คํํ๊ธฐ ์ ์ Lightsail์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋นํธ๋๋ฏธ ์ํ์น ์๋ฒ๊ฐ ์ผ์ ธ์์ด ๊บผ์ฃผ์ด์ผ ํ๋ค.
sudo ./ctlscript.sh stop apache
โป ์๋ฒ๊ฐ ์คํ๋์ง ์๋๋ค๋ฉด sudo pm2 logs --err ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํด ์ด๋ค ์๋ฌ๊ฐ ๋ฐ์ํ๋์ง ํ์ธํ๋ค.
- ํผ๋ธ๋ฆญ IP๋ฅผ ํธ๊ฐ์ธํด ์ค์ ๋ก ์ ์ํด ๋ณธ๋ค. http://ํผ๋ธ๋ฆญIP
- GCP ์ฝ์ ์น ์ฌ์ดํธ์ ์ ์ํด ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๊ณ ๊ตฌ๊ธ ๊ณ์ ์ผ๋ก ๊ฒฐ์ ๊ณ์ ์ ๋ง๋ ๋ค.
- ์ธ์คํด์ค๋ฅผ ๋ง๋ ํ ์ธ๋ถ IP ์ SSH๋ฅผ ๋๋ฅด๊ณ ํด๋น ์ธ์คํด์ค์ ์ฝ์๋ก ์ ๊ทผํ๋ค.
โป ์ฑ
729-735p ๋ฅผ ์ฐธ๊ณ ํด ๊ณ์ ๊ณผ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
-SSH๊ฐ ๋ธ๋ผ์ฐ์ ์ ์ฐฝ์์ ์คํ๋๋ฉด SSH์ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ๋ค.
sudo su
->์ฐ๋ถํฌ์ MySQL ์ค์น๊ฐ ์๋ฃ๋ ํ, ๊นํ๋ธ์ ์ฌ๋ ธ๋ ์์ค ์ฝ๋๋ฅผ ๋ด๋ ค ๋ฐ๋๋ค.
->node-deploy ํด๋๋ก ์ด๋ํด npm ํจํค์ง๋ค์ ์ค์นํ๊ณ ์๋ฒ๋ฅผ ์คํํ๋ค.
->์๋ฒ๊ฐ ์คํ๋์์ผ๋ ์ค์ ๋ก ์ธ๋ถ IP๋ก ์ ์ํด NodeBird ํ๋ฉด์ด ๋ณด์ด๋ฉด ์ฑ๊ณต์ด๋ค.
โป ์๋ฒ๋ฅผ ์ฌ์์ ํ๊ธฐ ์ํด์ sudo npx pm2 reload all ์ ์
๋ ฅํ๋ค.
1. ( )๋ ๋ฐฐํฌ ํ๊ฒฝ์ธ์ง ๊ฐ๋ฐ ํ๊ฒฝ์ธ์ง๋ฅผ ํ๋จํ ์ ์๋ ํ๊ฒฝ ๋ณ์์ด๋ค.
2. ( ) ๋ชจ๋๋ dev ๋ชจ๋์ ๋นํด ๋ ๋ง์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ก๊ทธ๋ก ๋จ๊ธฐ๋ฏ๋ก ์ถํ ๋ฒ๊ทธ๋ฅผ ํด๊ฒฐํ ๋ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
3. ์ํ๋ผ์ด์ฆ์์ ๋น๋ฐ๋ฒํธ๊ฐ ํ๋ ์ฝ๋ฉ ๋์ด์๊ธฐ ๋๋ฌธ์ json์ ์ง์ฐ๊ณ ( )๋ฅผ ์์ฑํ๋ค.
4. ( )๋ ์ํํ ์๋ฒ ์ด์์ ์ํ ํจํค์ง์ด๋ค.
5. ์ค์ ์๋ฒ๋ฅผ ์ด์ํ ๋ console.log์ console.error๋ฅผ ๋์ฒดํ๊ธฐ ์ํ ๋ชจ๋์ ( )์ด๋ค.
6. ๊น์ผ๋ก๋ถํฐ ์
๋ก๋ํ ์์ค ์ฝ๋๋ฅผ ์๋ฒ์ ์ ์ฅํ ์ ์๋ ์๊ฒฉ ์ ์ฅ์๋ ( )์ด๋ค.
7. ์๋น์ค๋ฅผ ํด๋ผ์ฐ๋์ ๋ฐฐํฌํ๊ธฐ ์ํด ( )์ ( )๋ฅผ ์ด์ฉํ๋ค.
8. ๋ฏธ๋ค์จ์ด๋ค์ ๋ฐฐํฌ์ฉ์ผ๋ก ์ค์ ํ๊ธฐ ์ํด ๋น์นธ์ ๋ค์ด๊ฐ ์ฝ๋๋ฅผ ์์ฑํ์์ค.
//app.js
...
if ((1) === 'production') { --- ๋ฐฐํฌ ํ๊ฒฝ์ธ์ง ๊ฐ๋ฐ ํ๊ฒฝ์ธ์ง๋ฅผ ํ๋จํ ์ ์๋ ํ๊ฒฝ ๋ณ์
app.enable('trust proxy');
(2) --- ๋ฐฐํฌํ๊ฒฝ์ผ ๋ morgan์ combined๋ชจ๋๋ก ์ฌ์ฉํ๋ ์ฝ๋
} else {
app.use(morgan('dev'));
}
app.use(express.static(path.join(__dirname, 'public')));
...
9. XXS ๊ณต๊ฒฉ์ ๋ง๊ธฐ ์ํด HTML์ sanitize-html ํจํค์ง์ ๋์์ ๋ฐ์ ๋ง์์ผ ํ๋ค. ๋น์นธ์ ๋ค์ด๊ฐ ์ฝ๋๋ฅผ ์์ฑํ์์ค.
const sanitizeHtml=require('sanitize-html');
const html="<script>location.href='https://gilbut.co.kr'</script>";
(1) ---์ฌ์ฉ์๊ฐ ์
๋ก๋ํ HTML์ sanitize-thml ํจ์๋ก ๊ฐ์ผ๋ค.
1. process.env.NODE_EW
2. combined
3. js
4. pm2
5. winston
6. ๊นํ๋ธ(GitHub)
7. AWS, GCP
8.
//app.js
...
if (process.env.NODE_ENV === 'production') { --- (1)๋ฐฐํฌ ํ๊ฒฝ์ธ์ง ๊ฐ๋ฐ ํ๊ฒฝ์ธ์ง๋ฅผ ํ๋จํ ์ ์๋ ํ๊ฒฝ ๋ณ์
app.enable('trust proxy');
app.use(morgan('combined')); --- (2)๋ฐฐํฌ ํ๊ฒฝ์ผ ๋ morgan์ combined๋ชจ๋๋ก ์ฌ์ฉํ๋ ์ฝ๋
} else {
app.use(morgan('dev'));
}
app.use(express.static(path.join(__dirname, 'public')));
...
9.
const sanitizeHtml=require('sanitize-html');
const html="<script>location.href='https://gilbut.co.kr'</script>";
console.log(sanitizeHtml(html)); ---(1)
์ถ์ฒ) ์กฐํ์ , ใNode.js ๊ต๊ณผ์ ๊ฐ์ 3ํใ, ๊ธธ๋ฒ(2022), 10์ฅ
Corner node.js 2ํ
Editor : Igumi
[๋ ธ๋ 2ํ] #12. ์น ์์ผ์ผ๋ก ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์กํ๊ธฐ (0) | 2025.01.17 |
---|---|
[๋ ธ๋ 2ํ] #11. ์น API ์๋ฒ ๋ง๋ค๊ธฐ (1) | 2025.01.10 |
[๋ ธ๋ 2ํ] #10. ์ต์คํ๋ ์ค๋ก SNS ์๋น์ค ๋ง๋ค๊ธฐ (0) | 2025.01.03 |
[๋ ธ๋ 2ํ] #9. ๋ชฝ๊ณ ๋๋น (3) | 2024.12.27 |
[๋ ธ๋ 2ํ] #8. MySQL (3) | 2024.11.29 |