ALV 리포트를 SE38 이나 T-Code 로 다이얼로그(Dialog) 모드에서 돌릴 때는 잘 동작하다가, 같은 리포트를 백그라운드 잡(BATCH) 으로 SM36 에서 예약·실행하면 갑자기 CNTL_ERROR 또는 CREATE_ERROR 같은 ST22 덤프가 떨어지는 경우가 흔합니다. 원인은 GUI 가 없는 환경에서 Container 객체를 생성하려 했기 때문.
CL_GUI_DOCKING_CONTAINER·CL_GUI_CUSTOM_CONTAINER 같은 GUI 컨테이너는 SAP GUI 가 떠 있는 세션에서만 생성 가능. 배치 잡은 GUI 가 없으므로 Container 생성 자체가 실패합니다. 해결책은 단순 — GUI 모드인지 백그라운드 모드인지 사전에 체크해서 Container 생성을 건너뛰기. 그 체크용 표준 메서드가 CL_GUI_ALV_GRID=>OFFLINE( ).
이 글에서는 백그라운드 ALV 덤프의 원인, OFFLINE( ) 메서드를 활용한 분기 패턴, 그리고 Container 가 NULL 인 채로 ALV Grid 를 만들면 어떻게 백그라운드에서도 SPOOL 출력이 되는지를 단계별로 정리합니다.
핵심 — Dialog vs Background 분기
| 구분 | Dialog (SE38·T-Code) | Background (SM36 배치) |
|---|---|---|
| GUI 존재 | O (SAP GUI 떠 있음) | X (GUI 없음) |
| OFFLINE( ) 결과 | IS INITIAL (TRUE) |
반환값 채워짐 (IS NOT INITIAL) |
| Container 생성 | 정상 (DOCKING/CUSTOM 등) | 생략 (시도하면 덤프) |
| ALV Grid 생성 | i_parent = lo_container |
i_parent = NULL (Container 안 만들었으므로) |
| 출력 결과 | 화면에 ALV Grid | SPOOL 로 출력 (SP01 / SM37 에서 확인) |
핵심은 “Container 만들기 직전에 OFFLINE( ) 체크 한 번”. 동일한 ALV 코드가 Dialog 와 Background 두 환경 모두에서 안전하게 동작하도록 만드는 표준 패턴.
OFFLINE( ) 메서드 — 백그라운드 여부 체크
CL_GUI_ALV_GRID 의 정적 메서드(Static Method) 라 인스턴스 없이 클래스명에서 바로 호출.
" 다이얼로그 환경이면 INITIAL 반환
IF cl_gui_alv_grid=>offline( ) IS INITIAL.
" 사용자가 SE38·T-Code 로 실행한 경우
...
ELSE.
" 백그라운드(BATCH) 잡 또는 RFC 호출 등 GUI 없는 환경
...
ENDIF.
내부적으로는 SY-BATCH 와 GUI 활성 상태를 함께 보는 표준 체크. 직접 IF sy-batch = 'X' 로만 체크하면 “화면이 떴는데 GUI 가 응답 없는” 케이스를 못 잡으므로 OFFLINE( ) 사용이 안전합니다.
단계별 — Container 분기 + ALV Grid 생성
1) 객체 참조 변수 선언
Container 와 Grid 를 한 묶음으로 관리하면 가독성이 좋아집니다.
DATA: BEGIN OF lo_grid,
container TYPE REF TO cl_gui_docking_container,
grid TYPE REF TO cl_gui_alv_grid,
END OF lo_grid.
2) OFFLINE( ) 체크 후 Container 분기 생성
" DIALOG — 직접 REPORT명, T-CODE 를 통한 ALV 실행 시
IF cl_gui_alv_grid=>offline( ) IS INITIAL.
CREATE OBJECT lo_grid-container
EXPORTING
extension = 2500
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_dynpro_dynpro_link = 4
lifetime_error = 5
OTHERS = 6.
" BACKGROUND — BATCH 등 GUI 없는 환경
ELSE.
IF lo_grid-container IS BOUND.
CALL METHOD lo_grid-container->free
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
OTHERS = 3.
CLEAR lo_grid-container.
ENDIF.
ENDIF.
ELSE 분기의 IS BOUND 체크 + FREE 호출은 혹시라도 앞 단계에서 잘못 만들어진 Container 가 남아 있을 경우 정리하는 안전 장치. 보통은 안 만들어졌지만, 같은 변수를 여러 번 재사용하는 흐름에서는 도움.
3) ALV Grid 생성 — Container 가 NULL 이어도 OK
CREATE OBJECT lo_grid-grid
EXPORTING
i_parent = lo_grid-container
EXCEPTIONS
error_cntl_create = 1
error_cntl_init = 2
error_cntl_link = 3
error_dp_create = 4
OTHERS = 5.
핵심 — Background 분기에서 lo_grid-container 는 NULL 인 채로 전달됩니다. CL_GUI_ALV_GRID 는 부모 Container 가 NULL 이면 “Offline 모드로 동작 — Grid 의 결과를 SPOOL 로 출력” 하도록 표준 처리됩니다. 그래서 같은 코드가 Dialog 에서는 화면에, Background 에서는 SPOOL 에 결과가 출력됩니다.
4) SET_TABLE_FOR_FIRST_DISPLAY 는 그대로
CALL METHOD lo_grid-grid->set_table_for_first_display
EXPORTING
is_layout = gs_layout
CHANGING
it_fieldcatalog = gt_fcat
it_outtab = gt_data
it_sort = gt_sort.
ALV 표시 메서드는 환경 관계없이 동일. Background 라면 SAP 가 알아서 SPOOL 출력으로 변환.
SM37 / SP01 에서 결과 확인
백그라운드 잡이 끝난 뒤 결과 확인 경로.
[1] SM37 (Job Overview)
└ 잡 이름 / 사용자 / 기간 등으로 조회 → 잡 더블클릭
[2] Spool 아이콘 클릭 (또는 Job Log → Spool List)
└ Spool Request 번호 확인
[3] SP01 (Spool Request Overview)
└ Spool 번호 더블클릭 → ALV 출력 확인
└ 또는 잡 화면에서 직접 Display → Content 보기
[4] PDF / 엑셀 다운로드 가능
└ SP01 의 Goto → Download → PDF/Excel
Dialog 의 ALV 와 동일한 컬럼·합계 구조로 SPOOL 에 그대로 들어가므로, 사용자에게 일배치 결과를 SPOOL 에서 받게 운영하면 됩니다.
다른 Container 종류에서도 동일
이 패턴은 CL_GUI_DOCKING_CONTAINER 외에 다음에도 똑같이 적용 가능.
| Container 종류 | 백그라운드 처리 |
|---|---|
CL_GUI_DOCKING_CONTAINER |
OFFLINE( ) 분기 — 이 글의 패턴 그대로 |
CL_GUI_CUSTOM_CONTAINER |
동일 — DOCKING 자리에 CUSTOM 만 바꿈 |
CL_GUI_SPLITTER_CONTAINER |
동일 — Splitter 자체도 GUI 의존이라 동일 분기 필요 |
CL_GUI_EASY_SPLITTER_CONTAINER |
동일 |
DOCKING 만 쓰는 ALV 가 가장 흔하지만, SPLITTER 로 2분할/3분할 화면을 만든 리포트도 백그라운드 잡으로 돌리려면 같은 분기가 필요합니다.
CL_SALV_TABLE 의 경우
새 ALV(CL_SALV_TABLE) 는 같은 분기 자체가 필요 없습니다. cl_salv_table=>factory( ) 자체가 Dialog/Background 를 자동 인식해서 동작.
DATA: lo_salv TYPE REF TO cl_salv_table.
cl_salv_table=>factory(
IMPORTING
r_salv_table = lo_salv
CHANGING
t_table = gt_data ).
lo_salv->display( ).
" Dialog 에서는 화면, Background 에서는 SPOOL 로 자동 출력
이 글의 분기 패턴은 CL_GUI_ALV_GRID 같은 전통적 객체 ALV 를 쓸 때 필요한 패턴이고, 신규 개발에서 CL_SALV_TABLE 을 쓰면 이 고민 자체가 없어집니다. 다만 기존 리포트 중 CL_GUI_ALV_GRID 기반이 많아 대부분의 운영 환경에서는 이 패턴이 필수.
자주 빠뜨리는 함정
- OFFLINE( ) 안 하고 sy-batch 만 체크 — sy-batch 만으로는 RFC 호출 같은 GUI 없는 다른 환경을 못 잡음. OFFLINE( ) 이 표준
- Container 생성 EXCEPTIONS 무시 — 6번(OTHERS) 예외도 잡아두면 환경 변경 시 디버깅이 쉬움. 다 OTHERS = 0 으로 막아두지 말 것
- CREATE OBJECT 직전 IS BOUND 체크 안 함 — 같은 PBO 가 여러 번 도는 화면에서 Container 가 이미 생성돼 있으면 새로 생성 시 메모리 누수. IF lo_grid-container IS INITIAL 후 CREATE 안전
- FREE 없이 CLEAR — Container 객체는 그냥 CLEAR 하면 SAP 내부 GUI 핸들이 안 풀려 누수.
->free( )호출 후 CLEAR - SPOOL 출력 길이 제한 — Background 의 SPOOL 은 기본 라인 길이 제한이 있음. 컬럼이 많은 ALV 면 SM37 잡 정의 시 Spool Page Format 을 X_65_255 같은 가로 긴 형식으로 변경
- SET_TABLE_FOR_FIRST_DISPLAY 의 IT_TOOLBAR_EXCLUDING — 배치에서는 어차피 SPOOL 이라 도구 모음이 의미 없지만 코드는 무해. 굳이 빼지 않아도 됨
요약
| 단계 | 코드 | 결과 |
|---|---|---|
| 1 | DATA: BEGIN OF lo_grid, container ..., grid ..., END OF lo_grid. |
참조 변수 묶음 선언 |
| 2 | IF cl_gui_alv_grid=>offline( ) IS INITIAL. |
Dialog/Background 분기 체크 |
| 3-Dialog | CREATE OBJECT lo_grid-container ... |
DOCKING/CUSTOM Container 정상 생성 |
| 3-BG | IF BOUND → free → CLEAR |
Container 생성 X (NULL 유지) |
| 4 | CREATE OBJECT lo_grid-grid EXPORTING i_parent = lo_grid-container |
i_parent 가 NULL 이면 SAP 가 Offline 모드로 자동 처리 |
| 5 | lo_grid-grid->set_table_for_first_display( ... ) |
Dialog → 화면 / Background → SPOOL 출력 |
백그라운드 ALV 덤프 대응의 본질은 “Container 만들기 직전에 OFFLINE( ) 한 번 체크 → Background 면 Container 생성 건너뛰기” 한 줄의 분기. CL_GUI_ALV_GRID 기반 모든 ALV 리포트에 동일 패턴을 적용해 두면 Dialog/Background 두 환경에서 같은 코드가 안전하게 동작하고, SM36 으로 일배치 잡을 돌려도 ST22 에 덤프가 안 쌓입니다.
Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.
CL_GUI_ALV_GRID 의 OFFLINE( ) 메서드 동작과 SPOOL 출력 형식은 NetWeaver 버전(ECC 6.0 / S/4HANA on-premise · Cloud) 에 따라 일부 차이가 있을 수 있으니, 실제 적용 시 SE24 의 CL_GUI_ALV_GRID 메서드 정의와 SM37 잡의 Spool Page Format 설정을 함께 확인하시기 바랍니다.