본문 바로가기
ALV · 화면 · 리포트

[SAP ABAP] Module Pool 입력값 유효성 체크 — FIELD·CHAIN·ON REQUEST 차이 (PAI)

by Song.sh 2026. 5. 19.

Module Pool 화면에서 입력 값을 검증할 때 가장 흔하게 쓰는 자리가 PAI(Process After Input) 입니다. PAI 안에 FIELD ... MODULE · CHAIN ... ENDCHAIN 같은 키워드와 ON REQUEST · ON INPUT · ON CHAIN-REQUEST 같은 부가 옵션을 조합하면, 어떤 필드를 언제 검증할지 화면 단위에서 세밀하게 제어할 수 있습니다.

 

문제는 이 4가지 옵션이 동작 시점과 커서 이동 방식이 서로 다르다는 점입니다. 똑같이 검증 모듈을 호출하는 것 같아도, 사용자가 값을 입력한 직후마다 호출되는지 / 값이 바뀐 경우에만 호출되는지 / 여러 필드를 묶어 한 번에 평가하는지에 따라 사용자 경험과 성능이 크게 달라집니다.

 

이 글은 Module Pool 의 PAI 영역에서 자주 쓰이는 검증 4가지 방식 — 단일 필드(FIELD), 입력 시(ON INPUT), 변경 시(ON REQUEST), 묶음 체크(CHAIN) 을 한 화면에 모아 정리한 실무 메모입니다. 메시지 출력 시 커서가 어디로 돌아가는지까지 같이 본문에 적어 두었습니다.


핵심 — 검증 4가지 한눈 비교

검증 4가지는 "언제 호출되는가" 와 "에러 시 어떤 필드에 커서가 머무는가" 두 축으로 나뉩니다.

키워드 호출 시점 에러 시 커서
FIELD f MODULE m PAI 가 흐를 때마다 항상 호출 해당 단일 필드
... ON INPUT 필드가 초기값이 아닐 때 만 호출 해당 단일 필드
... ON REQUEST 사용자가 값을 변경 한 경우에만 호출 해당 단일 필드
CHAIN ... ENDCHAIN 묶은 필드 중 하나라도 입력/변경 시 호출 CHAIN 안 모든 필드 입력 가능 상태

핵심 한 줄: FIELD 는 단일 필드 체크, CHAIN 은 묶음 체크. 두 키워드 모두 ON REQUEST · ON INPUT 로 호출 조건을 좁힐 수 있고, 에러 메시지 출력 시 커서가 머무는 범위는 FIELD = 단일, CHAIN = 묶음 전체입니다.


1단계 — 가장 기본: FIELD ... MODULE 으로 단일 필드 체크

화면에 입력 필드 하나(예: 자재번호) 가 있고, 사용자가 PAI 흐름이 발생할 때마다 그 필드를 항상 검증하고 싶을 때 가장 단순한 형태입니다.

 

* === Flow Logic (PAI) ===
PROCESS AFTER INPUT.
  FIELD gv_matnr MODULE check_matnr.
* === Module Pool 코드 ===
MODULE check_matnr INPUT.
  IF gv_matnr IS INITIAL.
    MESSAGE '자재번호를 입력하세요.' TYPE 'E'.
  ENDIF.

  SELECT SINGLE matnr FROM mara
    INTO @DATA(lv_matnr)
    WHERE matnr = @gv_matnr.
  IF sy-subrc <> 0.
    MESSAGE '존재하지 않는 자재번호입니다.' TYPE 'E'.
  ENDIF.
ENDMODULE.

PAI 가 흐르는 모든 경로(엔터·실행·메뉴 클릭 등) 에서 check_matnr 가 호출됩니다. 에러 메시지가 발생하면 시스템이 자동으로 그 필드만 입력 가능 상태로 되돌리고 나머지는 잠가둡니다. 사용자는 다른 필드를 못 건드리고 원인 필드만 고치게 되는 구조입니다.

이 패턴이 가장 안전하지만, 사용자가 매번 화면을 누를 때마다 검증이 흐르므로 SELECT 가 들어간 무거운 검증 은 후술할 ON REQUEST 와 결합해 호출 횟수를 줄이는 것이 좋습니다.


2단계 — 입력했을 때만: ON INPUT

사용자가 값을 한 번이라도 채운 경우에만 검증하고 싶을 때 사용합니다. 필드가 초기값(빈 값 또는 ABAP 초기값) 상태면 모듈이 호출되지 않습니다.

PROCESS AFTER INPUT.
  FIELD gv_werks MODULE check_werks ON INPUT.
