SAP 잠금 객체(Lock Object)란 - 왜 필요하고 언제 어떻게 쓰나

SAP 잠금 객체 배너

왜 DB 잠금만으로는 부족한가

두 사용자가 같은 주문을 동시에 열어 수정하는 상황을 생각해 봅시다. 데이터베이스에도 잠금이 있는데 왜 SAP는 잠금 장치를 따로 둘까요.

이유는 SAP가 일을 처리하는 단위와 데이터베이스가 일을 처리하는 단위가 다르기 때문입니다.

DB 트랜잭션화면 하나를 넘기면 끝난다

SAP는 화면을 넘길 때마다 데이터베이스 작업을 마무리합니다. 사용자가 화면을 보고 있는 동안에는 DB 잠금이 이미 풀려 있습니다.

SAP LUW여러 화면에 걸쳐 이어진다

업무 하나는 조회 → 수정 → 저장처럼 여러 화면에 걸쳐 진행됩니다. 이 긴 구간을 지켜 줄 별도의 잠금이 필요합니다.

그래서 SAP는 SAP LUW 동안 유지되는 자체 잠금을 제공합니다. 전용 서버(Enqueue Server)가 잠금 목록을 들고 있고, ABAP 프로그램은 거기에 "이 주문은 제가 씁니다"라고 등록해 두는 방식입니다.

가장 중요한 성질 - 강제가 아니라 약속이다

이 글에서 꼭 기억해야 할 한 가지입니다.

WARNING

SAP 잠금은 데이터베이스가 막아 주는 것이 아닙니다. 잠금을 걸어도 그 테이블에 그냥 UPDATE를 날리는 다른 프로그램은 성공합니다. 모든 프로그램이 같은 잠금 객체를 호출해 확인할 때만, 비로소 의미가 생기는 논리적 잠금입니다.

그래서 잠금 객체를 새로 만들었다면, 그 데이터를 건드리는 모든 경로(온라인 프로그램, 배치, 인터페이스, BAPI 호출)가 같은 잠금을 걸도록 맞추는 일이 설계의 핵심입니다. 한 군데라도 빠지면 잠금은 있으나 마나입니다.

SE11에서 잠금 객체 만들기

잠금 객체는 ABAP 사전(SE11)에서 만듭니다.

STEP 1SE11 · 잠금 객체EZ_SORDER
→
STEP 2테이블·잠금 인수기본 테이블과 키 필드
→
STEP 3활성화함수 2개 자동 생성

정해진 규칙이 몇 가지 있습니다.

  • 이름은 EZ 또는 EY로 시작합니다. 고객 네임스페이스 규칙입니다.
  • 기본 테이블과 잠금 인수(lock argument) 로 쓸 필드를 지정합니다. 보통 키 필드를 씁니다.
  • 활성화하면 함수 모듈 두 개가 자동으로 생성됩니다.
생성되는 함수역할
ENQUEUE_EZ_SORDER잠금을 건다
DEQUEUE_EZ_SORDER잠금을 푼다

잠금 인수를 어디까지 넣느냐가 잠금의 범위를 결정합니다. 주문번호만 넣으면 주문 단위로 잠그고, 주문번호와 품목번호를 함께 넣으면 품목 단위로 잠급니다. 범위가 넓으면 안전하지만 동시 작업이 막히고, 좁으면 동시성은 좋지만 설계가 까다로워집니다.

잠금 모드 네 가지

모드이름성격
S공유(Shared)여러 사용자가 동시에 걸 수 있다. 읽는 동안 남이 바꾸지 못하게 할 때
E배타(Exclusive)한 사람만. 같은 소유자는 중첩해서 걸 수 있다(누적)
X배타·비누적한 사람만. 같은 소유자라도 두 번 걸면 실패
O낙관(Optimistic)처음에는 읽기 잠금처럼 동작하다가, 저장 시점에 배타로 승격

실무에서 대부분은 E를 씁니다. S는 조회 중 변경 방지, O는 편집 화면을 오래 띄워 두는 경우에 씁니다.

INFO

E와 X의 차이가 헷갈리기 쉽습니다. 같은 프로그램에서 같은 잠금을 두 번 거는 상황(예: 공통 모듈이 안쪽에서 또 잠금)이 생길 수 있는데, E는 허용되고 X는 실패합니다. 중복 호출 자체를 막고 싶을 때 X를 씁니다.

기본 사용 흐름

1" 1. 잠금
2CALL FUNCTION 'ENQUEUE_EZ_SORDER'
3  EXPORTING
4    mode_zsorder = 'E'
5    vbeln        = lv_vbeln
6  EXCEPTIONS
7    foreign_lock   = 1
8    system_failure = 2
9    OTHERS         = 3.
10
11IF sy-subrc <> 0.
12  " sy-msgv1 에 이미 잠그고 있는 사용자 ID가 담긴다
13  MESSAGE e001(zorder) WITH lv_vbeln sy-msgv1.
14ENDIF.
15
16" 2. 데이터 변경
17UPDATE zsorder SET status = 'C' WHERE vbeln = @lv_vbeln.
18
19" 3. 저장
20COMMIT WORK.
21
22" 4. 해제 (기본 설정에서는 COMMIT 시 함께 풀린다)
23CALL FUNCTION 'DEQUEUE_EZ_SORDER'
24  EXPORTING
25    mode_zsorder = 'E'
26    vbeln        = lv_vbeln.
TIP

