subindev 개발 블로그

[Oracle] SEQUENCE 는 무엇이며 어떤 상황에서 활용할 수 있는가 ( Insert 이후 Id 값 추출하기 ) 본문

DB , SQL

[Oracle] SEQUENCE 는 무엇이며 어떤 상황에서 활용할 수 있는가 ( Insert 이후 Id 값 추출하기 )

subindev 2025. 12. 11. 16:49

상황 설명

현재 Xamarin Forms 기반의 Calendar Todo 앱을 개발하고 있다.

Todo를 삽입한 직후 곧바로 수정할 수 있는 페이지를 만들던 중 문제를 발견했다.


서버 삽입이 성공하면 서버에서 다시 조회하지 않고, ViewModel에서 바로 추가하는 방식을 사용했는데,
새로 추가된 Todo 항목들이 ID 없이 화면에 표시되면서 문제가 발생한 것이다.

 

ID가 없으면 삭제·수정 기능이 동작하지 않기 때문에 이는 반드시 해결해야 했다.

 

하지만 현재 사용하는 미들 서버 구조상, Insert 후 반환값은 bool(성공 여부) 였다.

이미 만들어진 구조를 변경하기엔 어려움이 있었다.

 

그래서 아래처럼 직접 다음 ID를 조회하고 이를 ID로 설정하여 Insert 하기로 결정하였다.

SELECT TODO_SEQ.NEXTVAL AS ID FROM DUAL

 

 

그러나 이 방식에서 자연스럽게 다음과 같은 의문이 생겼다.

  • 삽입 요청이 여러 번 동시에 들어오면?
  • 사용자가 UI에서 더블 클릭을 하면 거의 동시에 두 Insert가 들어오는데?
  • Race Condition이 발생해 같은 ID가 중복될 가능성은 없을까?
  • 트랜잭션을 직접 처리해야 안전하지 않을까?

즉 Race Condition에 대한 걱정이 들었다


 

✅ 결론부터 말하자면, SEQUENCE는 동시성에서 안전하다

  • 오라클 SEQUENCE를 사용하면 Race Condition은 발생하지 않는다.

 


 

이에 대해 조금 더 알아보자

 

 

1. 오라클 공식 권장 구조: RETURNING INTO

원래 가장 권장되는 Insert 방식은 아래처럼
RETURNING INTO로 Insert와 ID 반환을 한 번에 처리하는 것이다.

INSERT INTO TODOITEMS 
(
    WRITER_ID, TODO_CONTENT, ISDONE,
    DESCRIPTION, START_DATE, PRIORITY,
    CATEGORY, CREATEDAT, ID
)
VALUES
(
    :writerId, :content, :isDone,
    :description, TO_DATE(:startDate, 'YYYY/MM/DD'),
    :priority, :category,
    SYSDATE, TODO_SEQ.NEXTVAL
)
RETURNING ID INTO :newId;

 

하지만 현재 미들 서버 구조가 이를 지원하지 않기 때문에 NEXTVAL을 직접 조회하고 삽입하는 방법을 사용하였다.


2. NEXTVAL 직접 조회 방식은 안전한가?

현재 흐름은 다음과 같다.

  1. SELECT TODO_SEQ.NEXTVAL AS ID FROM DUAL
  2. INSERT INTO TODOITEMS(ID, …)

이 방식에서도 ID 충돌은 발생하지 않는다.
오라클 SEQUENCE는 DB 내부에서 원자적으로 증가하기 때문에
100개의 요청이 동시에 다음 쿼리를 실행해도:

SELECT TODO_SEQ.NEXTVAL FROM DUAL;

오라클은 절대 중복된 값을 반환하지 않는다.

 

다만, NEXTVAL을 SELECT한 후 INSERT가 실패하면 해당 번호는 사라지는 점(번호 구멍 발생)이 있다

 

→ 이는 완전 정상 - ID는 유일성만 보장되면 된다.
→ 반드시 연속일 필요는 없다.

 


정리

 

오라클 SEQUENCE

아래는 SEQUENCE 자체에 대한 정리이다.


1. 목적 (Purpose)

오라클 SEQUENCE는 중복되지 않는 숫자 값을 고속으로 생성하기 위한 객체이며, 주 목적은 다음과 같다.

  • Primary Key 자동 생성
  • 대량 Insert 환경에서 유일한 ID 제공
  • 동시성 환경에서 충돌 없는 고유 값 생성
  • 테이블과 독립된 일련번호 생성

즉, SEQUENCE는 단순 증가값이 아닌
분산·고동시성 환경에서 안전한 고유 ID 생성기이다.


2. 사용 사례 (Use Cases)

 PK 생성

INSERT INTO TODO (ID, CONTENT)
VALUES (TODO_SEQ.NEXTVAL, '내용');

Insert 직후 ID를 받아 사용

INSERT INTO TODO (ID, CONTENT)
VALUES (TODO_SEQ.NEXTVAL, 'test')
RETURNING ID INTO :newId;

여러 테이블에서 하나의 SEQUENCE 공유

로그/이벤트 테이블 등 전역적으로 유일한 번호가 필요할 때

분산·멀티 서버 환경

서버가 여러 대여도 ID 충돌이 절대 발생하지 않음


3. 특징 (Key Characteristics)

1) 락(Lock-Free)

테이블이나 행에 Lock을 걸지 않음
→ 동시성 매우 높음
→ 병목(Blocking) 없음

2) 원자적(Atomic) 연산

  • 값 읽기
  • 증가
  • 증가값 반환

이 3단계를 하나의 원자 작업으로 처리
→ Race Condition 자체가 구조적으로 발생 불가

3) 유일성 보장, 연속성 보장 X

중간 값 건너뛰는(gap) 현상은 정상
중요한 건 중복되지 않는 것

4) 테이블과 독립된 객체

PK 생성용으로 가장 많이 사용되지만,
특정 테이블에 종속적이지 않음

5) 매우 빠른 성능

CPU 기반 increment + 캐시(Cache) 적용
→ 초당 수만 Insert에서도 병목 없음

6) NEXTVAL / CURRVAL 제공

  • NEXTVAL → 새로운 ID 생성
  • CURRVAL → 해당 세션의 마지막 NEXTVAL 값