웹 API Project 1

도메인 등록

Posted by ETHAN KIM on December 10, 2021 · 9 mins read
Node.js

웹 API 서버 구조설명

SNS 프로젝트 서버와 DB를 공유하여 클라이언트에게 SNS 정보 제공

  1. 기존의 SNS서비스와 계정 공유
  2. user 테이블과 one-to-many 관계를 가지는 domain 테이블 생성
  3. uuid를 통한 비밀키 생성 로직 구현


app.js

기존 main 함수와 동일하나 8001번과 겹치지 않도록 8002번 포트로 설정.

const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const morgan = require('morgan');
const session = require('express-session');
const nunjucks = require('nunjucks');
const dotenv = require('dotenv');

dotenv.config();
const authRouter = require('./routes/auth');
const indexRouter = require('./routes');
const  { sequelize } = require('./models');
const passportConfig = require('./passport');

const app = express();
passportConfig();
app.set('port', process.env.PORT || 8002);
app.set('view engine', 'html');
nunjucks.configure('views', {
    express : app,
    watch: true,
});
sequelize.sync({ force: false })
    .then(() => {
        console.log('데이터베이스 연결 성공');
    })
    .catch((err) => {
        console.error(err);
    });

app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
    resave:false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
        httpOnly: true,
        secure: false,
    },
}));

app.use(passport.initialize());
app.use(passport.session());

app.use('/auth', authRouter);
app.use('/', indexRouter);

app.use((req, res, next) => {
    const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
    error.status = 404;
    next(error);
});

app.use((err, req, res, next) => {
    res.locals.message = err.message;
    res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
    res.status(err.status ||500);
    res.render('error');
});

app.listen(app.get('port'), () => {
    console.log(app.get('port'),'번 포트에서 대기 중');
});


./models/domain.js

도메인 테이블 모델 정의.

  • UUID 타입의 컬럼을 지정하여 시크릿 키로 활용
  • user 테이블에도 associate 함수를 통해 관계 정의 필요
const Sequelize = require('sequelize');

module.exports = class Domain extends Sequelize.Model {
    static init (sequelize) {
        return super.init({
            host : {
                type : Sequelize.STRING(80),
                allowNull : false,
            },
            type : {
                type : Sequelize.ENUM('free', 'premium'),
                allowNull : false,
            },
            clientSecret : {
                type : Sequelize.UUID,
                allowNull : false,
            },
        },{
            sequelize,
            timestamps : true,
            paranoid : true,
            modelName : 'Domain',
            tableName : 'domains',
        });
    }

    static associate(db){
        db.Domain.belongsTo(db.User);
    }
}


./routes/index.js

기존 계정정보로 로그인하여 도메인 등록 시 도메인 테이블에 정보 저장 및 출력 (redirect)

  • secret key 컬럼은 uuid 모듈을 활용하여 겹치지 않는 36자리 문자열 형식 생성
const express = require('express');
const { v4 : uuidv4 } =require('uuid');
const { User, Domain } = require('../models');
const { isLoggedIn } = require('./middlewares');

const router = express.Router();

router.get('/', async(req, res, next) => {
    try {
        const user = await User.findOne({
            where: { id:req.user && req.user.id || null },
            include: { model: Domain },
        });          
        res.render('login', {
            user,
            domains: user && user.Domains,
        });
    }catch(err){
        console.error(err);
        next(err);
    }
});

router.post('/domain', isLoggedIn, async(req,res,next) => {
    try{
        await Domain.create({
            UserId: req.user.id,
            host: req.body.host,
            type: req.body.type,
            clientSecret: uuidv4(),
        });
        res.redirect('/');
    }catch(err){
        console.error(err);
        next(err);
    }
});

module.exports = router;



로그인 화면 및 도메인 등록 테스트


1. 로그인 화면


2. 사용자 정보 및 도메인 등록 화면


3. 도메인 등록 결과 출력 화면