MODULE check_werks INPUT.
  SELECT SINGLE werks FROM t001w
    INTO @DATA(lv_werks)
    WHERE werks = @gv_werks.
  IF sy-subrc <> 0.
    MESSAGE |플랜트 { gv_werks } 가 존재하지 않습니다.| TYPE 'E'.
  ENDIF.
ENDMODULE.

플랜트 필드가 선택 사항인 화면에서 자주 쓰는 패턴입니다. 비워둔 채로 다음 단계로 넘어가는 시나리오는 그대로 허용하면서, 사용자가 입력한 경우에만 존재 여부를 체크합니다.

주의: "초기값이 아닌가" 의 판정은 ABAP 의 IS INITIAL 과 같은 의미입니다. 화면 사전(Dynpro) 에 DEFAULT 값 을 박아둔 필드는 사용자가 손대지 않아도 초기값이 아닐 수 있으므로, 이 경우 ON INPUT 이 첫 PAI 부터 호출됩니다.


3단계 — 값이 바뀐 경우만: ON REQUEST

화면이 PBO 단계에서 보여준 값과 사용자가 PAI 시점에 가지고 있는 값이 다를 때만 검증을 흘리는 옵션입니다. 같은 필드를 사용자가 그대로 두면 모듈이 호출되지 않습니다.

 

PROCESS AFTER INPUT.
  FIELD gv_lifnr MODULE check_lifnr ON REQUEST.
MODULE check_lifnr INPUT.
  SELECT SINGLE lifnr FROM lfa1
    INTO @DATA(lv_lifnr)
    WHERE lifnr = @gv_lifnr.
  IF sy-subrc <> 0.
    MESSAGE |거래처 { gv_lifnr } 는 존재하지 않습니다.| TYPE 'E'.
  ENDIF.
ENDMODULE.

화면이 다시 그려질 때마다 DB 를 다시 조회하는 부담을 줄여 줍니다. 사용자가 거래처 코드를 입력하지 않거나 이전 값 그대로 두면 LFA1 조회를 건너뛰고, 코드를 새로 입력하거나 바꾼 경우에만 DB 조회가 흐릅니다.

ON INPUTON REQUEST 의 차이는 자주 헷갈리는 부분이라 표로 정리합니다.

옵션 호출 조건 자주 쓰는 곳
ON INPUT 현재 값이 초기값이 아니면 호출 선택 입력 필드의 존재 여부 검증
ON REQUEST PBO 가 보여준 값과 다르면 호출 (사용자가 손댄 경우) DB 조회·외부 호출이 들어간 무거운 검증

4단계 — 여러 필드 묶어 체크: CHAIN ... ENDCHAIN

두 개 이상 필드의 조합으로만 검증할 수 있는 시나리오 — 예를 들어 "회사코드 + 거래처" 조합으로 LFB1 을 조회하거나, 시작일과 종료일을 비교하는 등 — 에는 CHAIN ... ENDCHAIN 으로 묶습니다.

 

PROCESS AFTER INPUT.
  CHAIN.
    FIELD gv_bukrs.
    FIELD gv_lifnr.
    MODULE check_lfb1.
  ENDCHAIN.
MODULE check_lfb1 INPUT.
  SELECT SINGLE bukrs FROM lfb1
    INTO @DATA(lv_bukrs)
    WHERE bukrs = @gv_bukrs
      AND lifnr = @gv_lifnr.
  IF sy-subrc <> 0.
    MESSAGE |해당 회사코드/거래처 조합이 LFB1 에 없습니다.| TYPE 'E'.
  ENDIF.
ENDMODULE.

CHAIN 의 핵심 효과는 에러 메시지 출력 시 묶인 필드 전부가 입력 가능 상태로 풀린다 는 점입니다. 사용자가 두 필드 모두 다시 확인하고 수정할 수 있습니다. 만약 FIELD 한 줄로만 작성하면 에러 발생한 한 필드만 풀리고 나머지는 잠깁니다.


5단계 — CHAIN + ON CHAIN-REQUEST 결합

CHAIN 에도 ON CHAIN-REQUEST 옵션이 있습니다. 묶인 필드 중 어느 하나라도 값이 변경된 경우에만 모듈을 호출합니다. CHAIN 의 ON CHAIN-INPUT 은 묶음 중 하나라도 초기값이 아닌 경우 호출입니다.

PROCESS AFTER INPUT.
  CHAIN.
    FIELD gv_datum_von.
    FIELD gv_datum_bis.
    MODULE check_period ON CHAIN-REQUEST.
  ENDCHAIN.
