방금 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;
이 방식이 가장 안정적이고 실무에서도 표준입니다.
'mariaDB > 3. SQL 사용법' 카테고리의 다른 글
| 도서구매사이트 - 주문목록 조회 (0) | 2025.05.24 |
|---|---|
| mysql. 연결 생성 방식=> createConnection() vs createPool() 차이점 (0) | 2025.05.21 |
| 도서구매사이트 - 주문 API 작성 시 코드 리팩토링 (0) | 2025.05.21 |
| IN (?, ?, ?) 문법 (0) | 2025.05.20 |
| EXISTS 문법 (0) | 2025.05.19 |