본문 바로가기
node.js 교과서

node.js 교과서 | 7장] MySQL(4) : 모델 정의하기, 관계 정의하기

by 솨앙 2024. 10. 6.
반응형

 

 
Node.js 교과서
서버와 데이터베이스 개념을 시작으로 노드의 기본 개념을 차근차근 설명해나간다. 군더더기 없는 직관적인 설명, 풍부한 그림으로 기본 개념을 확실히 이해하고, 노드의 기능과 생태계를 사용해보며 실제로 동작하는 서버를 만들어보자. 웹 서버, 웹 API 서버, SNS 서비스, 실시간 GIF 채팅방, 경매 시스템, 위치 기반 장소 검색 서비스, 커맨드라인 인터페이스를 모두 만들어 볼 수 있다. 실무에 당장 적용할 수 있고, 참고할 수 있는 예제와 코드를 최신 문법으로 다뤄보자.
저자
조현영
출판
길벗
출판일
2018.08.01

 

본 글의 내용은 node.js 교과서(조현영)를 읽고 공부한 내용입니다. 

1. 모델 정의하기

앞선 글에서 exprss앱에 mysql을 연결하는 것을 성공하였다.

2024.09.29 - [node.js 교과서] - [node.js 교과서 | 7장] MySQL(3) : Sequelize 사용하기

 

[node.js 교과서 | 7장] MySQL(3) : Sequelize 사용하기

본 글의 내용은 node.js 교과서(조현영) 을 읽고 공부한 내용입니다.1.  Sequelize 설치하기- 시퀄라이즈란 자바 스크립트 객체와 데이터베이스의 릴레이션을 매핑해주는 도구입니다.- 즉 자바스크립

sua0105.tistory.com

그럼 이제 MySQL에서 정의한 테이블을 시퀄라이즈에서도 정의해 보자.

MySQL에서의 테이블 == 시퀄라이즈에서의 모델

시퀄라이즈는 모델과 MySQL의 테이블을 연결해 주는 역할을 하는 것이다.


앞서서 나는 'nodejs' 데이터베이스 안에 'users'와 'comment' 테이블을 만들어놓았다. 이 테이블과 User, Comment 모델을 만들어

연결해 보자

model/user.js

const Sequelize = require('sequelize');
// user모델을 만들고 모듈로 exports 해준다. User 모델은 Sequelize.Model을 확장한 클래스

module.exports = class User extends Sequelize.Model{
    static init(sequelize){
        return super.init({
            name :{
                type : Sequelize.STRING(20),
                allowNull : false,
                unique : true,
            },
            age : {
                type : Sequelize.INTEGER.UNSIGNED,
                allowNull:false,
            },
            married :{
                type : Sequelize.BOOLEAN,
                allowNull:false,
            },
            comment : {
                type : Sequelize.TEXT,
                allowNull:true,
            },
            created_at:{
                type : Sequelize.DATE,
                allowNull:false,
                defaultValue:Sequelize.NOW,
            },
        },{
            sequelize,
            timestamps:false,
            underscored:false,
            modelName:'User',
            tableName:'users',
            paranoid : false,
            charset : 'utf8',
            collate:'utf8_general_ci',
        });
    }
    static assocate(db){}
};
User 모델을 만들고 모듈로 exports 하는 코드다. User모델은 Sequelize.Model을 확장한 클래스로 선언한다.
모델은 크게 static init 메서드, static associate 메서드가 있다.
1. static init
- 테이블에 대한 설정
-> 첫 번째 인수 : 테이블 칼럼에 대한 설정
* 시퀄라이즈는 알아서 id를 기본키로 연결하므로 id 칼럼을 적어줄 필요가 없다.
- mySQL의 컬럼 내용과 동일해야 정확하게 대응된다. 

 

시퀄라이즈와 mysql에서의 속성 값 비교

-> 두 번째 인수 : 테이블 자체에 대한 설정
-timestamps : createdAt과 같은 칼럼을 추가하는 것 - 예제에서는 created_at칼럼을 넣어줬으므로 false
- modelname: 모델 이름 설정
- tablename : 실제 데이터베이스의 테이블 이름
-underscored : 테이블 명과 칼럼명을 캐멀케이스로 기본적으로 제공(camelCase) -> 스네이크 케이스로(snake_case)
- paranoid : deletedAt이 기록되도록 : 복원해야 될 상황이 있을 것 같다면 사용
- charset / collate : 한국어를 사용할 거라면 utf8/utf8_general_ci , 이모티콘까지 사용할거라면 : utf8mb4/ utf8mb4_general_ci

 

