따꿍의 프로젝트

[20205.08.25] UserBookProgress의 is_bookmarked column 삭제 후 UserBookBookmark 생성 본문

웹프로젝트/졸작

[20205.08.25] UserBookProgress의 is_bookmarked column 삭제 후 UserBookBookmark 생성

공장 주인 따꿍 2025. 8. 29. 00:52

문제 및 발단

 

그냥 읽었을때는 뭔 소리인지 하나도 못 이해했는데 천천히 ERD 보면서 보니까 뭐가 문제인지 이해했다. 

북마크 했다고 책을 본건 아닌데 

북마크 여부가 최근 책 읽은 위치 정보와 같이 있으니까

북마크 하면 updated_at이 current time인 상태와 last_page와 last_char이 0, 0인 상태로 데이터가 생겨버린다. 

 

해결책

사실은 근데 최근 읽은 위치를 구할때 last_page와 last_char이 0,0인 애들은 빼고 구하면 해결되는 문제이긴 하다. 

근데 북마크 여부랑 책 진행상황이랑 같이 있는게 지저분하긴 해서

DB를 따로 둬야하긴 할 것 같다. 

 

소연이가 어떻게 DB를 분리했는지 좀 구경하고

더 좋은 해결책이라고 판단되면 그냥 그렇게 PR을 어푸할 생각이다. 

 

userBookProgress.ts

import { DataTypes, Model, Optional } from 'sequelize';
import sequelize from '../sequelize';

export interface UserBookProgressAttributes {
    user_id: number;
    book_id: number;
    updated_at?: Date;
    last_page?: number;
    last_char?: number;
}

interface UserBookProgressCreationAttributes
    extends Optional<
        UserBookProgressAttributes,
        'updated_at' | 'last_page' | 'last_char'
    > {}

class UserBookProgress
    extends Model<
        UserBookProgressAttributes,
        UserBookProgressCreationAttributes
    >
    implements UserBookProgressAttributes
{
    public user_id!: number;
    public book_id!: number;
    public updated_at!: Date;
    public last_page!: number;
    public last_char!: number;
}

UserBookProgress.init(
    {
        user_id: {
            type: DataTypes.INTEGER,
            primaryKey: true,
        },
        book_id: {
            type: DataTypes.INTEGER,
            primaryKey: true,
        },
        updated_at: {
            type: DataTypes.DATE,
            defaultValue: DataTypes.NOW,
        },
        last_page: {
            type: DataTypes.INTEGER,
            defaultValue: 0,
        },
        last_char: {
            type: DataTypes.INTEGER,
            defaultValue: 0,
        },
    },
    {
        sequelize,
        modelName: 'UserBookProgress',
        tableName: 'UserBookProgress',
        timestamps: false,
    }
);

export default UserBookProgress;

 

userBookBookmark.ts

import { DataTypes, Model } from 'sequelize';
import sequelize from '../sequelize';

export interface UserBookBookmarkAttributes {
    user_id: number;
    book_id: number;
    created_at?: Date;
}

class UserBookBookmark
    extends Model<UserBookBookmarkAttributes>
    implements UserBookBookmarkAttributes
{
    public user_id!: number;
    public book_id!: number;
    public created_at!: Date;
}

UserBookBookmark.init(
    {
        user_id: { type: DataTypes.INTEGER, primaryKey: true },
        book_id: { type: DataTypes.INTEGER, primaryKey: true },
        created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
    },
    {
        sequelize,
        modelName: 'UserBookBookmark', // Sequelize 내부에서 사용할 이름
        tableName: 'UserBookBookmark', // 실제 DB 테이블명
        timestamps: false,
    }
);

export default UserBookBookmark;

 

models/index.ts

import User from './user';
import Book from './book';
import Review from './review';
import UserBookProgress from './userBookProgress';
import UserPageBookmark from './userPageBookmark';
import UserReviewLike from './userReviewLike';
import UserBookBookmark from './userBookBookmark';

User.hasMany(Review, { foreignKey: 'user_id' });
Review.belongsTo(User, { foreignKey: 'user_id' });

Book.hasMany(Review, { foreignKey: 'book_id' });
Review.belongsTo(Book, { foreignKey: 'book_id' });

User.hasMany(UserBookProgress, { foreignKey: 'user_id' });
Book.hasMany(UserBookProgress, { foreignKey: 'book_id' });
UserBookProgress.belongsTo(User, { foreignKey: 'user_id' });
UserBookProgress.belongsTo(Book, { foreignKey: 'book_id' });

User.hasMany(UserPageBookmark, { foreignKey: 'user_id' });
Book.hasMany(UserPageBookmark, { foreignKey: 'book_id' });
UserPageBookmark.belongsTo(User, { foreignKey: 'user_id' });
UserPageBookmark.belongsTo(Book, { foreignKey: 'book_id' });

User.belongsToMany(Review, {
    through: 'UserReviewLike',
    foreignKey: 'user_id',
    otherKey: 'review_id',
});
Review.belongsToMany(User, {
    through: 'UserReviewLike',
    foreignKey: 'review_id',
    otherKey: 'user_id',
});

User.belongsToMany(Book, {
    through: UserBookBookmark,
    foreignKey: 'user_id',
    otherKey: 'book_id',
    as: 'bookmarkedBooks',
    onDelete: 'CASCADE',
});

Book.belongsToMany(User, {
    through: UserBookBookmark,
    foreignKey: 'book_id',
    otherKey: 'user_id',
    as: 'bookmarkUsers',
    onDelete: 'CASCADE',
});

export {
    User,
    Book,
    Review,
    UserBookProgress,
    UserPageBookmark,
    UserReviewLike,
    UserBookBookmark,
};