MODULE check_period INPUT.
  IF gv_datum_von IS INITIAL OR gv_datum_bis IS INITIAL.
    MESSAGE '시작일과 종료일을 모두 입력하세요.' TYPE 'E'.
  ENDIF.
  IF gv_datum_von > gv_datum_bis.
    MESSAGE '시작일이 종료일보다 클 수 없습니다.' TYPE 'E'.
  ENDIF.
ENDMODULE.

기간 입력처럼 두 필드의 관계를 비교하는 검증에서 자주 쓰는 패턴. 시작일·종료일 어느 한쪽이라도 사용자가 바꾸면 재검증이 흐릅니다.


6단계 — 오류 메시지와 커서 동작

PAI 검증 모듈 안에서 MESSAGE ... TYPE 'E' 를 호출하면 화면은 즉시 멈추고 사용자에게 메시지가 표시됩니다. 이때 어떤 필드에 커서가 머무는지가 검증 패턴마다 다릅니다.

검증 형태 에러 후 입력 가능 필드
FIELD f MODULE m f 하나만 풀림 / 나머지는 잠김
CHAIN ... ENDCHAIN CHAIN 안 모든 필드 풀림
메시지 타입 W (경고) 사용자가 엔터로 무시 가능 / 검증 통과로 흐름 계속

이 동작이 자동으로 제공되기 때문에, 검증 모듈 안에서 명시적으로 커서를 옮길 필요는 없습니다. 다만 특정 필드로 커서를 강제로 보내고 싶을 때는 SET CURSOR FIELD 'GV_LIFNR'. 한 줄을 메시지 직전에 추가합니다.


전체 코드 — 복사용 통합본

위 4가지 패턴을 한 화면에 모은 PAI 예제. Module Pool 신규 작성 시 그대로 가져다 쓰면 빠릅니다.

* === Flow Logic ===
PROCESS BEFORE OUTPUT.
  MODULE status_0100.

PROCESS AFTER INPUT.
  MODULE exit_command AT EXIT-COMMAND.

  " 1) 항상 체크 — 자재번호 (필수)
  FIELD gv_matnr MODULE check_matnr.

  " 2) 입력했을 때만 — 플랜트 (선택)
  FIELD gv_werks MODULE check_werks ON INPUT.

  " 3) 값이 바뀐 경우만 — 거래처
  FIELD gv_lifnr MODULE check_lifnr ON REQUEST.

  " 4) 묶음 체크 — 회사코드 + 거래처 조합
  CHAIN.
    FIELD gv_bukrs.
    FIELD gv_lifnr.
    MODULE check_lfb1.
  ENDCHAIN.

  " 5) 묶음 체크 + 변경 시만 — 기간
  CHAIN.
    FIELD gv_datum_von.
    FIELD gv_datum_bis.
    MODULE check_period ON CHAIN-REQUEST.
  ENDCHAIN.

  MODULE user_command_0100.
* === 검증 모듈들 ===
MODULE check_matnr INPUT.
  IF gv_matnr IS INITIAL.
    MESSAGE '자재번호를 입력하세요.' TYPE 'E'.
  ENDIF.
ENDMODULE.

MODULE check_werks INPUT.
  SELECT SINGLE werks FROM t001w
    INTO @DATA(lv_w)
    WHERE werks = @gv_werks.
  IF sy-subrc <> 0.
    MESSAGE |플랜트 { gv_werks } 없음.| TYPE 'E'.
  ENDIF.
ENDMODULE.

MODULE check_lifnr INPUT.
  SELECT SINGLE lifnr FROM lfa1
    INTO @DATA(lv_l)
    WHERE lifnr = @gv_lifnr.
  IF sy-subrc <> 0.
    MESSAGE |거래처 { gv_lifnr } 없음.| TYPE 'E'.
  ENDIF.
ENDMODULE.

MODULE check_lfb1 INPUT.
  SELECT SINGLE bukrs FROM lfb1
    INTO @DATA(lv_b)
    WHERE bukrs = @gv_bukrs AND lifnr = @gv_lifnr.
  IF sy-subrc <> 0.
    MESSAGE |해당 회사코드/거래처 조합 없음.| TYPE 'E'.
  ENDIF.
ENDMODULE.

MODULE check_period INPUT.
  IF gv_datum_von > gv_datum_bis.
    MESSAGE '시작일이 종료일보다 큽니다.' TYPE 'E'.
  ENDIF.
ENDMODULE.

흔히 빠뜨리는 함정

FIELD 안 쓰고 모듈만 호출