models/comment.js

const Sequelize = require('sequelize');
const { sequelize } = require('.');

modeul.exports = class Comment extends Sequelize.Model{
    static init(sequelize){
        return super.init({
        comment : {
            type : Sequelize.STRING(100),
            allowNull : false,
        },
        created_at:{
            type : Sequelize.DATE,
            allowNull : true,
            defaultValue : Sequelize.NOW,
        },
    },{
        sequelize,
        timestamps : false,
        modelName : 'Comments',
        tableName : 'comments',
        paranoid : false,
        charset: 'utf8mb4',
        collate : 'utf8mb4_general_ci',
    }
);
}
static associate(db){}
};

 

이제 모델을 생성했으니 models/index.js와 연결해 보자.

const Sequelize = require('sequelize');
const User = require('./user');
const Comment = requir('./comment');
...
db.sequelize = sequelize;

db.User = User;
db.Comment = Comment;

User.init(sequelize);
Comment.init(sequelize);

User.associate(db);
Comment.associate(db);
...
db라는 객체에 User, Comment 모델을 담아 두었다. 따라서 db객체를 require 해서 User와 Comment 모델에 접근이 가능.
User.init, Comment.init은 앞서 작성해 놓은 static.init을 호출하는 것이고 메서드가 실행되어야 테이블이 모델로 연결된다.
associate 메서드는 다른 테이블과의 관계를 연결하는 것이다.

관계? 관계에 대해서 더 알아보자

 

2. 관계 정의하기

주어진 예시 users과 comments 테이블을 생각해 보자

사용자 1명은 여러 개의 댓글을 달 수 있다. 하지만 한 개의 댓글에 작성자가 여러 명일 수는 없다

-> 이런 관계를 1:N 관계라고 한다.

추가적으로 1대 1, 다대다 관계 또한 존재한다. 

 

(1) 1:N 관계 ( hasMany, belongsTo)

- 시퀄라이즈에서는 1:N 관계를 hasMany라는 메서드로 표현한다.

-> users 로우 한 개를 불러올 때 연결된 comments 테이블의 로우들도 함께 불러온다.

- belongsTo 메서드도 존재한다

-> comments 테이블의 로우 하나를 불러올 때 연결된 users 로우도 함께 불러온다.

 

앞서 작성해 놓은 user.js와 comment.js associate 메서드를 작성해 보자.

 

//comment.js
static associate(db){
    db.Comment.belongsTo(db.User,{foreignKey : 'commenter', targetKey:'id'});
}

//user.js 
static assocate(db){
        db.User.hasMany(db.Comment,{foreignKey : 'commenter', sourceKey:'id'});
    }

 

이제 npm start 명령어로 서버를 실행해 주면?

데이터베이스 연결 성공!

 

그럼 나머지 1:1 관계, 다대다 관계에 대해서도 알아보자

 

(2) 1:1관계(hasOne, belongTo)

- 예를들어 user의 id를 담고 있는 info 모델이 있다고 가정하자 그럼 다음과 같이 작성할 수 있다.

db.User.hasOne(db.Info,{foreignKey : 'UserId', sourceKey:'id'});
db.Info.belongTo(db.User,{foreignKey:'UserId',targetKey:'id});

- 1대 1 관계에서도 메서드가 반대가 되면 안된다!

다른 모델의 정보가 들어가는 테이블에 belongTo를 사용한다

 

(3) 다대 다 관계(belongsToMany)

- 게시글과 해시태그의 관계를 살펴보자

-> 한개의 게시글은 여러 개의 태그를 가질 수 있다.

-> 한개의 해시태그는 여러 개의 게시글에 사용될 수 있다.

db.Post.belongsToMany(db.Hashtag,{through : 'PostHashtag'});
db.Hashtag.belongsToMany(db.Hashtag,{through : 'PostHashtag'});

- 양쪽 모델에서 모두 belongsToMany 매서드를 사용한다.

- 다대 다 관계 특성상 새로운 모델이 생성된다(PostHashtag : 게시글과 태그의 아이디 저장) 

 

반응형