오늘은 11월 12일 12일차이다.
데이터베이스 구조를 갈아엎었다. 원래는 makers, urls, solvers로 나눠져있었는데, urls를 makers에 통합시키고, makers와 solvers 관계를 1대N으로 유지시켜주었다. 그리고 solvers 테이블에 key_state 칼럼을 추가하였다.
useEffect(() => { // 렌더링될 때
client.get(`/solve/${params.maker}`)
.then( res => {
if ( res.data === 'no-session')
setMessage('Enter your nickname!');
else {
setLineSet(sixLines);
setWordCorrect(res.data.wordCorrect);
keyState = res.data.keyState;
submitNickname = true;
setTimeout(() => { setWordList(res.data.wordList); }, 1);
}
})
}, [params]);
렌더링될 때 실행되는 부분이다. 서버로 GET /solve/:maker 요청을 보내서 세션 여부를 확인한다. 세션이 없다면 닉네임 입력창부터 시작하고, 있다면 6줄로 바꿔서 단어 입력창부터 시작한다. 이때 서버에서 보내준 wordCorrect, keyState, wordList를 활용해서 사용자가 입력했던 단어들을 렌더링해준다.
router.get('/:maker', async (req, res) => {
try {
console.log(req.session);
if ( req.session.solver === undefined || !req.session.solver[req.params.maker] ) {
res.send('no-session');
return;
}
const maker = await Maker.findOne({
attributes: ['correct_word'],
where: {
nickname: req.params.maker,
},
include: [{
model: Solver,
attributes: ['word_list', 'key_state'],
where: {
nickname: req.session.solver[req.params.maker],
}
}],
});
let word_list = maker.Solvers[0].word_list;
let key_state = maker.Solvers[0].key_state;
if ( word_list === undefined)
word_list = '[]';
if ( key_state === undefined )
key_state = '{}';
console.log("correct_word:", maker.correct_word, "word_list", word_list);
res.send({
wordCorrect: maker.correct_word,
wordList: JSON.parse(word_list),
keyState: JSON.parse(key_state),
});
} catch (error) {
console.error(error);
}
});
GET /solve/:maker 요청을 처리하는 라우터이다. 세션이 없다면 'no-session'응답을 보내고, 있다면 req.params에 담긴 정보로 maker 모델에서 correct_word를 찾아내고, 관계 쿼리를 사용하여 solver 모델에서 word_list와 key_state도 함께 가져와 클라이언트로 보내준다.
router.post('/:maker/register', async (req, res) => {
try {
const nickname = req.body.nickname;
console.log(nickname, req.params.maker);
const maker = await Maker.findOne({
attributes: ['correct_word'],
where: {
nickname: req.params.maker,
}
});
const solver = await Solver.create({
nickname: nickname,
maker: req.params.maker,
});
await maker.addSolver(solver);
if ( req.session.solver === undefined )
req.session.solver = {};
req.session.solver [req.params.maker]= nickname;
console.log('session saved', req.session.solver[req.params.maker]);
res.send({
wordCorrect: maker.correct_word
});
} catch (error) {
console.error(error);
}
});
POST /solve/:maker/register 요청을 처리하는 라우터이다. solver 닉네임이 요청과 함께 온다. 먼저 req.params 값을 활용하여 maker를 찾고, solver 닉네임과 maker 닉네임을 넣은 새로운 데이터를 만든다. 이후 maker 모델에 방금 만든 solver 모델을 추가해준다. 이후 응답으로 정답 단어를 보내준다.
router.post('/:maker/add', async (req, res) => {
// solver 테이블에 등록
const solver = await Solver.findOne({
attributes: ['word_list', 'key_state'],
where: {
nickname: req.session.solver[req.params.maker],
}
});
let word_list = JSON.parse(solver.word_list);
let key_state = JSON.parse(solver.key_state);
if ( word_list === null )
word_list = [];
word_list.push(req.body.newWord);
key_state = req.body.keyState;
word_list = JSON.stringify(word_list);
key_state = JSON.stringify(key_state);
await Solver.update({
word_list: word_list,
key_state: key_state,
}, {
where: {
nickname: req.session.solver[req.params.maker],
}
});
console.log(word_list, key_state);
res.end();
});
POST /solve/:maker/add 요청을 처리하는 라우터이다. 해당 요청은 단어를 입력할 때마다 서버에 등록하는 요청이다. 요청과 함께 방금 입력한 단어와 keyState가 들어온다. db에는 문자열로 저장되어 있기 때문에 JSON.parse를 통해 추가하기 좋은 형태로 바꿔준다. 이후 word_list에는 요청으로 들어온 단어를 추가하고, key_state는 요청으로 들어온 keyState로 교체해준다. 이것들은 js 배열과 객체이기 때문에 db에 저장하기 위해서는 JSON.stringify를 통해 문자열로 바꿔줘야 한다. 이후 update를 하고 응답을 보낸다.
오늘은 간만에 오랫동안 작업했다. 주말에 알바가 없는 주이기 때문이다. 생각보다 오래 걸렸고, 생각보다 복잡했다. 세션이 지금 key-value 형식으로, maker 닉네임-solver 닉네임 형식으로 되어있는데, 이렇게 하는 게 옳은 방식인지 모르겠다. 그래도 나름 고민해서 한 것이니 의미있다고 생각한다. 내일부터는 maker가 solver들이 입력한 단어들을 볼 수 있는 LoadPage를 진행할 것이다. 이전의 MakerPage와 SolverPage는 wordle에서 디자인을 많이 따왔는데, LoadPage는 스스로 디자인하고 구성해야되는 것이라 시간이 좀 걸릴 것 같지만 열심히 할 것이다.