잠금에 실패하면 sy-msgv1에 이미 잠그고 있는 사용자 ID가 들어옵니다. "다른 사용자가 사용 중입니다"로 끝내지 말고 누가 쓰고 있는지 메시지에 보여주면, 문의가 확 줄어듭니다.

상황별로 어떤 방식을 쓸까

저장만 짧게 하는 경우 (권장 기본형)

✓권장저장 직전에 걸고 바로 푼다

사용자가 입력하는 동안은 잠그지 않고, 저장 버튼을 누른 뒤에만 잠금 → 검증 → 변경 → COMMIT WORK 순서로 처리합니다. 잠겨 있는 시간이 1초 미만이라 충돌이 거의 없습니다.

!주의먼저 읽은 값이 그 사이 바뀔 수 있다

화면을 띄운 뒤 저장까지 사이에 남이 바꿨을 수 있습니다. 잠근 직후 데이터를 다시 읽어 변경 여부를 확인하는 절차가 필요합니다.

편집 화면을 오래 띄워 두는 경우

사용자가 수정 화면을 열어 둔 내내 잠가 두고 싶을 때가 있습니다. 선택지는 둘입니다.

방식동작단점
E 모드로 계속 유지화면을 여는 순간 배타 잠금사용자가 창을 띄워 둔 채 자리를 비우면 아무도 못 씀
O 모드(낙관)열 때는 서로 충돌하지 않고, 저장 시점에 배타로 승격저장할 때 승격이 실패할 수 있어 그 처리를 만들어야 함

여러 사람이 같은 데이터를 자주 보는 업무라면 O 모드가 현실적입니다. 승격 방법은 ENQUEUE·DEQUEUE 상세 글에서 코드로 다룹니다.

배치·인터페이스에서 처리하는 경우

  • 온라인 사용자가 쓰는 데이터를 배치가 건드린다면 배치도 같은 잠금을 걸어야 합니다.
  • 잠겨 있을 때 기다릴지 건너뛸지를 정해야 합니다. 대량 처리에서는 건너뛰고 로그에 남긴 뒤 나중에 재처리하는 쪽이 안전합니다.

SM12로 확인하기

현재 걸려 있는 잠금은 트랜잭션 SM12 에서 봅니다. 사용자, 잠금 객체, 잠금 인수, 모드가 나옵니다.

  • "저장이 안 된다"는 문의가 오면 여기서 누가 잡고 있는지 바로 확인할 수 있습니다.
  • 비정상 종료로 남은 잠금도 여기서 보입니다.
WARNING

SM12에서 잠금을 강제로 지우는 것은 매우 조심해야 합니다. 실제로 작업 중인 사용자의 잠금을 지우면 데이터가 깨질 수 있습니다. 운영에서는 담당자 확인 후 처리하세요.

자주 하는 실수

!실수키를 안 넘겨 전부 잠근다

잠금 인수를 비우고 호출하면 조건에 해당하는 전체가 잠깁니다. 변수가 빈 채로 호출돼 업무 전체가 멈추는 사고가 실제로 납니다.

!실수오류 처리를 건너뛴다

sy-subrc를 확인하지 않으면 잠기지 않았는데도 그대로 진행합니다. 잠금을 건 의미가 사라집니다.

여기에 더해 자주 보이는 것들입니다.

  • 잠금을 풀지 않고 끝내기 — 기본 설정에서는 COMMIT WORK 때 풀리지만, 설정에 따라 남을 수 있습니다.
  • 잠금 범위를 너무 넓게 잡기 — 품목만 바꾸면 되는데 전표 전체를 잠가 동시 작업이 막힙니다.
  • 일부 경로에만 적용 — 온라인에만 걸고 인터페이스는 빼먹으면 잠금이 무력화됩니다.

정리

  • SAP 잠금은 여러 화면에 걸친 업무 단위(SAP LUW)를 보호하기 위한 장치입니다.
  • 강제가 아니라 약속입니다. 데이터를 건드리는 모든 경로가 같은 잠금을 걸어야 합니다.
  • 잠금 객체는 SE11에서 EZ/EY로 만들고, 활성화하면 ENQUEUE_/DEQUEUE_ 함수가 생깁니다.
  • 모드는 S·E·X·O 네 가지이고, 기본은 E입니다.
  • 가능하면 저장 직전에 짧게 잠그는 방식을 기본으로 삼으세요.

다음 글에서는 함수의 파라미터와 _SCOPE, 낙관적 잠금 승격, 그리고 웹 환경에서 잠금이 유지되지 않는 문제를 다룹니다.

INFO

트랜잭션 코드와 화면 구성, 파라미터 기본값은 릴리스에 따라 다를 수 있습니다. 실제 시스템에서 확인하세요.

Disclaimer — 이 포스트는 AI(Claude)를 활용하여 작성된 초안을 바탕으로 검수 및 보완하여 작성되었습니다. 내용 중 오류나 오타가 있다면 댓글로 알려주시면 감사하겠습니다.