[Node] Node.js + mySQL + Sequelize로 데이터베이스 테이블 만들어보자

    728x90
    반응형

     

     

    [Node] Node.js + mySQL + Sequelize로 데이터베이스 테이블 만들어보자

    강의에서 백엔드 구성을 위 세가지를 사용하는 것을 보았다.

    앞으로는 프론트도 백단을 알고있어야 한다고 생각하는 것과 함께

    다음에 내가 프로젝트를 혼자 만들때 이걸보고 참고해서 만들기 위해서

    이번에 잘 알아두고자 블로그에 올린다.

     

    Node.js?

    • Node.js는 JavaScript를 서버 측에서 실행할 수 있게 해주는 런타임 환경입니다.
    • 원래 JavaScript는 브라우저 내에서만 실행되었지만, Node.js 덕분에 개발자들은 웹 서버 개발에도 JavaScript를 사용할 수 있게 되었습니다.
    • node가 서버가 아니냐고 착각하는 분들이 있는데 node에서 제공하는 http모듈이 서버 입니다. 
    • Express.js
      • Node.js의 웹 애플리케이션 프레임워크
      • 웹 서버를 빠르고 쉽게 구축할 수 있도록 설계되었으며, 다양한 라우팅 기능과 미들웨어 옵션을 제공하여 확장성 있는 API를 개발할 수 있게 해줍니다.
      • 기본 node의 http모듈 보다 깔끔하고 구조적으로 짤 수 있다.
      • 내부적으로 http를 사용해서 서버를 돌릴 수 있다.

    필요한 모듈

    npm i express

     

     

    mySQL?

    • MySQL은 관계형 데이터베이스 관리 시스템(RDBMS)으로, 구조화된 데이터를 효율적으로 저장하고 관리할 수 있습니다.
    • SQL(Structured Query Language)을 사용하여 데이터를 쿼리합니다.

    필요한 모듈

    mySQL 설치가 처음이라면  아래 링크 참고하세요 (제로초의 node.js 교과서)

    https://thebook.io/080334/0319/

    mysql installer for window 다운로드 및 설치
    
    mySql workbench 설치 => 데이터베이스를 들여다 보려면 터미널에서 명령어 쳐서 해야하는데,
    시각화해서 편하게 만들어준것

     

     

     

     

    Sequelize?

    • Sequelize는 Node.js 환경에서 사용할 수 있는 Promise 기반 ORM(Object-Relational Mapping) 라이브러리입니다.
    • 데이터베이스의 테이블을 JavaScript 객체로 매핑함으로써 SQL 쿼리를 직접 작성하지 않고도 데이터베이스를 조작할 수 있게 해줍니다.
    • 즉, SQL언어를 사용하는 mySQL를 자바스크립트로 조작할 수 있게 해주는 라이브러리

    필요한 모듈

    npm i sequelize sequelize-cli mysql2
    
    mysql2 = 노드와 mysql을 연결해주는 드라이버

     

     

     

     

    초기 세팅 해보자

    sequelize 초기 세팅

    npx sequelize init
    
    --> config, migrations, models, seeders의 폴더가 생긴다.
    --> /config/config.json 파일에 들어가 data-base명과 password를 입력한다.
    --> host는 기본 127.0.0.1
    --> portsms 3306

     

     

    mySQL과 sequelize 연결하기

    /models/index.js

    /models/index.js
    
    const Sequelize = require("sequelize");
     // 운영버전일땐 production 개발할땐 development
    const env = process.env.NODE_ENV || "development";
    // config데이터를 가져온거에서 development의 데이터 가져옴
    const config = require("../config/config")[env];
    const db = {};
    
    // sequelize가 node와 mySQL연결해는 코드
    // sequelize는 내부적으로 mySQL툴 사용.
    // node와 mySQL을 연결해주는 드라이버역할인 mysql2라이브러리에 필요정보를 줘서 역할을 수행하게 함
    // 연결성공하면 sequelize객체에 연결정보가 담김
    // 근데 연결만 성공해서는 아무 의미 없고 mySQL에 테이블들을 만들어줘야한다.
    const sequelize = new Sequelize(config.database, config.username, config.password, config);
    
    Object.keys(db).forEach((modelName) => {
    	if (db[modelName].associate) {
    		db[modelName].associate(db);
    	}
    });
    
    db.sequelize = sequelize;
    db.Sequelize = Sequelize;
    
    module.exports = db;

     

     

    sequelize 모델 만들기

    /models/user.js

    /models/user.js
    
    module.exports = (sequelize, DataTypes) => {
        const User = sequelize.define(
            // define한 User은 모델의 이름.
            // mySQL에는 자동으로 소문자, 복수가 되어서 users 테이블로 저장됨.
            // 첫번째 객체 : user 정보
            // 두번째 객체 : user모델에 대한 세팅
            "User",
            {
            	// id: {}, // id는 mySQL에서 자동으로 넣어주기 때문에 여기서 만들 필요 없다.
                // 각 컬럼들에 대한 정의
                email: {
                	// datatypes = STRING, TEXT, BOOLEAN, INT, INTEGER, FLOAT, DATETIME
                    type: DataTypes.STRING(30), // 최대 30자까지의 문자열
                    allowNull: false, // NULL 값을 허용하지 않음 (필수 값)
                    unique: true, // 고유한 값, 중복 불가
                },
                nickname: {
                    type: DataTypes.STRING(30), // 최대 30자까지의 문자열
                    allowNull: false, // NULL 값을 허용하지 않음
                },
                password: {
                    type: DataTypes.STRING(100), // 비밀번호는 암호화할 때 길이가 길어지므로 100자 제한
                    allowNull: false, // NULL 값을 허용하지 않음
                },
            },
            {
                charset: "utf8", // UTF-8 인코딩
                collate: "utf8_general_ci" // 일반적인 비교 방식을 사용 // 한글 저장
            }
        );
    
        // 테이블간의 관계 설정
        // 테이블간의 관계에서는 associate 사용 (글과 글을 쓴사람, 팔로워와 팔로잉 등등 여러테이블이 관계 되어있을때)
    	// 그래서 mySQL같은걸 관계형 데이터베이스라고도 한다.
        User.associate = (db) => {
            // User와 Post는 1:N 관계(1대다)
            // User.hasMany(db.Post) = 유저는 포스트를 많이 가질 수 있다.
             // 유저가 쓴 Post들의 정보를 유저에 쓰지 않는 이유는
             // 한칸에 하나의 데이터만 들어가야하는데 많아지면 그럴수 없기 때문이다. (, or 여러정보 안된다)
             // 그래서 hasMany가 있는곳에 많이 가지고 있을 데이터를 갖고있는건 원칙적으로 맞지 않다.
             // hasMany당한 즉 belongsTo를 사용하는 컬럼에서 갖고있어야 한다.
            db.User.hasMany(db.Post);
            db.User.hasMany(db.Comment);
            
            // User와 Post는 N:M 관계(다대다), "Like"라는 중간 테이블을 통해 연결
            db.User.belongsToMany(db.Post, { through: "Like", as: "Liked" });
            
            // User와 User는 N:M 관계, "Follow"라는 중간 테이블을 통해 팔로워와 팔로잉 관계 설정
            // User의 Followers 찾기
            db.User.belongsToMany(db.User, { through: "Follow", as: "Followers", foreignKey: "FollowingId" });
            // User의 Followings 찾기
            db.User.belongsToMany(db.User, { through: "Follow", as: "Followings", foreignKey: "FollowerId" });
            
            // 예: post 모델에서 사용
            db.Post.belongsTo(db.Post, { as: "Retweet" }); // 리트윗 할때 post끼리 관계
        };
    
        return User;
    };

     

    추가 설명

    sequelize.define 함수의 두번째 객체는 user모델에 대한 세팅이 들어간다.

    거기에서 coollate 키값을 가진 데이터는

    • collate: "utf8_general_ci",  // 한글 저장
    • collate: "utf8mb4_general_ci"  // 한글 + 이모티콘 저장

     

     

    sequelize 모델 결합 (index.js에 모델들 등록)

    /models/index.js

    /models/index.js
    
    const Sequelize = require("sequelize");
    const env = process.env.NODE_ENV || "development";
    const config = require("../config/config")[env];
    const db = {};
    
    // sequelize가 node와 mySQL연결해는 코드
    // node와 mySQL을 연결해주는 드라이버역할인 mySQL2라이브러리에 필요정보를 줘서 역할을 수행하게 함
    const sequelize = new Sequelize(config.database, config.username, config.password, config);
    
    // 빈 객체 db에 모델 5개 등록
    // comment.js에서 module.exports로 가져온 함수 실행 -> 모델이 sequelize에 등록
    db.Comment = require("./comment")(sequelize, Sequelize);
    db.Hashtag = require("./hashtag")(sequelize, Sequelize);
    db.Image = require("./image")(sequelize, Sequelize);
    db.Post = require("./post")(sequelize, Sequelize);
    db.User = require("./user")(sequelize, Sequelize);
    
    // 모델이 채워진 db객체를 반복문 돌려서 associate 실행
    Object.keys(db).forEach((modelName) => {
    	if (db[modelName].associate) {
    		db[modelName].associate(db);
    	}
    });
    
    db.sequelize = sequelize;
    db.Sequelize = Sequelize;
    
    module.exports = db;

     

     

    app.js에 모델 불러오기 / sequeliz sync 맞추기

    // node에서는 import / export 안쓰고 require / module.exports 사용
    const express = require("express");
    const postRouter = require("./routes/post");
    
    // sequelize에서 model 모두 등록
    // express에서 그 sequelize를 등록해야 한다.
    const db = require("./models");
    const app = express();
    db.sequelize
    	.sync()
    	.then(() => {
    		console.log("db연결 성공!");
    	})
    	.catch(console.error);
    
    app.listen(3065, () => {
    	console.log("서버 실행 중");
    });

     

     

     

    명령어로 실행

    models를 sequelize에 등록, sequelize를 express에 등록 후
    
    npx sequelize db:create --> sequelize 초기 생성
    
    node app --> 실행

     

     

    그런데 이러한 경우엔 코드를 바꿀때마다 껐다가 다시 켜줘야하는 불편함이 있다.

    이럴때는 

    // 노드에서 코딩을하고나서 매번 껐다 켰다 해야 확인할 수 있는데, 이를 자동화해주는 라이브러리
    npm i -D nodemon
    
    /package.json 에 등록
    "scripts": {
        "dev": "nodemon app"
    },
    
    npm run dev로 실행

     

    이러면 코드가 바뀔때마다 자동으로 재실행된다.

     

     

     

    결과

    mySQL에 config.js에 database명으로 지정해놓은

    react-nodebird라는 이름으로 데이터베이트 칼럼이 들어있는것을 확인할 수 있다.

    뿐만아니라 model을 만들고 그걸 sequelize에 등록 -> sequelize를 express에 등록한 것들도

    모두 확인 할 수 있다.

     

     

     

     

     

     

     

    참조!

    https://www.inflearn.com/course/lecture?courseSlug=%EB%85%B8%EB%93%9C%EB%B2%84%EB%93%9C-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%A6%AC%EB%89%B4%EC%96%BC&unitId=48832&category=questionDetail&tab=curriculum

     

    학습 페이지

     

    www.inflearn.com

     

    728x90
    반응형

    댓글