SAP 표준이든 자체 개발한 ALV 리포트든, 화면에서 합계·집계 결과를 보여주는 코드는 보통 검증이 끝난 상태로 운영 중입니다. 이때 외부 시스템이나 EAI 인터페이스에서 같은 결과를 RFC로 받고 싶다는 요구가 종종 들어옵니다.
같은 집계 로직을 RFC 안에서 다시 작성하면 두 곳을 따로 관리해야 해서 값이 어긋날 위험이 큽니다. SAP는 이 문제를 해결하기 위해 CL_SALV_BS_RUNTIME_INFO 클래스를 제공합니다. ALV 화면 출력을 끈 채로 SUBMIT 으로 호출하면, ALV가 화면에 그릴 내부 테이블을 메모리에서 그대로 회수할 수 있습니다.
이 글은 RFC(Function Module) 안에서 SUBMIT … AND RETURN 과 CL_SALV_BS_RUNTIME_INFO 를 결합해 ALV 결과를 EXPORTING 파라미터로 돌려주는 4단계 패턴과, 자주 빠지는 함정을 정리한 메모입니다.
핵심 — 화면 출력을 끈 상태로 ALV 내부 테이블만 가져옵니다
CL_SALV_BS_RUNTIME_INFO 는 CL_SALV_TABLE 기반 ALV가 사용하는 런타임 메모리 영역에 직접 접근하는 통로입니다. 호출자가 SET 메소드로 "화면은 그리지 말고 데이터만 메모리에 두라" 라고 모드를 바꿔주면, SUBMIT 된 리포트가 ALV 출력을 건너뛰고 결과 테이블만 메모리에 EXPORT 합니다.
세 가지 플래그(display · metadata · data) 의 의미는 다음과 같습니다.
| 플래그 | 의미 | RFC 용도 권장값 |
|---|---|---|
display |
ALV 화면을 실제 그릴지 여부 | abap_false (화면 미표시) |
metadata |
Fieldcat · Layout · Sort 같은 메타 정보를 메모리에 둘지 여부 | abap_false (값만 필요) |
data |
화면에 들어갈 내부 테이블 자체를 메모리에 둘지 여부 | abap_true (데이터만 수집) |
RFC 안에서 합계만 EXPORTING 으로 돌려주는 용도라면 위 표의 권장값 조합이 표준입니다. 메타데이터까지 받아 자체 ALV를 다시 그리는 시나리오가 아니라면 data 만 켜는 편이 메모리 사용량도 가볍습니다.
대상 리포트가 CL_SALV_TABLE=>FACTORY 기반인지는 사전에 확인이 필요합니다. 구식 REUSE_ALV_GRID_DISPLAY 기반 리포트는 동작하지 않거나 결과 테이블이 비는 경우가 있어, 이때는 본문 마지막에 안내한 대로 다른 호출 패턴을 검토합니다.
1단계 — SET 메소드로 런타임 모드 켜기
SUBMIT 전에 SET 을 호출해 모드를 바꿔두지 않으면, 호출된 리포트가 평소처럼 화면을 그리고 사용자 입력을 기다리며 멈춥니다. RFC 컨텍스트에서는 그 자체로 사고이므로 이 단계를 가장 먼저 실행합니다.
CL_SALV_BS_RUNTIME_INFO=>SET(
EXPORTING
display = abap_false " 화면 미표시
metadata = abap_false " Fieldcat 등 메타 정보 안 받음
data = abap_true " 결과 데이터만 메모리에 적재
).
내부적으로는 EXPORT s_runtime_info TO MEMORY ID 'ALV_RUNTIME_INFO' 가 실행되며, 다음 SUBMIT 으로 호출되는 리포트가 ALV 출력 직전에 이 모드를 읽어 동작을 분기합니다.
같은 RFC 세션에서 SUBMIT 을 여러 번 돌릴 거라면, 매 회차 직전에 SET 을 다시 호출해야 합니다. 뒤에서 다룰 CLEAR_ALL 이 메모리를 깨끗이 비우기 때문에, 두 번째 회차에서 모드가 사라진 상태로 SUBMIT 하면 화면이 그려져 버립니다.
2단계 — SUBMIT … AND RETURN 으로 ALV 리포트 호출
대상 리포트의 Selection-screen 파라미터·셀렉트 옵션 이름을 그대로 WITH 절에 매핑합니다. 리포트 소스에서 SELECT-OPTIONS so_budat FOR sy-datum 으로 선언된 옵션은 WITH so_budat IN ra_budat 형태로 전달합니다.
SUBMIT zrxx0123
WITH so_budat IN ra_budat
WITH so_werks IN ra_werks
WITH so_matkl IN ra_matkl
AND RETURN.
두 가지를 반드시 지킵니다.
AND RETURN절을 빠뜨리지 않습니다. 누락 시 호출된 리포트가 끝나는 순간 컨텍스트도 같이 종료되어 RFC가 EXPORTING 을 채울 기회를 잃습니다.WITH절의 변수명은 리포트 소스의 선언명과 정확히 일치해야 합니다. 오타가 있어도 컴파일은 통과하지만, 해당 옵션은 빈 값으로 처리되어 결과가 비거나 엉뚱하게 나옵니다.
호출된 리포트는 평소 흐름대로 SELECT → 가공 → 집계까지 진행한 뒤, CL_SALV_TABLE=>FACTORY 호출 직전에 1단계 모드를 감지해 화면 출력 대신 메모리 EXPORT 만 수행합니다.
3단계 — GET_DATA_REF 로 결과 회수 후 ASSIGN
리포트가 메모리에 적재한 내부 테이블은 자료형이 호출자 입장에서 미리 알 수 없습니다. 그래서 CL_SALV_BS_RUNTIME_INFO=>GET_DATA_REF 가 데이터 레퍼런스(REF TO DATA) 를 돌려주고, 호출자가 FIELD-SYMBOL 로 받아 컴포넌트 이름으로 접근합니다.
DATA: lr_data TYPE REF TO data.
FIELD-SYMBOLS:
<lt_data> TYPE ANY TABLE,
<ls_data> TYPE any,
<fs> TYPE any.
CL_SALV_BS_RUNTIME_INFO=>GET_DATA_REF(
IMPORTING r_data = lr_data
).
ASSIGN lr_data->* TO <lt_data>. " SUBMIT 이후에만 할당 가능
LOOP AT <lt_data> ASSIGNING <ls_data>.
ASSIGN COMPONENT 'WGBEZ' OF STRUCTURE <ls_data> TO <fs>.
" <fs> 에 ALV 컬럼 값이 담김
ENDLOOP.
핵심 포인트:
<lt_data>는SUBMIT이 메모리를 실제로 채운 뒤에만 할당됩니다.SET직후에는 비어 있습니다.ASSIGN COMPONENT '필드명'으로 ALV 컬럼에 이름 기반 접근합니다. 호출자 RFC가 ALV 내부 구조체 타입을 알지 못해도 동작합니다.- 호출 전에
lr_data IS BOUND또는sy-subrc체크를 한 번 더 해두면, 리포트가 결과를 만들지 못한 경우에 발생하는CX_SY_REF_IS_INITIAL덤프를 피할 수 있습니다.
4단계 — CLEAR_ALL 로 메모리 정리
회수한 데이터를 EXPORTING 테이블에 옮긴 뒤에는 즉시 CLEAR_ALL 로 메모리를 비웁니다. 이전 회차 데이터가 남아 다음 호출 결과로 오인되는 사고를 막아주는 역할입니다.
CL_SALV_BS_RUNTIME_INFO=>CLEAR_ALL( ).
CLEAR_ALL 은 다음 네 가지 메모리 영역을 한 번에 삭제합니다.
| 메모리 ID | 내용 |
|---|---|
ALV_RUNTIME_INFO |
SET 으로 설정한 모드 플래그(display · metadata · data) |
ALV_RUNTIME_DATA |
ALV가 화면에 그릴 내부 테이블 데이터 |
ALV_RUNTIME_METADATA |
Fieldcat · Layout · Sort 정보 |
ALV_RUNTIME_ERROR |
리포트 실행 중 발생한 에러 메시지 |
같은 RFC 안에서 두 번 이상 SUBMIT 을 도는 패턴이라면, 각 회차마다 SET → SUBMIT → GET_DATA_REF → ASSIGN → CLEAR_ALL → UNASSIGN 6단계를 반복합니다. UNASSIGN 으로 FIELD-SYMBOL 을 끊지 않으면 이전 회차 메모리 영역에 묶인 채로 다음 결과를 덮어쓰려다 덤프가 나는 경우가 있습니다.
흔히 빠뜨리는 함정
AND RETURN 누락
SUBMIT 만 단독 사용 시 호출된 리포트 종료와 함께 RFC 컨텍스트도 같이 끝납니다. EXPORTING 채울 기회를 잃기 전에 AND RETURN 을 반드시 붙입니다.
회차마다 SET 다시 호출 안 함
여러 번 SUBMIT 도는 패턴에서 첫 회차만 SET 하면, 두 번째 회차는 CLEAR_ALL 이후라 모드가 비어 있어 화면이 그려지고 RFC가 멈춥니다. 회차마다 SET 부터 다시 호출합니다.
REUSE_ALV_GRID_DISPLAY 기반 리포트
CL_SALV_BS_RUNTIME_INFO 는 CL_SALV_TABLE 기반 리포트에서만 동작합니다. 옛 함수형 ALV(REUSE_ALV_GRID_DISPLAY) 기반 리포트는 결과 테이블이 비거나 동작하지 않습니다. 사전에 리포트 소스에서 ALV 생성 방식을 확인합니다.
WITH 절 옵션명 오타
리포트의 Selection-screen 선언명과 WITH 절 이름이 한 글자라도 다르면 해당 옵션은 빈 값으로 처리됩니다. 컴파일은 통과하므로 결과 검증 단계에서 발견됩니다.
CX_SY_REF_IS_INITIAL 덤프
리포트가 결과를 못 만들었을 때 GET_DATA_REF 가 빈 레퍼런스를 돌려주고, 거기에 ASSIGN 하면 덤프가 납니다. IF lr_data IS BOUND 체크 후 ASSIGN 합니다.
외부 시스템 RFC 컨텍스트에서 모드 미반영
다른 시스템에서 RFC 로 호출할 때는 ABAP 메모리 영역이 의도와 다르게 잡힐 수 있습니다. 같은 인스턴스·같은 client 안에서 호출하는 경우에만 안정적으로 동작하며, 외부 시스템 인터페이스에는 EXPORT TO MEMORY ID 같은 명시적 메모리 패턴을 우선 검토합니다.
CLEAR_ALL 누락으로 다음 RFC 호출에 잔여 데이터
EXPORTING 채운 뒤 CLEAR_ALL 을 빠뜨리면, 다음에 같은 RFC 가 호출되었을 때 이전 데이터가 메모리에 남아 있다가 새 호출 결과로 잘못 회수될 수 있습니다. RFC 종료 직전에는 항상 CLEAR_ALL 을 호출합니다.
전체 코드 — 복사용 통합본
플랜트 · 자재 그룹 기준 일자별 재고 합계를 ALV로 보여주는 표준 리포트(ZRXX0123) 의 결과를 그대로 RFC 결과로 돌려주는 흐름입니다. SE37 에 신규 Function Module 로 등록해 사용합니다.
FUNCTION z_xx_get_daily_stock.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(I_WERKS) TYPE WERKS_D OPTIONAL
*" VALUE(I_BUDAT) TYPE DATS OPTIONAL
*" EXPORTING
*" VALUE(E_MTYPE) TYPE BAPI_MTYPE
*" VALUE(E_MTEXT) TYPE BAPI_MSG
*" TABLES
*" ET_STOCK STRUCTURE ZSXX0123
*"----------------------------------------------------------------------
* ★ 사전 작업
* 1) 호출 대상 ALV 리포트(ZRXX0123) 가 CL_SALV_TABLE=>FACTORY 기반인지 확인
* 2) 리포트의 Selection-screen 옵션명(SO_BUDAT, SO_WERKS, SO_MATKL) 확인
* 3) EXPORTING 구조체(ZSXX0123) 의 필드명 일치 확인
RANGES:
ra_budat FOR sy-datum,
ra_werks FOR marc-werks,
ra_matkl FOR mara-matkl.
DATA: lr_data TYPE REF TO data.
FIELD-SYMBOLS:
<lt_data> TYPE ANY TABLE,
<ls_data> TYPE any,
<fs> TYPE any.
DATA: BEGIN OF ls_buf,
wgbez LIKE zsxx0123-wgbez,
zclstc_sum LIKE zsxx0123-zclstc,
END OF ls_buf,
lt_buf LIKE TABLE OF ls_buf.
* 1) 입력 파라미터 검증
IF i_budat IS INITIAL.
e_mtype = 'E'.
e_mtext = '조회일은 필수입니다.'.
RETURN.
ENDIF.
IF i_werks IS INITIAL.
e_mtype = 'E'.
e_mtext = '플랜트는 필수입니다.'.
RETURN.
ENDIF.
* 2) RANGES 구성 — 호출 리포트의 Selection-screen 옵션에 매핑
ra_budat-sign = 'I'.
ra_budat-option = 'EQ'.
ra_budat-low = i_budat.
APPEND ra_budat.
ra_werks-sign = 'I'.
ra_werks-option = 'EQ'.
ra_werks-low = i_werks.
APPEND ra_werks.
ra_matkl-sign = 'I'.
ra_matkl-option = 'EQ'.
ra_matkl-low = 'HALB'.
APPEND ra_matkl.
* 3) ★ 핵심: ALV 런타임 모드 ON — 화면 미표시, 데이터만 수집
CL_SALV_BS_RUNTIME_INFO=>SET(
EXPORTING
display = abap_false
metadata = abap_false
data = abap_true
).
* 4) 표준/커스텀 ALV 리포트 호출 — AND RETURN 필수
SUBMIT zrxx0123
WITH so_budat IN ra_budat
WITH so_werks IN ra_werks
WITH so_matkl IN ra_matkl
AND RETURN.
* 5) ALV 내부 테이블 회수
CL_SALV_BS_RUNTIME_INFO=>GET_DATA_REF(
IMPORTING r_data = lr_data
).
IF lr_data IS NOT BOUND.
CL_SALV_BS_RUNTIME_INFO=>CLEAR_ALL( ).
e_mtype = 'E'.
e_mtext = '리포트 실행 결과가 비었습니다.'.
RETURN.
ENDIF.
ASSIGN lr_data->* TO <lt_data>.
CL_SALV_BS_RUNTIME_INFO=>CLEAR_ALL( ).
* 6) 컴포넌트 단위 추출 + COLLECT 로 합계
LOOP AT <lt_data> ASSIGNING <ls_data>.
ASSIGN COMPONENT 'WGBEZ' OF STRUCTURE <ls_data> TO <fs>.
ls_buf-wgbez = <fs>.
ASSIGN COMPONENT 'ZCLSTC' OF STRUCTURE <ls_data> TO <fs>.
ls_buf-zclstc_sum = <fs>.
COLLECT ls_buf INTO lt_buf.
CLEAR ls_buf.
ENDLOOP.
* 7) EXPORTING 채우기
et_stock[] = CORRESPONDING #( lt_buf MAPPING
wgbez = wgbez
zclstc = zclstc_sum ).
IF et_stock[] IS INITIAL.
e_mtype = 'E'.
e_mtext = '조회된 데이터가 없습니다.'.
ELSE.
e_mtype = 'S'.
e_mtext = '데이터 조회 성공'.
ENDIF.
ENDFUNCTION.
기간 루프로 같은 리포트를 여러 번 SUBMIT 하는 변형은 DO ... ENDDO 안에 위 6단계 흐름을 통째로 넣고, 각 회차 끝에 UNASSIGN <lt_data> 한 줄을 추가합니다. 회차마다 SET 부터 다시 호출하는 점만 지키면 동일한 패턴으로 확장됩니다.
요약
| 단계 | 호출 | 핵심 |
|---|---|---|
| 1 | SET |
display=false, metadata=false, data=true |
| 2 | SUBMIT … AND RETURN |
대상 ALV 리포트 호출 — Selection-screen 옵션명 정확히 매핑 |
| 3 | GET_DATA_REF |
결과 레퍼런스 회수 → ASSIGN 후 ASSIGN COMPONENT 로 추출 |
| 4 | CLEAR_ALL |
메모리 4영역 일괄 정리 — 다음 회차·다음 RFC 호출 격리 |
RFC 안에서 ALV 결과를 그대로 EXPORTING 으로 돌려주는 패턴은 검증된 집계 로직을 두 곳에서 관리하지 않아도 된다는 게 가장 큰 장점입니다. SET → SUBMIT … AND RETURN → GET_DATA_REF → ASSIGN → CLEAR_ALL 5단계를 정확히 지키고, 호출 대상 리포트가 CL_SALV_TABLE 기반인지 사전 확인만 거치면, 같은 시스템 안에서 안정적으로 활용할 수 있는 표준 패턴입니다. 외부 시스템 인터페이스에는 명시적 EXPORT TO MEMORY ID 방식을 우선 검토합니다.
Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.
CL_SALV_BS_RUNTIME_INFO 클래스와 SET · GET_DATA_REF · CLEAR_ALL 메소드, SUBMIT … AND RETURN 구문은 SAP NetWeaver 표준 기능으로 ECC 6.0 · S/4HANA on-premise 환경 공통으로 동작합니다. CL_SALV_TABLE=>FACTORY 기반 ALV에만 적용되며, 구식 REUSE_ALV_GRID_DISPLAY 함수형 ALV에는 동작하지 않으므로 호출 대상 리포트의 ALV 구현 방식을 사전에 확인하시기 바랍니다. 외부 시스템에서 인입되는 RFC 호출이나 백그라운드(JOB) 모드 실행 시 ABAP 메모리 컨텍스트가 의도와 다르게 잡힐 수 있으므로, 시스템 경계를 넘어가는 인터페이스에는 명시적 EXPORT TO MEMORY ID 패턴을 우선 검토하시기 바랍니다.