// src/models/user.model.js // 사용자 모델 const { DataTypes } = require('sequelize'); const bcrypt = require('bcryptjs'); module.exports = (sequelize) => { const User = sequelize.define('User', { id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, }, email: { type: DataTypes.STRING(255), allowNull: false, unique: true, validate: { isEmail: true, }, comment: '이메일 (로그인 ID)', }, password: { type: DataTypes.STRING(255), allowNull: false, comment: '비밀번호 (해시)', }, name: { type: DataTypes.STRING(100), allowNull: false, comment: '사용자 이름', }, role: { type: DataTypes.ENUM('user', 'admin'), defaultValue: 'user', comment: '역할 (user: 일반 사용자, admin: 관리자)', }, status: { type: DataTypes.ENUM('active', 'inactive', 'suspended'), defaultValue: 'active', comment: '계정 상태', }, plan: { type: DataTypes.ENUM('free', 'basic', 'pro', 'enterprise'), defaultValue: 'free', comment: '요금제 플랜', }, monthlyTokenLimit: { type: DataTypes.INTEGER, defaultValue: 100000, // 무료 플랜 기본 10만 토큰 comment: '월간 토큰 한도', }, lastLoginAt: { type: DataTypes.DATE, allowNull: true, comment: '마지막 로그인 시간', }, }, { tableName: 'users', timestamps: true, underscored: true, hooks: { // 비밀번호 해싱 beforeCreate: async (user) => { if (user.password) { const salt = await bcrypt.genSalt(10); user.password = await bcrypt.hash(user.password, salt); } }, beforeUpdate: async (user) => { if (user.changed('password')) { const salt = await bcrypt.genSalt(10); user.password = await bcrypt.hash(user.password, salt); } }, }, }); // 인스턴스 메서드: 비밀번호 검증 User.prototype.validatePassword = async function(password) { return bcrypt.compare(password, this.password); }; // 인스턴스 메서드: 안전한 JSON 변환 (비밀번호 제외) User.prototype.toSafeJSON = function() { const values = { ...this.get() }; delete values.password; return values; }; return User; };