2020.09.03 sequelize mvc 스프린트 처음부터 구현하기
[내일 공부할것] --> 화요일에 세운 계획
controller 구현, sprint완성하기. 일단 테스트 통과 후 처음부터 재작성 하기. :완료
오피스 아워. : 로그인 인증 내용 강의 들음
toy-30 번 풀기. : 못함..
+) sequelize 사용 MVC 스프린트 다시 처음부터 코드 작성해서 제출하기
[실제 한것]
공부시간: 7시간 정도.
sequelize 설치.
//터미널
$ npm install --save sequelize
마이그레이션을 하기 위한 cli 설치
//터미널
npm install --save-dev sequelize-cli
프로젝트 bootstrapping
//터미널
npx sequelize-cli init
터미널에 mysql을 열어서 데이터베이스를 만들어 주기.
//터미널
mysql -u root -p
mysql> create database sprintMVC ;
//데이터베이스 생성
Table Plus GUI 에서 데이터베이스 확인하기 -> 생성확인됨.
config 설정 변경
{
"development": {
"username": "root",
"password": "---",//내 mysql접속 비밀번호
"database": "sprintMVC",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": "---",//내 mysql접속 비밀번호
"database": "sprintMVC",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": "---",//내 mysql접속 비밀번호
"database": "sprintMVC",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
models 하위에 url.js 파일 생성 후 모델 작성. 함수로 작성해준다.
//cli를 통해서 코드를 만들면, 아래와 같은 구조로 생성된다.
//이런 구조로 모델을 작성해야, sequelize에서 사용할 수 있는데, 원리는 좀더 공부해봐야겠다.
//models/index.js 에서 파일을 읽어오면서, 적용되는걸로 추정..된다.
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Url extends Model { }
Url.init({
url:DataTypes.STRING,
title:DataTypes.STRING,
visits:{
type:DataTypes.INTEGER,
defaultValue:0 }
}, {
sequelize, // 데이터베이스 connection
modelName: 'Url'
});
return Url;
}
마이그레이션을 진행해야 DB에 반영된다. 모델코드를 따로 작성했으므로, migration skeleton 코드작성.
//터미널
npx sequelize-cli migration:generate --name 내가 넣고 싶은 이름 migration-skeleton
명령어를 실행하면 migration 디렉토리에 이런 코드가 생성된다.
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
/**
* Add altering commands here.
*
* Example:
* await queryInterface.createTable('users', { id: Sequelize.INTEGER });
*/
},
down: async (queryInterface, Sequelize) => {
/**
* Add reverting commands here.
*
* Example:
* await queryInterface.dropTable('users');
*/
}
};
작성해주기.
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('urls',
{
url: Sequelize.STRING,
title: Sequelize.STRING,
visits: {
type: Sequelize.INTEGER,
defaultValue: 0
}
})
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('urls');
}
};
마이그레이션 해주기!
//터미널
npx sequelize-cli db:migrate
터미널에 이런 안내메세지가 뜨면서 테이블이 생성된걸 볼 수 있다. sequelizeMeta도 생성된다.
Loaded configuration file "config/config.json".
Using environment "development".
== 20200903103539-url: migrating =======
== 20200903103539-url: migrated (0.017s)
cli 에서 자동으로 생성해주면, 터미널에 치기 번거롭다는 단점이 있지만 아래와 같은 장점이 있다.
레퍼런스: https://victorydntmd.tistory.com/27
- 테이블 이름이 복수형으로 변경
- 자동으로 id, createAt, updateAt 3개의 필드를 생성
- migration 파일을 생성
cli로 생성해주지 않았으므로..ㅠㅠ 직접 작성해주어야 한다. 마이그레이션 파일을 수정하고 다시 마이그레이션을 해주더라도, 새로운 내용이 반영된 테이블이 생성되지 않는데, 이미 기존에 테이블이 동일한 내용으로 생성되서 그런것 같다.
//터미널
npx sequelize-cli db:migrate:undo
즉, 여태까지 해본결과 마이그레이션을 해주면 최신 상태로 업댓해주지 않고, undo를 했다가 다시 npx sequelize-cli db:migrate 를 해주면 mysql에서 테이블 칼럼이 업데이트 된걸 볼 수 있다.
테스트케이스를 돌려보면, 자꾸 int(11)이 int로 되야 한다고 하는데 최신버전인 6.3.5 에서도 int(11)로 찍히는 이유를 나는 모르겠다.. 헬프데스크에 올려봐야겠다...
이제 MVC중 controllers작성 후 routing하기. 테스트케이스를 잘 보고 똑같은 명칭의 경로로 파일을 만들어야 한다;
스프린트를 하면서 제일 많이 본 에러는
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
인데 asnyc , await , res end까지 완성하면 해결된다. 구글링 해보니 모카에서 내는 에러다.
라우터 코드 구현. 그리고 컨트롤러의 get을 구현하던 중 findAll()을 하면 select와 동일하게 데이터 목록 전부를 배열의 형태로 불러올 수 있다는 걸 배웠다. 추가로 res.status().json() 형식으로 사용할 수도 있다는 걸 알았다.
res.json() 레퍼런스
https://haeguri.github.io/2018/12/30/compare-response-json-send-func/
sequelize의 메소드를 사용하기 위해서는 async 함수로 get과 post함수를 선언해주어야한다. 이후 주어진 utils.js파일을 이용해서, post함수를 작성해야한다. 혹시 이글을 보시는 분들이 정답을 스포(?)당할까봐 컨트롤러 관련 코드는 작성하지 않기로.
이 코드를 이해하기 위해서 request에 대해서 다시 공부했다.
https://www.npmjs.com/package/request
request
Simplified HTTP request client.
www.npmjs.com
당황스러운 것은, findOrCreate 를 어떻게 넣어서 title을 뽑아내야..하나 싶은 문제였는데, 레퍼런스를 꼼꼼히 보니 리턴값에 불리언이 있었다.
https://sequelize.org/master/class/lib/model.js~Model.html#static-method-findOrCreate

