• Database name : 원하는 이름을 입력
  • Charset: utf8mb4 
    • 문자 인코딩 스타일을 셋팅 하는 부분
    • utf8mb4은 이모지까지 인코딩 가능
  • Collection : utf8mb4_unicode_ci
    • 정렬을 하는 방식을 선택하는 부분
    • 선택한 방식을 사람들이 많이 사용

Error 가 발생한 상황

content 에 1000 글자 이상의 문자를 입력 했을때 발생

출력된 Error  내용

ERROR message
{
    "name": "SequelizeDatabaseError",
    "parent": {
        "code": "ER_DATA_TOO_LONG",
        "errno": 1406,
        "sqlState": "22001",
        "sqlMessage": "Data too long for column 'content' at row 1",
        }
}

 

예상한 Error 위치

table 을 생성할 때 설정한 content에 입력할 수 있는 데이터(글자)의 길이를 초과

// model-Post.js
content: { type: DataTypes.STRING}

 

Sequelize 에서 STRING == VARCHAR

그래서 65535 글자 수를 가질 수있다고 생각했는데 에러 발생

 

시도 1 : TEXT 사용

content:{type:DataType.TEXT}

-->  긴 문장이 담아지는 것은 성공

 

!! 하지만 1000 글자를 넘겼을 경우 서버가 중단된다. --> res.send() 를 호출한 뒤 또 호출하여서 발생

 

 

해결

1. data가 길어서 에러가 뜨는 상황 : content:{type:DataType.TEXT} 로 변경하여 해결

 

2. 유효성 확인을 하는 코드가 res.send() 를 중복해서 호출하여 생기는 상황 

  • 문제의 코드
router.post("/", async (req, res)=>{
    const {title, content} = req.body;
    
    try{
        const newPost = await sequelize.transaction(async ()=>{
	// -------- res.send 중복 유발 --------------------
            if(title.length > 15){
                return res.status(400).send("Title must be under 15 characters.");
            }

            if(content.length > 1000){
                return res.status(400).send("Content must be under 1000 characters.");
            }
	//---------------------------------------------
            const post = await Post.create({
                title,
                content
            });
            console.log("A post is created")
            return post;
        })
        res.status(200).send(newPost);

    }catch (err){
        console.error("Error while create a post");
        res.status(500).send(err);
    }

})
  • 해결법 1 :  if 문 위치 변경
router.post("/", async (req, res)=>{
    const {title, content} = req.body;

    if(title.length > 15){
        return res.status(400).send("Title must be under 15 characters.");
    }

    if(content.length > 1000){
        return res.status(400).send("Content must be under 1000 characters.");
    }

    try{
        const newPost = await sequelize.transaction(async ()=>{

            const post = await Post.create({
                title,
                content
            });
            console.log("A post is created")
            return post;
        })
        res.status(200).send(newPost);

    }catch (err){
        console.error("Error while create a post");
        res.status(500).send(err);
    }
})

 

  • 해결법 2 : if, else if 사용
router.post("/", async (req, res)=>{
    const {title, content} = req.body;

    try{
        if(title.length > 15){
            return res.status(400).send("Title must be under 15 characters.");
        }else if(content.length > 1000){
            return res.status(400).send("Content must be under 1000 characters.");
        }

        const newPost = await sequelize.transaction(async ()=>{
            const post = await Post.create({
                title,
                content
            });
            return post;
        })
        res.status(200).send(newPost);

    }catch (err){
        console.error("Error while create a post");
        res.status(500).send(err);
    }
})

Post 는 해당 pk 로 전부 지워지는데 comment는 postId 부분만 지워진다.

 

>> 지우는 순서의 문제다!!

router.delete('/:id', async (req, res) => {
    const id = req.params.id;
    await sequelize.transaction(async ()=>{
        
        await Post.destroy({where: {id: id}}); // 1
        await Comment.destroy({where: {postId: id}}); // 2
    })
    res.status(204).send();
})

여기서 1 이 지워지면  Comment에 있는 postId가 어디를 참조 하고 있는지 몰라서 NULL로 바뀌고

2 의 코드에서 지워야할 포스트를 찾을 수가 없으므로 코멘트가 지워지지 않는다.

 

!! 각 모델에서 foreignKey가 어떤 모델과 관계가 있는 지 꼭 확인을 하고 지우는 순서를 고려해야 한다.

router.delete('/:id', async (req, res) => {
    const id = req.params.id;
    await sequelize.transaction(async ()=>{
        await Comment.destroy({where: {postId: id}}); // 1
        await Post.destroy({where: {id: id}}); // 2
        
    })
    res.status(204).send();
})
.../routers/posts.js:65
allPosts.sort(sortDateDescending);
TypeError: allPosts.sort is not a function

이유가 뭐지?? allPosts가 array가 아닌가?? -> console 로 출력 해보자

 

<시도>

const allPosts = Post.findAll();
console.log(allPosts);
console.log(Array.isArray(allPosts);

 

<결과>

// console.log(allPosts)의 출력 결과
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 1230,
  [Symbol(trigger_async_id_symbol)]: 1222
}

// console.log(Array.isArray(allPosts))의 출력 결과
false

TypeError: allPosts.sort is not a function

 

>>  첫번째 출력은 뭔지 모르겠으나, Array 형식이 아니라고 하여 형식을 변환 후 출력

const allPosts = Post.findAll();
const allPostsArray = Array.from(allPosts)

console.log(allPostsArray);  // 출력 : []
console.log(Array.isArray(allPostsArray));// 출력: true

 

<< 코드는 정상적으로 작동하는데 받아오는 값이 없다>>

  1. Sequelize 에서 findAll 조사 : https://sequelize.org/api/v6/class/src/model.js~model#static-method-findAll.

..... 문제는 단순했다...   await 를 쓰지 않은 상태에서  array 형태로 변형 시켜서 allPosts 에 아무런 값이 담기지 않았다.

//const allPosts = Post.findAll(); 
const allPosts = await Post.findAll();
 

+ Recent posts