PROCESS AFTER INPUT.
  MODULE check_matnr.   " ❌ 에러 시 커서 자동 복귀가 안 됨

FIELD f MODULE m 으로 묶지 않고 모듈만 호출하면, 모듈 안에서 에러 메시지를 던져도 시스템이 어느 필드를 풀어줘야 할지 모릅니다. 결과적으로 사용자는 모든 필드가 잠긴 채 메시지만 보게 됩니다. 검증 모듈은 반드시 FIELD 또는 CHAIN 으로 감싸기.

CHAIN 안 여러 FIELD 가 다른 모듈 호출

CHAIN.
  FIELD gv_a MODULE check_a.   " ❌ 의도와 다를 수 있음
  FIELD gv_b MODULE check_b.
ENDCHAIN.

CHAIN 안에서 각 FIELD 에 모듈을 따로 붙이면 묶음 효과(에러 시 모든 필드 풀림) 는 그대로지만, 모듈은 각자 호출됩니다. 묶음 검증을 의도했다면 모듈을 CHAIN 맨 끝에 한 번만 두는 형태가 명확합니다.

ON REQUEST 만 믿고 필수 입력 검사 누락

ON REQUEST 는 값이 변경된 경우에만 호출되기 때문에, 사용자가 처음부터 빈 값으로 두면 모듈이 한 번도 호출되지 않습니다. "필수 입력" 검증은 ON REQUEST 없이 기본 FIELD 로 작성하거나, 화면 사전에서 필드 속성을 Required 로 잡아 두는 것이 안전합니다.

MESSAGE TYPE 'I' 또는 'S' 로 검증

IF gv_matnr IS INITIAL.
  MESSAGE '값을 입력하세요.' TYPE 'I'.   " ❌ 사용자가 무시하고 다음 단계로 감
ENDIF.

검증 모듈에서 메시지 타입 I(Information) 또는 S(Status) 를 사용하면 화면은 멈추지 않고 사용자에게 보여주기만 합니다. 검증은 반드시 E(Error) 또는 A(Abort) 로 던집니다.

Exit-Command 자리 처리 빠뜨림

PROCESS AFTER INPUT.
  FIELD gv_matnr MODULE check_matnr.   " ❌ 사용자가 종료 버튼 눌러도 검증 흐름
  ...

사용자가 화면 종료(F3, F12) 를 눌러도 PAI 가 흐르면서 입력 값 검증이 작동해 화면이 못 빠져나가는 현상이 발생합니다. PAI 첫 줄에 MODULE exit_command AT EXIT-COMMAND. 한 줄을 두고, 안에서 CASE sy-ucomm 으로 종료 키 분기·LEAVE PROGRAM / LEAVE TO SCREEN 0 처리합니다.


요약

단계 키워드 언제 쓰나
1 FIELD f MODULE m PAI 가 흐를 때마다 항상 단일 필드 체크
2 ... ON INPUT 선택 입력 필드 — 사용자가 채운 경우만 체크
3 ... ON REQUEST DB 조회처럼 무거운 검증 — 값이 바뀐 경우만 호출
4 CHAIN ... ENDCHAIN 여러 필드 조합 체크 — 에러 시 묶인 필드 전부 풀림
5 ... ON CHAIN-REQUEST 묶음 체크 + 변경 시만 호출 (기간·범위 검증에 적합)

Module Pool 의 PAI 검증은 결국 "언제 호출할지" 와 "에러 시 어디까지 풀어줄지" 의 조합 게임입니다. 단일 필드는 FIELD, 묶음은 CHAIN 으로 시작하고, DB 조회 같은 무거운 검증은 ON REQUEST · ON CHAIN-REQUEST 로 호출 횟수를 줄이는 패턴이 화면 응답 속도와 사용자 경험을 모두 살립니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.

FIELD · CHAIN · ON INPUT · ON REQUEST · ON CHAIN-REQUEST 는 ABAP / Dynpro 표준 키워드로 시스템 버전 의존 없이 동작합니다. 에러 메시지(TYPE 'E') 발생 시 FIELD 단일은 해당 필드만, CHAIN 은 묶인 필드 전부가 입력 가능 상태로 복귀하는 동작은 SAP GUI Dynpro 의 표준 메커니즘으로, S/4HANA on-premise 환경에서도 그대로 유지됩니다. Fiori / SAPUI5 화면에서는 동일 개념을 컨트롤러의 validate 콜백·FormElement.setError() 등으로 구현하며, 본문 키워드는 SAP GUI Module Pool 환경에서만 적용됩니다.