즉, 프로미스방식으로 리턴하되 모델과 불리언을 리턴한다! 그래서 실질적으로 해당 배열의 값은 2개가 되니 인자를 두개로 나눠서 배열의 구조분해 할당 방식으로 받아오면, 각 변수에 접근해서 문제를 해결할 수 있는 것이다. 이거참, 알고보니 보는거지 허허허헣.
그리고 헷갈리는 부분은, 기존에 값이 있으면 false / 값이 없으면 true를 리턴하는 것이다. 아니..반대가 맞지않나..?
아마도 기존에 값이 없으면 만들꺼니까 true! 이런식인가.. (추측..)
마지막으로 redirect 까지 구현하면 과제는 끝난다. 리다이렉트 될때마다 visits를 1씩 업데이트하는게 목적인데, 이 과정에서 sementic url 방식이 사용된다. 해당 방식은, 쿼리스트링을 통해서 하는것에 비해서 url을 깔끔해 보이게 만들어주는 방법으로,
req.params를 통해 값을 받아올수 있다. req.params를 하면 {id: '1'} 처럼 객체를 리턴해준다.
레퍼런스
Express url 스트링을 통한 정보전달
위와 같이 쿼리 스트링을 사용하고 싶은경우. req.query를 사용한다. 복수의 쿼리스트링을 가져오는 것도 가능: path 방식을 통한 url의 경우 params를 통해서 값을 가져올 수 있다.깔끔한 URL을 유지하�
velog.io
https://wayhome25.github.io/nodejs/2017/02/18/nodejs-11-express-query-string/
Express-URL을 이용한 정보의 전달 - 쿼리스트링 · 초보몽키의 개발공부로그
동적인 파일을 통해서 (app.js 에 직접 작성) 쿼리스트링 사용에 대해 살펴본다.
wayhome25.github.io
또 여기서 알게 된점은
await urlModel.findOne().then((data)=>{return }).then(res.redirect)
같이 await를 사용하더라도 .then을 통해서 연속해서 사용할 수 있다는점! 이다. await로 받아와도 체이닝 가능. 흠.. 프로미스 부분.. 진짜 못해도 30시간쯤은 쓴 것 같은데 매번 왜 이리 새로워;;
그리고 res.redirect는 express에서 지원하는 기능으로, 해당 url로 보내준다!
길고 긴 스프린트를 처음부터 되짚어 가며 마무리하였다. 다음은 솔로 프로그래밍으로 구현하는 것이라고 하니, 해보면 더 잘 이해할 수 있을 것 같다. 그리고.. sequelize... 얼마나 현업에서 유용한지 모르겠지만 지금은 sql 쿼리 짜는게 더 쉬운거 같은데.. ㅠㅠ
휘발성이라서 지금 생각은 또 아리아리 하게 나지만. 이번 스프린트가 유독 어렵긴 했지만, 한번 했던걸 되짚어 가는데도 계속 버벅 거렸다. 앞으로 복습을 누진적으로 꼭 해야겠다.
[내일 할 것]
toy - 30 번 풀기 , 블로그에 리뷰하기
toy - 31 번 풀기 , 블로그에 리뷰하기
인증(authentication) 스프린트 진행. 어차피 이번주는 솔로 프로그래밍이라고 하니 후딱 해버리자! 코테공부를 거의 못해서
9/12일에 카카오 코테때 분명 떨어지겠지.. ㅠㅠ 사실 면접가도 지식이 너무 낮아서 쫄리긴한다.
어차피 늦는거, 일과 병행하고 있으니 조급증 내지 말고 꾸준히 하자!
(이직이라도 했으면 마음이 편할텐데.. ㅠㅠ)
오늘도 고생했음 나자신!