프로그래밍 언어/NODE JS

쿼리 알아보기

· 코딩마이데이

시퀄라이즈로 CRUD 작업을 하려면 먼저 시퀄라이즈 쿼리를 알아야 합니다. SQL문을 자바스크립트로 생성하는 것이라 시퀄라이즈만의 방식이 있습니다. 쿼리는 프로미스를 반환하므로 then을 붙여 결괏값을 받을 수 있습니다. async/await 문법과 같이 사용할 수도 있습니다.

로우를 생성하는 쿼리부터 알아보겠습니다. 첫 줄이 SQL문이고, 그 아래는 시퀄라이즈 쿼리입니다.

INSERT INTO nodejs.users (name, age, married, comment) VALUES ('zero', 24, 0, '자기소개1');
const { User } = require('../models');
User.create({
  name: 'zero',
  age: 24,
  married: false,
  comment: '자기소개1',
});

 

models 모듈에서 User 모델을 불러와 create 메서드를 사용하면 됩니다. 앞으로 나오는 모든 메서드는 User 모델을 불러왔다는 전제하에 소개합니다.

한 가지 주의할 점은 데이터를 넣을 때 MySQL의 자료형이 아니라 시퀄라이즈 모델에 정의한 자료형대로 넣어야 한다는 것입니다. 이것이 married가 0이 아니라 false인 이유입니다. 시퀄라이즈가 알아서 MySQL 자료형으로 바꿉니다. 자료형이나 옵션에 부합하지 않는 데이터를 넣었을 때는 시퀄라이즈가 에러를 발생시킵니다.

 

이번에는 로우를 조회하는 쿼리들입니다.

다음은 users 테이블의 모든 데이터를 조회하는 SQL문입니다. findAll 메서드를 사용하면 됩니다.

SELECT * FROM nodejs.users;
User.findAll({});

 

다음은 Users 테이블의 데이터 하나만 가져오는 SQL문입니다. 앞으로 데이터를 하나만 가져올 때는 findOne 메서드를, 여러 개 가져올 때는 findAll 메서드를 사용한다고 생각하면 됩니다.

SELECT * FROM nodejs.users LIMIT 1;
User.findOne({});

 

attributes 옵션을 사용해서 원하는 컬럼만 가져올 수도 있습니다.

SELECT name, married FROM nodejs.users;
User.findAll({
  attributes: ['name', 'married'],
});

 

where 옵션이 조건들을 나열하는 옵션입니다.

SELECT name, age FROM nodejs.users WHERE married = 1 AND age > 30;
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
  attributes: ['name', 'age'],
  where: {
    married: true,
    age: { [Op.gt]: 30 },
  },
});

 

MySQL에서는 undefined라는 자료형을 지원하지 않으므로 where 옵션에는 undefined가 들어가면 안 됩니다. 빈 값을 넣고자 하면 null을 대신 사용하세요.

 

age 부분이 조금 특이한데요. 시퀄라이즈는 자바스크립트 객체를 사용해서 쿼리를 생성해야 하므로 Op.gt 같은 특수한 연산자들이 사용됩니다. Sequelize 객체 내부의 Op 객체를 불러와 사용합니다. { [Op.gt]: 30 }은 ES2015 문법이니 2.1.3절을 참고하길 바랍니다.

자주 쓰이는 연산자로는 Op.gt(초과), Op.gte(이상), Op.lt(미만), Op.lte(이하), Op.ne(같지 않음), Op.or(또는), Op.in(배열 요소 중 하나), Op.notIn(배열 요소와 모두 다름) 등이 있습니다.

Op.or를 한번 사용해봅시다.

SELECT id, name FROM users WHERE married = 0 OR age > 30;
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
  attributes: ['id', 'name'],
  where: {
    [Op.or]: [{ married: false0 }, { age: { [Op.gt]: 30 } }],
  },
});

 

 

Op.or 속성에 OR 연산을 적용할 쿼리들을 배열로 나열하면 됩니다.

SELECT id, name FROM users ORDER BY age DESC;
User.findAll({
  attributes: ['id', 'name'],
  order: [['age', 'DESC']],
});

 

시퀄라이즈의 정렬 방식입니다. order 옵션으로 가능합니다. 배열 안에 배열이 있다는 점에 주의하세요. 정렬은 꼭 컬럼 하나로만 하는 게 아니라 컬럼 두 개 이상으로 할 수도 있기 때문입니다.

다음은 조회할 로우 개수를 설정하는 방법입니다. LIMIT 1인 경우에는 findAll 대신 findOne 메서드를 사용해도 되지만, 다음과 같이 limit 옵션으로 할 수도 있습니다.

SELECT id, name FROM users ORDER BY age DESC LIMIT1;
User.findAll({
  attributes: ['id', 'name'],
  order: [['age', 'DESC']],
  limit: 1,
});

 

limit 옵션으로 가능합니다. OFFSET도 역시 offset 속성으로 구현할 수 있습니다.

