๐ ์ ๊ทํ
- DB ์ค๊ณ์ ์์ด์ ์ค๋ณต์ ์ต์ํ ํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์กฐํ ํ๋ ๊ณผ์
- ํฌ๊ณ ์กฐ์งํ ๋์ง ์์ ํ ์ด๋ธ์ ์๊ณ ์ ์กฐ์งํ ๋ ํ ์ด๋ธ๋ก ๋ณ๊ฒฝ
- ๋ฐ์ดํฐ ์ถ๊ฐ ๋ฐ ์ญ์ ์์ ์ด์ ํ์์ ์๋ฐฉํ ์ ์์
๐ฉ ์ 1์ ๊ทํ(1NF): ํ๋์ ์ปฌ๋ผ์ ๋ฐ๋์ ํ๋์ ์์ฑ๋ง์ ๊ฐ์ ธ์ผ ํจ
๐ฉ ์ 2์ ๊ทํ(2NF): ๋ชจ๋ ์ปฌ๋ผ์ ๋ํ ๋ถ๋ถ ์ข ์์ด ์์ด์ผ ํจ
๐ฉ ์ 3์ ๊ทํ(3NF): ์ดํ ์ข ์์ฑ(A=B, B=C์ฌ์ A=C์ธ ๊ฒฝ์ฐ)์ด ์์ด์ผ ํจ
๐ Foreign Key(์ธ๋ ํค)
- ์ ๊ทํ๋ฅผ ํ๊ฒ ๋๋ฉด ํ ์ด๋ธ์ ์ต์ํ์ ๋จ์๋ก ์ชผ๊ฐ์ง๊ฒ ๋จ
- ํ์ง๋ง ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ๋ค์ผ ๋์๋ ํ๊บผ๋ฒ์ ๋ง์ ๊ฐ์ ๊ฐ์ง๋ ํ ์ด๋ธ์ JOIN ํด์ ๊ฐ์ง๊ณ ์์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์
- JOIN์ ํตํด ํ ์ด๋ธ์ ํฉ์น๋๋ฐ, ์ด ๋ ๊ธฐ์ค์ด ๋๋ ๊ฐ(์๋ก ๊ณต์ ํ๊ณ ์๋ ๊ฐ)์ ์ธ๋ ํค๋ผ๊ณ ํจ
๐ InitialData ํ ์ด๋ธ ๊ตฌ์ฑ
- Question Table: ID_PK, QUESTION_TEXT
- Answer Table: ID_PK, ANSWER_TEXT, RESULT, QUESTION_ID_FK
- Explanation Table: ID_PK, MBTI_TYPE, EXPLANATION, IMG_SRC
๐ฉ Question Table ์์ฑ
๐ฉ Answer Table ์์ฑ
* cascade: ์ธ๋ํค๊ฐ ์ ๋ฐ์ดํธ ๋์์ ๋ ๋ฐ๋ผ๊ฐ๋ ๊ฒ
๐ฉ Explanation Table ์์ฑ
๐ฉ Question Table ๋ฐ์ดํฐ ์ฝ์
insert into MyDB.question (ID_PK, QUESTION_TEXT) values
(0, 'ํด๊ทผ ์ง์ ์ ๋๋ฃ๋ก๋ถํฐ ๊ฐ๋ฐ์ ๋ชจ์์ ์ด๋๋ฅผ ๋ฐ์ ๋!!\n\nํด๊ทผ ์๊ฐ์ ๋๋?'),
(1, '์๋ก์ด ์๋น์ค ๊ฐ๋ฐ ์ค์, ๋๋ฃ๊ฐ ์๋ก ๋์จ ์ ๊ธฐ์ ์ ์ฐ๋๊ฒ ๋ ํธํ ๊ฑฐ๋ผ๊ณ ์ถ์ฒ์ ํด์ค๋ค!\n\n๋์ ์ ํ์!?'),
(2, '์๋น์ค ์ถ์ ์ดํ ์ ์ผ๊ทผ ์๊ฐ, ๊ฐ์๊ธฐ ๋๋ฃ๊ฐ ์ด!?๋ฅผ ์ธ์ณค๋ค!\n\n๋์ ์ ํ์?'),
(3, 'ํ์ฅ๋์ด xx ์จ ๊ทธ์ ์ ๋งํ ๊ธฐ๋ฅ ๋ด์ผ ์คํ๊น์ง ์๋ฃ ๋ถํํด์๋ผ๊ณ ๋งํ๋ค!\n\n๋์ ์ ํ์?');
๐ฉ Answer Table ๋ฐ์ดํฐ ์ฝ์
insert into MyDB.answer (ANSWER_TEXT, RESULT, QUESTION_ID_FK) values
('๊ทธ๋ฐ ๋ชจ์
์ ์ ์ด์ ์์ผ ์๋ ค ์ค๊ฑฐ์ผ! ๋น์ฅ ๋ชจ์์ผ๋ก ์ถ๋ฐํ๋ค', 'E', 0),
('1๋
์ ์ ์๋ ค์คฌ์ด๋ ์๊ฐ์ ๊ฑด๋ฐ ๋ญ... ๋ ๋น ๋ฅด๊ฒ ์ง์ผ๋ก ๊ฐ๋ค', 'I', 0),
('๋ญ์๋ฆฌ์ฌ, ๊ทธ๋ฅ ํ๋ ๋๋ก ๊ฐ๋ฐํ๋ฉด ๋๋๊ฑฐ์ง! ๊ธฐ์กด ์๊ฐ๋๋ก ๊ฐ๋ฐํ๋ค', 'S', 1),
('์คํธ? ๊ทธ๋ฐ๊ฒ ์์ด? ์ผ๋จ ๊ตฌ๊ธ์ ์ฐพ์๋ณธ๋ค', 'N', 1),
('๋ฌด์จ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ๊ฑฐ์ง? ์๋ง DB ๊ด๋ จ ๋ฒ๊ทธ๊ฐ ์๋๊น? ๋น ๋ฅด๊ฒ ๋๋ฃ์ ์๋ฆฌ๋ก ๋ฌ๋ ค๊ฐ๋ค', 'T', 2),
('์... ๋ด์ผ๋ ์ผ๊ทผ ๊ฐ์ด๊ตฌ๋ ใ
ใ
! ์ผ๋จ ๋๋ฃ์ ์๋ฆฌ๋ก ๊ฐ ๋ณธ๋ค', 'F', 2),
('์ผ๋จ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐ ์๋ฃํ๊ณ , ๋๋จธ์ง ์๊ฐ์ ๋
ผ๋ค', 'J', 3),
('๊ทธ๊ฑฐ ๋ด์ผ ์์นจ์ ์์ ๊ฐ๋ฐํด๋ ์ถฉ๋ถ ํ๊ฒ ๋๋ฐ? ์ผ๋จ ๋
ผ๋ค', 'P', 3);
๐ฉ Explanation Table ๋ฐ์ดํฐ ์ฝ์
insert into MyDB.explanation (MBTI_TYPE, EXPLANATION, IMG_SRC) values
('ESTJ', '๋ฌด๋ฆฌํ ๊ฐ๋ฐ ์ผ์ ๋ง ์๋๋ผ๋ฉด ์ผ์ ์ ์ฒ ์ ํ๊ฒ ์งํฌ ๋น์ ์ MBTI ๋!', '/images/estj.jpg'),
('ISTJ', '์ค์ค๋ก ํ๊ณ ์ถ์ ๋ถ์ผ๋ฅผ ๋๊น์ง ํ๊ณ ๋ค์ด์ ๋๋ด ์ฑ๊ณต ์ํฌ ๋น์ ์ MBTI ๋!', '/images/istj.jpg'),
('ENTJ', '๋ฏธ๋์ ๋ฅ๋ ฅ ์ฉ๋ ๊ฐ๋ฐ ํ์ฅ๋์ผ๋ก ๊ฐ๋ฐํ์ ์ด๋ ๋น์ ์ MBTI ๋!', '/images/entj.jpg'),
('INTJ', 'ํผ์์ ๋ชจ๋ ๊ฒ์ ๋ค ํด๋ด๋ ์๋งจ ์บ๋ฆฌ์ ํ๋ณธ! ๋น์ ์ MBTI ๋!', '/images/intj.jpg'),
('ESFJ', '๊ฐ๋ฐํ์ ๋ถ์๊ธฐ ๋ฉ์ด์ปค์ด์ ์์ด๋์ด ๋ฑ
ํฌ๊ฐ ๋ ๋น์ ์ MBTI ๋!', '/images/esfj.jpg'),
('ISFJ', '๊ฐ๋ฐํ์ ๋ง๋ ํ
๋ ์ฌ, ๊ณ ๋ฏผ ์๋ด์ ์ญํ ์ ์์ฒํ๋ ๋น์ ์ MBTI ๋!', '/images/isfj.jpg'),
('ENFJ', '๋น์ ์ด ์๋ ํ์ ์ธ์ ๋ ์ฌ๋ฐ๋ฅธ ๊ณณ์ ํฅํ๊ณ ์์ต๋๋ค! ํ์์ ๋ฌผ๋ก ํ์ ๋ฐฉํฅ์ ์ฑ๊ธฐ๋ ๋น์ ์ MBTI ๋!', '/images/enfj.jpg'),
('INFJ', '์๋ฆฌํ ํต์ฐฐ๋ ฅ์ผ๋ก ๋ชจ๋ ๊ฒ์ ๋ด๋ค๋ณด๋ฉด์ ์๋ฒฝํ๊ฒ ๊ฐ๋ฐ์ ํ ๋น์ ์ MBTI ๋!', '/images/infj.jpg'),
('ESTP', '์ฟจํ๊ฒ ์์ ์ด ํ ๊ฒ์ ํ๋ฉด์ ๋
ผ๋ฆฌ์ ์ธ ๊ฐ๋ฐ์ ํ ๋น์ ์ MBTI ๋!', '/images/estp.jpg'),
('ISTP', '๋จ์๊ฐ์๋ ํจ์จ์ ์ผ๋ก ๊ฐ๋ฐํ์ฌ ๋ชจ๋ ๊ฒ์ ์์ฑํ ๋น์ ์ MBTI ๋!', '/images/istp.jpg'),
('ENTP', '์ค์ค๋ก ํฅ๋ฏธ๋ง ์๊ธด๋ค๋ฉด ๋น์ฅ์ ํ์ด์ค๋ถ๋ ๋ง๋ค์ด ๋ฒ๋ฆด ๋น์ ์ MBTI ๋!', '/images/entp.jpg'),
('INTP', 'ํ์คํ ์ฃผ๊ด๊ณผ ๋ฐ์ด๋ ์ง๋ฅ์ ๋ฐํ์ผ๋ก ๋
ผ๋ฆฌ์ ๊ฐ๋ฐ์ ํ ๋น์ ์ MBTI ๋!', '/images/intp.jpg'),
('ESFP', '๊ฐ๋ฐํ์ ์๋์์ด์ ! ๊ฐ๋ฐํ ํน์ ์ ์๋จนํจ์ ๊นจ๋ ๋น์ ! ๋น์ ์ MBTI ๋!', '/images/esfp.jpg'),
('ISFP', '๋ฐ์ด๋ ํธ๊ธฐ์ฌ๊ณผ ์์ ์ ๊ฐ๊ฐ์ผ๋ก ๊ฐ๋ฐํ์ ๋ถ์กฑํจ์ ์ฑ์๊ฐ ๋น์ ! ๋น์ ์ MBTI ๋!', '/images/isfp.jpg'),
('ENFP', '์์ ๋ก์ด ์ํผ์ผ๋ก ๊ฐ๋ฐํ์ ์คํ์ ๋ฐ ํ๋ ฅ์๊ฐ ๋์ด์ค ๋น์ ์ MBTI ๋!', '/images/enfp.jpg'),
('INFP', '๊ฐ๋ฐํ์ ๊ทธ ์ด๋ค ํธ๋ฌ๋ธ๋ ๋น์ ์์์๋ ์ฌ๋ฅด๋ฅด ๋
น์๋ฟ, ํ์ ๊ทผ๊ฐ์ ๋ค์ ธ์ฃผ๋ ๋น์ ์ MBTI ๋!', '/images/infp.jpg');
๐ Redux InitialData๋ฅผ SQL DB๋ก๋ถํฐ ๋ฐ๊ธฐ
๐ฉ survey, explanation ์ปจํธ๋กค๋ฌ ์ถ๊ฐ
- ํ์ฌ MySQL์ ๋ฐ์ดํฐ๋ ์ ๊ทํ๋ฅผ ์ํด์ ํ ์ด๋ธ์ด ๋ถ๋ฆฌ๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ Question Table๊ณผ Answer Table์ ๋์์ ๊ฐ์ง๊ณ ์์ผ ํจ
- ๊ธฐ์กด controller ๋ชจ๋์ getSurvey, getExplanation ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๊ณ , JOIN์ผ๋ก ํฉ์น ๋ฐ์ดํฐ์ ๊ฐ ์ ๋ฌ
// data-server/controllers/dataController.js
getSurvey: (cb) => {
connection.query(
'SELECT * FROM MyDB.question q LEFT JOIN MyDB.answer a ON q.ID_PK=a.QUESTION_ID_FK',
(err, data) => {
if(err) throw err;
cb(data);
}
);
},
getExplanation: (cb) => {
connection.query('SELECT * FROM MyDB.explanation', (err, data) => {
if (err) throw err;
cb(data);
});
},
๐ฉ survey, explanation router ์ค์
// data-server/routes/data.js
router.get('/survey', (req, res) => {
db.getSurvey((data) => {
console(data);
res.send(data);
});
});
router.get('/explanation', (req, res) => {
db.getExplanation((data) => {
console.log(data);
res.send(data);
});
});
๐ฉ React์์ ๋ฐ์ดํฐ ๋ฐ๊ธฐ
// src/components/Start.js
useEffect(() => {
async function fetchData() {
const resCount = await fetch('http://localhost:4000/data/count');
if (resCount.status === 200) {
const num = await resCount.json();
if (num[0].counts !== 0) setCounts(num[0].counts);
} else throw new Error('ํต์ ์ด์');
//survey ๊ฐ์ ์ํ JOIN Table์ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
const resSurvey = await fetch('http://localhost:4000/data/survey');
if (resSurvey.status === 200) {
const surveyData = await resSurvey.json();
// explanation table์ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
const resExplanation = await fetch('http://localhost:4000/data/explanation');
if(resExplanation.status === 200) {
const explanationData = await resExplanation.json();
console.log(explanationData);
} else throw new Error('ํต์ ์ด์');
} else throw new Error('ํต์ ์ด์');
}
fetchData();
}, [counts]);
๐ฉ ๋ฐ์์จ ๋ฐ์ดํฐ ๊พธ๋ฏธ๊ธฐ
- DB์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ redux์์ ์ธํ ํ๋ initialState์ ๊ตฌ์กฐ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๊ฐ๊ณต์ด ํ์ํจ
// src/components/Start.js
function makeData(survey, explanation) {
const initData = { survey: [], explanation: {} };
if(initData.survey.length === 0) {
for(let i = 0; i < survey.length; i = i + 2) {
initData.survey.push({
question: survey[i].QUESTION_TEXT,
answer: [
{
text: survey[i].ANSWER_TEXT,
result: survey[i].RESULT,
},
{
text: survey[i + 1].ANSWER_TEXT,
result: survey[i + 1].RESULT,
},
],
});
}
for(let i = 0; i< explanation.length; i++) {
initData.explanation[explanation[i].MBTI_TYPE] = {
explanation: explanation[i].EXPLANATION,
img: explanation[i].IMG_SRC,
};
}
}
return initData;
}
๐ฉ redux ์์ ํ๊ธฐ
- ๊ฐ๊ณตํ ๋ฐ์ดํฐ๋ฅผ redux์ ์ ๋ฌํ์ฌ ์ด๊ธฐ ๊ฐ์ผ๋ก ๋ง๋ค๊ธฐ
- ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐํ ํ๋ ์์ ๋ ํ๋์ action์ด๋ฏ๋ก redux์ action type ์ค์ , ์์ฑ ํจ์ ๋ง๋ค๊ธฐ, reducer ์์ ํ๊ธฐ
// src/store/modules/mbti.js
// ๋ฆฌ์กํธ ์ฑ ์ต์ด ์คํ ์ reducer์ ์ ๋ฌํ ๋น ์ด๊ธฐ ๊ฐ
const initStateEmpty = {
mbtiResult: '',
page: 0,
survey: [],
explanation: {},
}
// ์ก์
ํ์
(๋ฌธ์์ด)
const INIT = 'mbti/INIT';
const CHECK = 'mbti/CHECK';
const NEXT = 'mbti/NEXT';
const RESET = 'mbti/RESET';
// ์ก์
์์ฑ ํจ์
export function init(data) {
return {
type: INIT,
payload: data,
}
}
// ...
// reducer
export default function mbti(state = initStateEmpty, action) {
switch (action.type) {
case INIT:
return {
...state,
survey: action.payload.survey,
explanation: action.payload.explanation,
};
// ...
๐ฉ ๋ง๋ค์ด์ง ๋ฐ์ดํฐ ์ ๋ฌํ๊ธฐ
- dispatch๋ฅผ ํตํด init() ํจ์์ ๋ด์์ ์ ๋ฌ
// src/components/Start.js
useEffect(() => {
async function fetchData() {
const resCount = await fetch('http://localhost:4000/data/count');
if (resCount.status === 200) {
const num = await resCount.json();
if (num[0].counts !== 0) setCounts(num[0].counts);
} else throw new Error('ํต์ ์ด์');
//survey ๊ฐ์ ์ํ JOIN Table์ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
const resSurvey = await fetch('http://localhost:4000/data/survey');
if (resSurvey.status === 200) {
const surveyData = await resSurvey.json();
// explanation table์ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
const resExplanation = await fetch(
'http://localhost:4000/data/explanation'
);
if (resExplanation.status === 200) {
const explanationData = await resExplanation.json();
const madeData = makeData(surveyData, explanationData);
dispatch(init(madeData));
} else throw new Error('ํต์ ์ด์');
} else throw new Error('ํต์ ์ด์');
}
fetchData();
}, [counts]);
๐ MongoDB๋ก ๊ตฌํํ๊ธฐ
๐ฉ MongoDB ๋ชจ๋ ์ค์น ๋ฐ ์ธํ
- [ํฐ๋ฏธ๋] npm i mongodb
// data-server/mongoConnect.js
const { MongoClient, ServerApiVersion } = require('mongodb');
const uri = process.env.MDB_URI;
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
serverApi: ServerApiVersion.v1,
});
module.exports = client;
๐ฉ MongoDB controller ์์ฑ
- ์ค๋ฌธ์ฉ ๋ฐ์ดํฐ๋ฅผ DB์ ์ ์ฅ์์ผ์ฃผ๋ controller๋ถํฐ ์์ฑ
// data-server/controllers/mongoController.js
const mongoClient = require('../mongoConnect');
const _client = mongoClient.connect();
const initState = {
mbtiResult: '',
page: 0, // 0: ์ธํธ๋ก ํ์ด์ง, 1 ~ n: ์ ํ ํ์ด์ง, n+1: ๊ฒฐ๊ณผ ํ์ด์ง
survey: [
{
question:
'ํด๊ทผ ์ง์ ์ ๋๋ฃ๋ก๋ถํฐ ๊ฐ๋ฐ์ ๋ชจ์์ ์ด๋๋ฅผ ๋ฐ์ ๋!!\n\nํด๊ทผ ์๊ฐ์ ๋๋?',
answer: [
{
text: '๊ทธ๋ฐ ๋ชจ์์ ์ ์ด์ ์์ผ ์๋ ค ์ค๊ฑฐ์ผ! ๋น์ฅ ๋ชจ์์ผ๋ก ์ถ๋ฐํ๋ค',
result: 'E',
},
{
text: '1๋
์ ์ ์๋ ค์คฌ์ด๋ ์๊ฐ์ ๊ฑด๋ฐ ๋ญ... ๋ ๋น ๋ฅด๊ฒ ์ง์ผ๋ก ๊ฐ๋ค',
result: 'I',
},
],
},
{
question:
'์๋ก์ด ์๋น์ค ๊ฐ๋ฐ ์ค์, ๋๋ฃ๊ฐ ์๋ก ๋์จ ์ ๊ธฐ์ ์ ์ฐ๋๊ฒ ๋ ํธํ ๊ฑฐ๋ผ๊ณ ์ถ์ฒ์ ํด์ค๋ค!\n\n๋์ ์ ํ์!?',
answer: [
{
text: '๋ญ์๋ฆฌ์ฌ, ๊ทธ๋ฅ ํ๋ ๋๋ก ๊ฐ๋ฐํ๋ฉด ๋๋๊ฑฐ์ง! ๊ธฐ์กด ์๊ฐ๋๋ก ๊ฐ๋ฐํ๋ค',
result: 'S',
},
{
text: '์คํธ? ๊ทธ๋ฐ๊ฒ ์์ด? ์ผ๋จ ๊ตฌ๊ธ์ ์ฐพ์๋ณธ๋ค',
result: 'N',
},
],
},
{
question:
'์๋น์ค ์ถ์ ์ดํ ์ ์ผ๊ทผ ์๊ฐ, ๊ฐ์๊ธฐ ๋๋ฃ๊ฐ ์ด!?๋ฅผ ์ธ์ณค๋ค!\n\n๋์ ์ ํ์?',
answer: [
{
text: '๋ฌด์จ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ๊ฑฐ์ง? ์๋ง DB ๊ด๋ จ ๋ฒ๊ทธ๊ฐ ์๋๊น? ๋น ๋ฅด๊ฒ ๋๋ฃ์ ์๋ฆฌ๋ก ๋ฌ๋ ค๊ฐ๋ค',
result: 'T',
},
{
text: '์... ๋ด์ผ๋ ์ผ๊ทผ ๊ฐ์ด๊ตฌ๋ ใ
ใ
! ์ผ๋จ ๋๋ฃ์ ์๋ฆฌ๋ก ๊ฐ ๋ณธ๋ค',
result: 'F',
},
],
},
{
question:
'ํ์ฅ๋์ด xx ์จ ๊ทธ์ ์ ๋งํ ๊ธฐ๋ฅ ๋ด์ผ ์คํ๊น์ง ์๋ฃ ๋ถํํด์๋ผ๊ณ ๋งํ๋ค!\n\n๋์ ์ ํ์?',
answer: [
{
text: '์ผ๋จ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐ ์๋ฃํ๊ณ , ๋๋จธ์ง ์๊ฐ์ ๋
ผ๋ค',
result: 'J',
},
{
text: '๊ทธ๊ฑฐ ๋ด์ผ ์์นจ์ ์์ ๊ฐ๋ฐํด๋ ์ถฉ๋ถ ํ๊ฒ ๋๋ฐ? ์ผ๋จ ๋
ผ๋ค',
result: 'P',
},
],
},
],
explanation: {
ESTJ: {
text: '๋ฌด๋ฆฌํ ๊ฐ๋ฐ ์ผ์ ๋ง ์๋๋ผ๋ฉด ์ผ์ ์ ์ฒ ์ ํ๊ฒ ์งํฌ ๋น์ ์ MBTI๋!',
img: '/images/estj.jpg',
},
ISTJ: {
text: '์ค์ค๋ก ํ๊ณ ์ถ์ ๋ถ์ผ๋ฅผ ๋๊น์ง ํ๊ณ ๋ค์ด์ ๋๋ด ์ฑ๊ณต ์ํฌ ๋น์ ์ MBTI ๋!',
img: '/images/istj.jpg',
},
ENTJ: {
text: '๋ฏธ๋์ ๋ฅ๋ ฅ ์ฉ๋ ๊ฐ๋ฐ ํ์ฅ๋์ผ๋ก ๊ฐ๋ฐํ์ ์ด๋ ๋น์ ์ MBTI ๋!',
img: '/images/entj.jpg',
},
INTJ: {
text: 'ํผ์์ ๋ชจ๋ ๊ฒ์ ๋ค ํด๋ด๋ ์๋งจ ์บ๋ฆฌ์ ํ๋ณธ! ๋น์ ์ MBTI ๋!',
img: '/images/intj.jpg',
},
ESFJ: {
text: '๊ฐ๋ฐํ์ ๋ถ์๊ธฐ ๋ฉ์ด์ปค์ด์ ์์ด๋์ด ๋ฑ
ํฌ๊ฐ ๋ ๋น์ ์ MBTI๋!',
img: '/images/esfj.jpg',
},
ISFJ: {
text: '๊ฐ๋ฐํ์ ๋ง๋ ํ
๋ ์ฌ, ๊ณ ๋ฏผ ์๋ด์ ์ญํ ์ ์์ฒํ๋ ๋น์ ์ MBTI๋!',
img: '/images/isfj.jpg',
},
ENFJ: {
text: '๋น์ ์ด ์๋ ํ์ ์ธ์ ๋ ์ฌ๋ฐ๋ฅธ ๊ณณ์ ํฅํ๊ณ ์์ต๋๋ค! ํ์์ ๋ฌผ๋ก ํ์ ๋ฐฉํฅ์ ์ฑ๊ธฐ๋ ๋น์ ์ MBTI๋!',
img: '/images/enfj.jpg',
},
INFJ: {
text: '์๋ฆฌํ ํต์ฐฐ๋ ฅ์ผ๋ก ๋ชจ๋ ๊ฒ์ ๋ด๋ค๋ณด๋ฉด์ ์๋ฒฝํ๊ฒ ๊ฐ๋ฐ์ ํ ๋น์ ์ MBTI๋!',
img: '/images/infj.jpg',
},
ESTP: {
text: '์ฟจํ๊ฒ ์์ ์ด ํ ๊ฒ์ ํ๋ฉด์ ๋
ผ๋ฆฌ์ ์ธ ๊ฐ๋ฐ์ ํ ๋น์ ์ MBTI๋!',
img: '/images/estp.jpg',
},
ISTP: {
text: '๋จ์๊ฐ์๋ ํจ์จ์ ์ผ๋ก ๊ฐ๋ฐํ์ฌ ๋ชจ๋ ๊ฒ์ ์์ฑํ ๋น์ ์ MBTI๋!',
img: '/images/istp.jpg',
},
ENTP: {
text: '์ค์ค๋ก ํฅ๋ฏธ๋ง ์๊ธด๋ค๋ฉด ๋น์ฅ์ ํ์ด์ค๋ถ๋ ๋ง๋ค์ด ๋ฒ๋ฆด ๋น์ ์ MBTI๋!',
img: '/images/entp.jpg',
},
INTP: {
text: 'ํ์คํ ์ฃผ๊ด๊ณผ ๋ฐ์ด๋ ์ง๋ฅ์ ๋ฐํ์ผ๋ก ๋
ผ๋ฆฌ์ ๊ฐ๋ฐ์ ํ ๋น์ ์ MBTI๋!',
img: '/images/intp.jpg',
},
ESFP: {
text: '๊ฐ๋ฐํ์ ์๋์์ด์ ! ๊ฐ๋ฐํ ํน์ ์ ์๋จนํจ์ ๊นจ๋ ๋น์ ! ๋น์ ์ MBTI๋!',
img: '/images/esfp.jpg',
},
ISFP: {
text: '๋ฐ์ด๋ ํธ๊ธฐ์ฌ๊ณผ ์์ ์ ๊ฐ๊ฐ์ผ๋ก ๊ฐ๋ฐํ์ ๋ถ์กฑํจ์ ์ฑ์๊ฐ ๋น์ ! ๋น์ ์ MBTI๋!',
img: '/images/isfp.jpg',
},
ENFP: {
text: '์์ ๋ก์ด ์ํผ์ผ๋ก ๊ฐ๋ฐํ์ ์คํ์ ๋ฐ ํ๋ ฅ์๊ฐ ๋์ด์ค ๋น์ ์ MBTI๋!',
img: '/images/enfp.jpg',
},
INFP: {
text: '๊ฐ๋ฐํ์ ๊ทธ ์ด๋ค ํธ๋ฌ๋ธ๋ ๋น์ ์์์๋ ์ฌ๋ฅด๋ฅด ๋
น์๋ฟ, ํ์ ๊ทผ๊ฐ์ ๋ค์ ธ์ฃผ๋ ๋น์ ์ MBTI๋!',
img: '/images/infp.jpg',
},
},
};
const mongoDB = {
setData: async () => {
const client = await _client;
const db = client.db('MBTI').collection('data');
const result = await db.insertOne(initState);
if (result.acknowledged) {
return '์
๋ฐ์ดํธ ์ฑ๊ณต';
} else throw new Error('ํต์ ์ด์');
},
};
module.exports = mongoDB;
๐ฉ MongoDB ์ฉ ๋ผ์ฐํฐ ์ค์
// data-server/routes/mongo.js
const express = require('express');
const router = express.Router();
const mongoDB = require('../controllers/mongoController');
router.post('/setdata', async (req, res) => {
const msg = await mongoDB.setData();
res.send(JSON.stringify(msg));
});
module.exports = router;
// data-server/server.js
const express = require('express');
const cors = require('cors');
const PORT = 4000;
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());
require('dotenv').config();
const dataRouter = require('./routes/data');
const mongoRouter = require('./routes/mongo');
app.use('/data', dataRouter);
app.use('/mongo', mongoRouter);
app.listen(PORT, () => {
console.log(`๋ฐ์ดํฐ ํต์ ์๋ฒ๊ฐ ${PORT}์์ ์๋ ์ค`);
});
๐ฉ ์ปจํธ๋กค๋ฌ ๊ธฐ๋ฅ ์ถ๊ฐ
- ๋ฐฉ๋ฌธ์ ์๋ฅผ ๊ฐ์ ธ์ค๋ getCounts
- ๋ฐฉ๋ฌธ์ ์๋ฅผ ์ฆ๊ฐ์ํค๋ incCounts
- ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ getData
// data-server/controllers/mongoController.js
getCounts: async () => {
const client = await _client;
const db = client.db('MBTI').collection('counts');
const data = await db.find({}).toArray();
return data;
},
incCounts: async () => {
const client = await _client;
const db = client.db('MBTI').collection('counts');
const result = await db.updateOne({ id: 1 }, { $inc: { counts: 1 } });
if (result.acknowledged) {
return '์
๋ฐ์ดํธ ์ฑ๊ณต';
} else throw new Error('ํต์ ์ด์');
},
getData: async () => {
const client = await _client;
const db = client.db('MBTI').collection('data');
const data = await db.find({}).toArray();
return data;
},
๐ฉ mongoRouter ์ค์
// data-server/routes/mongo.js
router.get('/count', async (req, res) => {
const counts = await mongoDB.getCounts();
res.send(counts);
});
router.post('/inccount', async (req, res) => {
const msg = await mongoDB.incCounts();
res.send(JSON.stringify(msg));
});
router.get('/getdata', async (req, res) => {
const data = await mongoDB.getData();
res.send(data);
});
๐ฉ MySQL ๋ฐ์ดํฐ ๊ด๋ จ ์ฝ๋ ์ ๋ฆฌ
// src/components/Start.js
async function sqlFetchData() {
const resCount = await fetch('http://localhost:4000/data/count');
if (resCount.status === 200) {
const num = await resCount.json();
if (num[0].counts !== 0) setCounts(num[0].counts);
} else throw new Error('ํต์ ์ด์');
//survey ๊ฐ์ ์ํ JOIN Table์ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
const resSurvey = await fetch('http://localhost:4000/data/survey');
if (resSurvey.status === 200) {
const surveyData = await resSurvey.json();
// explanation table์ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
const resExplanation = await fetch(
'http://localhost:4000/data/explanation'
);
if (resExplanation.status === 200) {
const explanationData = await resExplanation.json();
const madeData = makeData(surveyData, explanationData);
dispatch(init(madeData));
} else throw new Error('ํต์ ์ด์');
} else throw new Error('ํต์ ์ด์');
}
async function mongoFetchData() {
const resMongoCount = await fetch('http://localhost:4000/mongo/count');
if (resMongoCount.status === 200) {
const num = await resMongoCount.json();
console.log(num);
} else throw new Error('ํต์ ์ด์');
const resMongoData = await fetch('http://localhost:4000/mongo/getdata');
if (resMongoData.status === 200) {
const data = await resMongoData.json();
console.log(data);
} else throw new Error('ํต์ ์ด์');
}
useEffect(() => {
// sqlfetchData();
mongoFetchData();
}, [counts]);
// src/components/Show.js
async function sqlSendData() {
const resInc = await fetch('http://localhost:4000/data/inccount', {
method: 'POST',
});
if (resInc.status === 200) console.log(await resInc.json());
else throw new Error('ํต์ ์ด์');
}
async function mongoSendData() {
const resInc = await fetch('http://localhost:4000/mongo/inccount', {
method: 'POST',
});
if (resInc.status === 200) console.log(await resInc.json());
else throw new Error('ํต์ ์ด์');
}
useEffect(() => {
// sqlSendData();
mongoSendData();
}, []);
๐ฉ counts ๊ฐ ์ ๋ฌ
- Start ์ปดํฌ๋ํธ์ ๋ฐฉ๋ฌธ์ ์ ๊ฐ์ update ํด์ค์ผ ํ๋ฏ๋ก useState๋ก ๊ฐ์ ์ ์ธํด์ hook์ ์ ๋ฌ
// src/components/Start.js
async function mongoFetchData() {
const resMongoCount = await fetch('http://localhost:4000/mongo/count');
if (resMongoCount.status === 200) {
const num = await resMongoCount.json();
if (num[0].counts !== 0) setCounts(num[0].counts);
} else throw new Error('ํต์ ์ด์');
const resMongoData = await fetch('http://localhost:4000/mongo/getdata');
if (resMongoData.status === 200) {
const data = await resMongoData.json();
} else throw new Error('ํต์ ์ด์');
}
๐ฉ redux initialData ์ ๋ฌ
- ์ด ๊ฐ์ ๋ฐ๋ก ์ฌ์ฉํ ์ผ์ด ์์ผ๋ฉฐ, Mbti ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉํ๋ฉด ๋๋ฏ๋ก state๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์
- init() ํจ์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ง ๋ฃ์ด์ dispatch๋ก ์ ๋ฌ
// src/components/Start.js
async function mongoFetchData() {
const resMongoCount = await fetch('http://localhost:4000/mongo/count');
if (resMongoCount.status === 200) {
const num = await resMongoCount.json();
if (num[0].counts !== 0) setCounts(num[0].counts);
} else throw new Error('ํต์ ์ด์');
const resMongoData = await fetch('http://localhost:4000/mongo/getdata');
if (resMongoData.status === 200) {
const data = await resMongoData.json();
if (data[0].survey.length !== 0) dispatch(init(data[0]));
} else throw new Error('ํต์ ์ด์');
}
๐ ์ฝ๋: https://github.com/ebulsok/KDT-React-MBTI.git
'KDT > TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
10/14 TIL : MySQL ์ ์ฉ (0) | 2022.10.17 |
---|---|
10/12 TIL : React SPA ์ ์(Mbti-app) (0) | 2022.10.17 |
10/7 TIL : Redux, ๊ฐ๋จํ Todo-list ๋ง๋ค๊ธฐ (0) | 2022.10.14 |
10/5 TIL : React Router (0) | 2022.10.14 |
9/30 TIL : React Hooks(useEffect, useMemo) (0) | 2022.10.14 |