오늘은 11월 7일 7일차이다.
먼저 sequelize를 mysql과 연동하기 위해 모델들을 구성했다. 그다음 maker 모델과 url 모델을 1대1로, url 모델과 solver 모델을 1대N으로 연결해줬다.
API는 오늘은 일단 makerPage 부분만 진행했다. 첫 번째는 POST /make/duplicated로, 닉네임 중복 검증이다. db에서 해당 닉네임을 가지는 로우를 찾아낸다. 닉네임 중복 검증이 끝나고 단어를 입력하면 POST /make/register 요청을 보낸다.
const Sequelize = require('sequelize');
module.exports = class Maker extends Sequelize.Model {
static init(sequelize) {
return super.init({
nickname: {
type: Sequelize.STRING(20),
allowNull: false,
unique: true,
},
url: {
type: Sequelize.STRING(200),
allowNull: true,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
}, {
sequelize,
timestamps: false,
underscored: false,
modelName: 'Maker',
tableName: 'makers',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Maker.hasOne(db.Url, { foreignKey: 'maker', sourceKey: 'id' });
}
};
maker 모델이다. hasOne을 통해 url 모델과 1대1로 연결해줬다.
const Sequelize = require('sequelize');
module.exports = class Url extends Sequelize.Model {
static init(sequelize) {
return super.init({
url: {
type: Sequelize.STRING(200),
allowNull: false,
},
correct_word: {
type: Sequelize.STRING(10),
allowNull: false,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
}, {
sequelize,
timestamps: false,
underscored: false,
modelName: 'Url',
tableName: 'urls',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Url.belongsTo(db.Maker, { foreignKey: 'maker', targetKey: 'id' });
db.Url.hasMany(db.Solver, { foreignKey: 'url', sourceKey: 'id' });
}
};
url 모델이다. belongsTo를 통해 maker 모델과 묶어줬고, hasMany를 통해 solver 모델과 1대N 관계로 묶어줬다.
const Sequelize = require('sequelize');
module.exports = class Solver extends Sequelize.Model {
static init(sequelize) {
return super.init({
nickname: {
type: Sequelize.STRING(20),
allowNull: false,
},
word_list: {
type: Sequelize.STRING(200),
allowNull: true,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
}, {
sequelize,
timestamps: false,
underscored: false,
modelName: 'Solver',
tableName: 'solvers',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Solver.belongsTo(db.Url, { foreignKey: 'url', targetKey: 'id' });
}
};
solver 모델이다. belongsTo를 통해 url 모델과 묶어줬다.
const Sequelize = require('sequelize');
const Maker = require('./maker');
const Url = require('./url');
const Solver = require('./solver');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Maker = Maker;
db.Url = Url;
db.Solver = Solver;
Maker.init(sequelize);
Url.init(sequelize);
Solver.init(sequelize);
Maker.associate(db);
Url.associate(db);
Solver.associate(db);
module.exports = db;
models 폴더의 index.js 파일이다.
client.post('/make/duplicated', { nickname: nickname })
.then( res => {
if ( res.data === 'duplicated') {
nickname = '';
setMessage('It already exists!');
setWordState('not-word');
setTimeout(() => {setWordState(''); setMessage(null);}, 500);
return;
}
else {
submitNickname = true;
for( let i = 0 ; i < wordMaxLen ; i++ ) {
word[i].state = 'correct';
}
setWordList({
...wordList,
word,
});
setTimeout(() => {
setWord([]);
setWordList({
word,
});
setMessage('Enter your word!')
}, 2000);
}
});
POST /make/duplicated 요청 부분이다. 요청을 보내 중복이라는 응답을 받으면 message를 출력하며 애니메이션을 진행시킨다. 아니라면 애니메이션을 진행시키고, 단어를 입력하는 보드로 넘어간다.
client.post('/make/register', {
nickname: nickname,
correct_word: correct_word,
})
.then( res => {
console.log(res);
})
setTimeout(() => {
setMessage('Your Wordle was made!');
}, 2000);
// 만든 문제 링크 띄우기(모달 or 링크 복사 div)
POST /make/register 요청 부분이다. nickname과 correct_word를 담은 객체를 요청으로 보내고 서버에서 등록하도록 한다.
const express = require('express');
const axios = require('axios');
const { Maker, Url } = require('../models');
const router = express.Router();
router.post('/duplicated', async (req, res) => {
try {
const nickname = req.body.nickname;
const maker = await Maker.findOne({
where: {
nickname: nickname
}
});
if( maker == null )
res.send('not-duplicated');
else
res.send("duplicated");
} catch (error) {
console.error(error);
}
})
router.post('/register', async (req, res) => {
try {
const nickname = req.body.nickname;
const correct_word = req.body.correct_word;
console.log(nickname, correct_word);
const URL = 'http://localhost:3000/' + nickname + '/' + correct_word;
const maker = await Maker.create({
nickname: nickname,
url: URL,
});
const url = await Url.create({
url: URL,
correct_word: correct_word,
maker: maker.id,
});
res.send({
url: URL,
});
} catch (error) {
console.error(error);
}
});
module.exports = router;
서버의 make 라우터 부분이다. 중복 여부는 데이터베이스에서 해당 닉네임을 찾아검증한다. 등록은 URL을 생성한 후, maker 모델에 닉네임과 url을 등록, url 모델에 url과 correct_word를 등록하고, maker 칼럼에 방금 만든 maker 모델의 id를 등록한다. 이후 url을 응답으로 보낸다.
HARRY 라는 닉네임을 입력했다.
단어 입력 창으로 넘어가서 BEGIN 단어를 등록했다.
DB에 잘 등록되어 있는 모습이다.
오늘은 시간이 간만에 좀 나서 진행을 많이 한 것 같다. 모델간의 관계를 정의해서 db 구성하는 것은 처음인데, 많이 신기했고 재밌었다. 그래도 아직 sql에 관해서 쿼리도 잘 모르고, 그에 대응되는 sequelize 구문도 찾아보고 하는 수준이라 많이 부족한 것 같다. 더 노력해야지.