SELECT id, name FROM users ORDER BY age DESC LIMIT 1 OFFSET 1;
User.findAll({
  attributes: ['id', 'name'],
  order: ['age', 'DESC'],
  limit: 1,
  offset: 1,
});

 

이번에는 로우를 수정하는 쿼리입니다.

UPDATE nodejs.users SET comment = '바꿀 내용' WHERE id = 2;
User.update({
  comment: '바꿀 내용',
}, {
  where: { id: 2 },
});

 

update 메서드로 수정할 수 있습니다. 첫 번째 인수는 수정할 내용이고, 두 번째 인수는 어떤 로우를 수정할지에 대한 조건입니다. where 옵션에 조건들을 적습니다.

로우를 삭제하는 쿼리는 다음과 같습니다.

DELETE FROM nodejs.users WHERE id = 2;
User.destory({
  where: { id: 2 },
});

 

destroy 메서드로 삭제합니다. where 옵션에 조건들을 적습니다.

 

관계 쿼리

findOne이나 findAll 메서드를 호출할 때 프로미스의 결과로 모델을 반환합니다(findAll은 모두 찾는 것이므로 모델의 배열을 반환합니다).

const user = await User.findOne({});
console.log(user.nick); // 사용자 닉네임

 

User 모델의 정보에도 바로 접근할 수 있지만, 더 편리한 점은 관계 쿼리를 지원한다는 것입니다. MySQL로 따지면 JOIN 기능입니다. 현재 User 모델은 Comment 모델과 hasMany-belongsTo 관계가 맺어져 있습니다. 만약 특정 사용자를 가져오면서 그 사람의 댓글까지 모두 가져오고 싶다면 include 속성을 사용합니다.

const user = await User.findOne({
  include: [{
    model: Comment,
  }]
});
console.log(user.Comments); // 사용자 댓글

 

어떤 모델과 관계가 있는지를 include 배열에 넣어주면 됩니다. 배열인 이유는 다양한 모델과 관계가 있을 수 있기 때문입니다. 댓글은 여러 개일 수 있으므로(hasMany) user.Comments로 접근 가능합니다. 또는 다음과 같이 댓글에 접근할 수도 있습니다.

const user = await User.findOne({});
const comments = await user.getComments();
console.log(comments); // 사용자 댓글

 

관계를 설정했다면 getComments(조회) 외에도 setComments(수정), addComment(하나 생성), addComments(여러 개 생성), removeComments(삭제) 메서드를 지원합니다. 동사 뒤에 모델의 이름이 붙는 형식입니다.

동사 뒤의 모델 이름을 바꾸고 싶다면 관계를 설정할 때 as 옵션을 사용할 수 있습니다.

// 관계 설정할 때 as로 등록
db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id', as: 'Answers' });
// 쿼리할 때는
const user = await User.findOne({});
const comments = await user.getAnswers();
console.log(comments); // 사용자 댓글

 

as를 설정하면 include할 때 추가되는 댓글 객체도 user.Answers로 바뀝니다.

include나 관계 쿼리 메서드에도 where이나 attributes 같은 옵션을 사용할 수 있습니다.

const user = await User.findOne({
  include: [{
    model: Comment,
    where: {
      id: 1,
    },
    attributes: ['id'],
  }]
});
// 또는
const comments = await user.getComments({
  where: {
    id: 1,
  },
  attributes: ['id'],
});

 

댓글을 가져올 때는 id가 1인 댓글만 가져오고, 컬럼도 id 컬럼만 가져오도록 하고 있습니다.

관계 쿼리 시 조회는 위와 같이 하지만 수정, 생성, 삭제 때는 조금 다른 점이 있습니다.

const user = await User.findOne({});
const comment = await Comment.create(); 
await user.addComment(comment);
// 또는
await user.addComment(comment.id);

 

여러 개를 추가할 때는 배열로 추가할 수 있습니다.

const user = await User.findOne({});
const comment1 = await Comment.create();
const comment2 = await Comment.create();
await user.addComment([comment1, comment2]);

 

관계 쿼리 메서드의 인수로 추가할 댓글 모델을 넣거나 댓글의 아이디를 넣으면 됩니다. 수정이나 삭제도 마찬가지입니다.

 

SQL 쿼리하기

만약 시퀄라이즈의 쿼리를 사용하기 싫거나 어떻게 해야 할지 모르겠다면 직접 SQL문을 통해 쿼리할 수도 있습니다.

const [result, metadata] = await sequelize.query('SELECT * from comments');
console.log(result);

 

웬만하면 시퀄라이즈의 쿼리를 사용하는 것을 추천하지만, 시퀄라이즈 쿼리로 할 수 없는 경우에는 위와 같이 하면 됩니다.

'프로그래밍 언어 > NODE JS' 카테고리의 다른 글

몽고디비 & NoSQL vs. SQL  (0) 2025.09.11
쿼리 수행하기  (0) 2025.09.08
관계 정의하기  (1) 2025.08.30
모델 정의하기  (1) 2025.08.27
MySQL 연결하기  (0) 2025.08.24