TIL

2020.09.03 sequelize mvc 스프린트 처음부터 구현하기

시계의온도 2020. 9. 3. 19:17

[내일 공부할것] --> 화요일에 세운 계획 

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'} 처럼 객체를 리턴해준다. 

 

레퍼런스

https://velog.io/@nawnoes/Express-url-%EC%8A%A4%ED%8A%B8%EB%A7%81%EC%9D%84-%ED%86%B5%ED%95%9C-%EC%A0%95%EB%B3%B4%EC%A0%84%EB%8B%AC

 

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일에 카카오 코테때 분명 떨어지겠지.. ㅠㅠ 사실 면접가도 지식이 너무 낮아서 쫄리긴한다. 

 

어차피 늦는거, 일과 병행하고 있으니 조급증 내지 말고 꾸준히 하자! 

(이직이라도 했으면 마음이 편할텐데.. ㅠㅠ) 

 

오늘도 고생했음 나자신!