본문 바로가기
Issue

Sequelize) boolean이 true/false가 아닌 0/1 숫자로 리턴되는 이슈

by 박채니 2023. 7. 28.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.

 

[Sequelize] boolean이 true/false가 아닌 0/1 숫자로 리턴되는 이슈

 

1️⃣ raw: true 옵션 사용할 경우

예를 들어, 아래와 같은 스키마를 가진 테이블이 있다고 가정해보겠습니다.

import { DataTypes, Model, Sequelize } from "sequelize";
import Post from "./post";

type ProviderType = "local" | "kakao";

class User extends Model {
    public readonly id: number;
    public email: string;
    public nick: string;
    public password: string;
    public provider: ProviderType;
    public sns_id: string;
    public is_married: boolean;

    static initiate(sequelize: Sequelize) {
        User.init(
            {
                email: {
                    type: DataTypes.STRING(40),
                    allowNull: true,
                    unique: true,
                },
                nick: {
                    type: DataTypes.STRING(15),
                    allowNull: false,
                },
                password: {
                    type: DataTypes.STRING(100),
                    allowNull: true,
                },
                provider: {
                    type: DataTypes.ENUM("local", "kakao"),
                    allowNull: false,
                    defaultValue: "local",
                },
                sns_id: {
                    type: DataTypes.STRING(30),
                    allowNull: true,
                },
                is_married: {
                    type: DataTypes.BOOLEAN(),
                    allowNull: false,
                },
            },
            {
                sequelize,
                underscored: true,
                timestamps: true,
                modelName: "User",
                tableName: "users",
                paranoid: true, // deleted_at 추가 (soft delete)
                charset: "utf8",
                collate: "utf8_general_ci",
            }
        );
    }

    static associate() {
        User.hasMany(Post);
        // 팔로워
        User.belongsToMany(User, { foreignKey: "following_id", as: "followers", through: "Follow" });
        User.belongsToMany(User, { foreignKey: "follower_id", as: "followings", through: "Follow" });
    }
}

export default User;

Sequelize를 통해 User 모델과 그에 따른 users 테이블을 생성하였습니다.

 

이 때, married를 boolean 타입으로 지정했지만, MySQL에는 boolean 타입이 아닌 TINYINT(1) 타입인 것을 확인할 수 있습니다.

 

데이터베이스에 저장된 값 역시 true | false가 아닌 0 | 1 인 것을 확인할 수 있습니다.

 

⭐️ 데이터 조회 시 raw: true 옵션 적용하지 않았을 때 리턴 값

router.get("/users", async (req: Request, res: Response, next: NextFunction) => {
    try {
        const user = await User.findOne({
            where: {
                id: 1,
            },
        });
        res.status(200).json(user);
    } catch (error) {
        console.error(error);
    }
});


// POSTMAN 리턴 값
{
    "id": 1,
    "email": "abc@test.com",
    "nick": "chany",
    "password": "1234",
    "provider": "local",
    "sns_id": null,
    "is_married": true,
    "createdAt": "2023-07-28T07:13:37.000Z",
    "updatedAt": "2023-07-28T07:13:37.000Z",
    "deletedAt": null
}

is_married가 true로 잘 리턴되는 것을 확인할 수 있습니다.

 

⭐️ 데이터 조회 시 raw: true 옵션 적용했을 때 리턴 값

router.get("/users", async (req: Request, res: Response, next: NextFunction) => {
    try {
        const user = await User.findOne({
            where: {
                id: 1,
            },
            raw: true
        });
        res.status(200).json(user);
    } catch (error) {
        console.error(error);
    }
});


// POSTMAN 리턴 값
{
    "id": 1,
    "email": "abc@test.com",
    "nick": "chany",
    "password": "1234",
    "provider": "local",
    "sns_id": null,
    "is_married": 1,
    "createdAt": "2023-07-28T07:13:37.000Z",
    "updatedAt": "2023-07-28T07:13:37.000Z",
    "deletedAt": null
}

is_married가 true | false가 아닌 1로 리턴되는 것을 확인할 수 있습니다.

 

2️⃣ SubQuery에서 boolean 값을 리턴할 경우 (ex. IF...)

const user = await User.findOne({
    attributes: [[Sequelize.literal("IF(provider = 'kakao', true, false)"), "is_kakao_login"]],
});

// POSTMAN 리턴 값
{
    "is_kakao_login": 0
}

역시 true | false가 아닌 0 | 1로 리턴 되는 것을 확인할 수 있습니다.

 

SubQuery에서 true | false를 문자열 'true' 혹은 'false'로 리턴하면 true, false로 리턴할 수 있지만,

프론트 단에서는 해당 값이 boolean이 아닌 문자열이므로, 분기 처리가 까다로울 수 있습니다.

 

해결책

 

1️⃣ raw: true 옵션을 제거

 

2️⃣ json으로 CAST

const user = await User.findOne({
    attributes: [
        [
            Sequelize.literal("IF(provider = 'kakao', CAST(true as json), CAST(false as json))"),
            "is_kakao_login",
        ],
    ],
});

// POSTMAN 리턴 값
{
    "is_kakao_login": false
}

boolean true | false로 리턴 되는 것을 확인할 수 있습니다.

 

✅ 참고 사이트

https://stackoverflow.com/questions/49131832/how-to-create-a-json-object-in-mysql-with-a-boolean-value

 

How to create a JSON object in MySql with a boolean value?

I would like my MySql query to return a JSON object that looks as follows: {"name": "Piotr", "likesMysql": true} This seems to be working fine when I do: SELECT json_object( 'name', 'Piotr',...

stackoverflow.com

 

https://bugs.mysql.com/bug.php?id=79813