mariaDB/3. SQL 사용법

방금 테이블에 INSERT한 row의 ID를 가져오기

bbomkim 2025. 5. 21. 21:45

방금 INSERT한 행의 ID를 가져오는 방법은 대표적으로 두 가지가 있습니다:


1. result.insertId 방식

사용 예시

const [result] = await conn.query(
  `INSERT INTO orders (user_id, adress, receiver, totalPrice) VALUES (?, ?, ?, ?)`,
  [user_id, adress, receiver, 0]
);
const order_id = result.insertId;

특징

  • 가장 안전하고 정확한 방식
  • DB 드라이버(mysql2, mysql, Sequelize 등)가 INSERT 후 반환해줌
  • 다른 사용자가 같은 테이블에 INSERT를 하더라도 전혀 영향을 받지 않음
  • 단일 트랜잭션 내에서 현재 내가 삽입한 row의 ID를 확실히 얻음

 


2. SELECT MAX(id) 방식

사용 예시

const [rows] = await conn.query(`SELECT MAX(id) AS max_id FROM orders`);
const order_id = rows[0].max_id;

특징

  • 단순하게 테이블의 가장 마지막 ID를 가져오는 방식
  • 여러 사용자가 동시에 INSERT를 하고 있는 경우, 내가 넣은 row의 ID가 아닐 수 있음
  • 특히 다중 사용자, 병렬 요청 환경에서는 위험 (경쟁 상태 발생 가능)

비교 정리

항목  insertId  SELECT MAX(id)
신뢰성 매우 높음 낮음 (동시성 문제 발생 가능)
속도 빠름 약간 느림 (SELECT 쿼리 1번 더 필요)
사용 조건 INSERT 직후 테이블 전체 상태 기반
안전한 트랜잭션 가능 위험 (다른 사용자의 데이터 섞일 수 있음)
실무 사용 표준 방식 테스트나 로컬에서만 제한적으로 사용

실제로 어떤 문제가 생길 수 있나?

예를 들어 두 사용자가 동시에 주문을 요청한다고 가정하면:

  • A가 INSERT 하고 SELECT MAX(id)를 하는 동안
  • B가 먼저 INSERT 해서 id=101을 차지하고
  • A는 자기 주문의 ID가 100인데 잘못해서 101을 가져가게 됨

→ A의 주문 상세(order_items)는 B의 주문에 연결되는 심각한 버그가 생김


결론

  • insertId는 DB 드라이버가 내부적으로 LAST_INSERT_ID()를 안전하게 호출해서 반환해주는 값이라 항상 신뢰할 수 있음
  • SELECT MAX(id)는 단일 사용자 환경에선 괜찮지만, 멀티 사용자 웹 서비스에선 절대 사용하면 안 됨

그래서 실무나 교육에서는 항상 다음처럼 사용하는 것을 권장합니다:

const [result] = await conn.query(...);
const order_id = result.insertId;

 

이 방식이 가장 안정적이고 실무에서도 표준입니다.