SAP 프로그램에서 여러 건의 처리 결과 메시지를 사용자에게 한꺼번에 보여줘야 할 때가 자주 있습니다. BAPI / BDC 일괄 처리 후 50건의 에러·워닝·성공 메시지가 쌓였다면 MESSAGE 키워드로 한 줄씩 띄우는 건 비효율적이고, 일반 ALV 리포트로 출력하면 화면이 너무 무겁습니다. 적절한 절충안이 ALV 형태의 팝업 창.
표준 SAP 에서 이 패턴은 두 가지 — BAL(Business Application Log) 의 BAL_DSP_LOG_DISPLAY FM 과 CL_SALV_TABLE 팝업 모드. BAL 은 메시지 타입(E·W·S·I·A) 별 아이콘과 표준 필터를 자동 제공하고, CL_SALV_TABLE 은 자유로운 데이터 구조에 더 유연한 ALV 팝업을 만들 수 있습니다.
이 글에서는 두 가지 패턴의 시그니처·BAPIRET2 메시지 변환·BAL 로그 생성 흐름·CL_SALV_TABLE 팝업 옵션·함정까지 한 번에 정리합니다. 일괄 처리 결과 표시 / 검증 결과 안내 / 에러 모음 화면을 가볍게 구현하는 표준 도구입니다.
핵심 — 두 방법 비교
| 항목 | 방법1 — BAL 로그 + DISPLAY | 방법2 — CL_SALV_TABLE 팝업 |
|---|---|---|
| 화면 형태 | 메시지 타입 아이콘 + 텍스트 ALV | 일반 ALV 팝업 |
| 입력 데이터 | BAPIRET2 또는 메시지 정보 | 자유 itab |
| 표준 기능 | 필터 · 통계 · long text 자동 | 정렬 · 필터 · 컬럼 제어 자유 |
| 구현 비용 | 3개 FM 호출 | factory + set_screen_popup + display |
| 적합 시나리오 | BAPI / BDC 결과 메시지 표시 | 자체 결과 데이터 (메시지 + 키 컬럼) |
선택 기준 — BAPI / BDC 의 RETURN 그대로 보여주면 BAL, 메시지 + 거래처번호 · 자재 등 추가 컬럼이 필요하면 CL_SALV_TABLE. 두 방법 모두 팝업이라 사용자가 보고 즉시 닫을 수 있어 화면 흐름이 가볍습니다.
1단계 — BAL 표준 흐름 (3개 FM)
BAL(Business Application Log) 은 SAP 가 메시지 로그 관리용으로 제공하는 표준 도구. 메시지를 누적해서 한 번에 ALV 로 표시.
[1] BAL_LOG_CREATE — 로그 핸들 생성 (메모리상)
[2] BAL_LOG_MSGBAPIRET2_ADD — BAPIRET2 메시지 추가 (반복)
[3] BAL_DSP_LOG_DISPLAY — ALV 팝업 / 풀스크린 표시
세 단계만 거치면 BAPIRET2 테이블이 그대로 표준 메시지 ALV 로 표시됩니다.
DATA: ls_log TYPE bal_s_log,
lv_log_h TYPE balloghndl,
lt_log_h TYPE bal_t_logh,
lt_return TYPE TABLE OF bapiret2.
" (lt_return 은 BAPI / BDC 호출 결과로 채워져 있다고 가정)
" ★ 1) 로그 핸들 생성
ls_log-extnumber = '메시지 결과'.
ls_log-aluser = sy-uname.
ls_log-aldate = sy-datum.
ls_log-altime = sy-uzeit.
ls_log-object = 'APPL_LOG'.
CALL FUNCTION 'BAL_LOG_CREATE'
EXPORTING
i_s_log = ls_log
IMPORTING
e_log_handle = lv_log_h
EXCEPTIONS
OTHERS = 1.
" ★ 2) BAPIRET2 메시지 일괄 추가
LOOP AT lt_return ASSIGNING FIELD-SYMBOL(<ls_ret>).
DATA(ls_msg) = VALUE bal_s_msg(
msgty = <ls_ret>-type
msgid = <ls_ret>-id
msgno = <ls_ret>-number
msgv1 = <ls_ret>-message_v1
msgv2 = <ls_ret>-message_v2
msgv3 = <ls_ret>-message_v3
msgv4 = <ls_ret>-message_v4 ).
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
i_log_handle = lv_log_h
i_s_msg = ls_msg
EXCEPTIONS
OTHERS = 1.
ENDLOOP.
" ★ 3) ALV 형태로 화면 표시
APPEND lv_log_h TO lt_log_h.
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXPORTING
i_t_log_handle = lt_log_h
EXCEPTIONS
OTHERS = 1.
화면이 뜨면 메시지 타입(E·W·S·I) 별 아이콘이 자동 표시되고 long text 보기 / 필터 / 정렬도 표준으로 동작.
2단계 — BAL 팝업 모드 (BAL_DSP_PROFILE_POPUP_GET)
기본 BAL_DSP_LOG_DISPLAY 는 풀스크린. 팝업 형태로 바꾸려면 표시 프로파일을 POPUP 용 으로 받아서 넘김.
DATA ls_profile TYPE bal_s_prof.
" 팝업용 표준 프로파일
CALL FUNCTION 'BAL_DSP_PROFILE_POPUP_GET'
IMPORTING
e_s_display_profile = ls_profile.
CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXPORTING
i_s_display_profile = ls_profile " ★ 팝업 프로파일 전달
i_t_log_handle = lt_log_h.
다른 프로파일 — BAL_DSP_PROFILE_NO_TREE_GET (트리 없는 단일 ALV) 도 자주 사용. 회사 정책에 맞춰 선택.
3단계 — CL_SALV_TABLE 팝업 (자유 데이터)
메시지 + 추가 컬럼(거래처번호·자재·PO 번호 등) 을 함께 보여주고 싶을 때. CL_SALV_TABLE 의 팝업 모드가 가장 가볍습니다.
TYPES: BEGIN OF ty_result,
seq TYPE i,
type TYPE bapiret2-type,
ebeln TYPE ekko-ebeln,
matnr TYPE mara-matnr,
message TYPE string,
END OF ty_result.
DATA: lt_result TYPE TABLE OF ty_result,
go_alv TYPE REF TO cl_salv_table.
" (lt_result 데이터 채움 — BAPI 호출 결과 + 추가 키 매핑)
" ★ ALV 객체 생성
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = go_alv
CHANGING t_table = lt_result ).
" ★ 팝업 모드 설정 — 시작 행·열 + 끝 행·열
go_alv->set_screen_popup(
start_column = 1
end_column = 100
start_line = 1
end_line = 20 ).
" ★ 표준 기능 활성화
go_alv->get_functions( )->set_all( abap_true ).
" 화면 표시
go_alv->display( ).
CATCH cx_salv_msg INTO DATA(lo_ex).
MESSAGE lo_ex->get_text( ) TYPE 'E'.
ENDTRY.
set_screen_popup 의 4개 좌표가 팝업 크기 / 위치를 결정. 일반적으로 시작(1,1) ~ 끝(100, 20) 이 화면 중앙 적당한 크기.
4단계 — 컬럼 라벨 / 메시지 타입 아이콘 (CL_SALV_TABLE)
CL_SALV_TABLE 팝업에서 메시지 타입을 아이콘으로 표시하면 사용자가 한눈에 에러를 파악할 수 있습니다.
TYPES: BEGIN OF ty_result,
icon TYPE icon_d, " 아이콘 컬럼
seq TYPE i,
type TYPE bapiret2-type,
ebeln TYPE ekko-ebeln,
message TYPE string,
END OF ty_result.
" 데이터 채울 때 type 별 아이콘 매핑
LOOP AT lt_return ASSIGNING FIELD-SYMBOL(<ls_ret>).
DATA(ls_row) = VALUE ty_result(
seq = sy-tabix
type = <ls_ret>-type
ebeln = <ls_ret>-message_v1
message = <ls_ret>-message ).
CASE <ls_ret>-type.
WHEN 'E' OR 'A'. ls_row-icon = '@5C@'. " 빨간 X
WHEN 'W'. ls_row-icon = '@5D@'. " 노란 경고
WHEN 'S'. ls_row-icon = '@5B@'. " 초록 체크
WHEN 'I'. ls_row-icon = '@8B@'. " 파란 정보
ENDCASE.
APPEND ls_row TO lt_result.
ENDLOOP.
" Field Catalog 에서 icon 컬럼을 아이콘으로 표시
go_alv->get_columns( )->get_column( 'ICON' )->set_short_text( '상태' ).
go_alv->get_columns( )->get_column( 'ICON' )->set_alignment( if_salv_c_alignment=>centered ).
ALV 가 자동으로 ICON_D 타입 컬럼을 그래픽으로 렌더링. 사용자가 빠르게 에러만 필터링하기 좋아집니다.
5단계 — 메시지 자동 빌드 + 추가 컬럼 (실무 패턴)
BAPI 호출 결과를 그대로 ALV 에 적재할 때 메시지 텍스트 빌드를 자동화. MESSAGE ... INTO 구문 활용.
LOOP AT lt_return INTO DATA(ls_return).
DATA lv_msg TYPE string.
IF ls_return-message IS NOT INITIAL.
lv_msg = ls_return-message.
ELSE.
MESSAGE ID ls_return-id
TYPE ls_return-type
NUMBER ls_return-number
WITH ls_return-message_v1
ls_return-message_v2
ls_return-message_v3
ls_return-message_v4
INTO lv_msg.
ENDIF.
APPEND VALUE ty_result(
seq = sy-tabix
type = ls_return-type
ebeln = lv_current_ebeln " 호출자가 알고 있는 키
matnr = lv_current_matnr
message = lv_msg
) TO lt_result.
ENDLOOP.
이 패턴이 일반 BAPI / BDC 결과 화면에서 가장 자주 쓰는 흐름입니다. 메시지 텍스트 + 비즈니스 키(PO 번호 / 자재) 를 같은 행에 묶어 사용자가 어떤 라인이 실패했는지 즉시 파악 가능.
흔히 빠뜨리는 함정
팝업 크기 좌표
set_screen_popup 의 4개 값은 SAP GUI 의 문자 단위. 너무 작게 잡으면 데이터가 잘리고, 너무 크게 잡으면 화면 밖으로 나가서 사용자가 닫기 버튼을 못 찾습니다. 시작 1,1 / 끝 100,20 정도가 안전한 기본값.
BAL 로그 컨테이너 누락
BAL_LOG_CREATE 의 OBJECT · SUBOBJECT 를 비우면 표시 화면의 일부 옵션이 비활성. 표준 APPL_LOG 또는 회사 자체 정의 값으로 채우시기 바랍니다.
BAPIRET2 MESSAGE 필드 신뢰 X
BAPIRET2 의 MESSAGE 필드가 비어 있는 BAPI 도 있습니다. MESSAGE ... INTO 구문으로 다시 빌드해서 표시하는 것이 안전.
CL_SALV_TABLE 인스턴스 메모리 누수
PBO 가 호출될 때마다 새 ALV 인스턴스를 만들면 메모리 누적. IF 가드로 한 번만 생성하거나 호출 후 명시적으로 free.
메시지 갯수 표시 안 됨
BAL 풀스크린에서는 좌측에 통계가 표시되지만 팝업 모드에서는 안 보일 수 있습니다. 사용자가 전체 갯수를 알아야 한다면 별도 메시지 + 합계 표시.
한 로그에 너무 많은 메시지
BAL_LOG_MSG_ADD 를 10,000건 이상 호출하면 메모리 / 표시 속도 부담. 대량 메시지 시나리오는 BAL 로그 여러 개로 분할하거나 CL_SALV_TABLE 로 직접 처리.
닫기 후 사용자 액션 캡처
팝업이 닫힌 후 사용자가 어떻게 닫았는지(OK / 취소 / 닫기) 알고 싶다면 BAL_DSP_LOG_DISPLAY 의 E_S_EXIT_COMMAND 를 받아 분기. CL_SALV_TABLE 은 이벤트 핸들러로 처리.
전체 코드 — 복사용 통합본 (CL_SALV_TABLE 팝업)
*&---------------------------------------------------------------------*
*& Report Z_XX_ALV_POPUP_MESSAGE
*&---------------------------------------------------------------------*
*& BAPI 결과 메시지 → ALV 형태 팝업 표시
*&---------------------------------------------------------------------*
REPORT z_xx_alv_popup_message.
TYPES: BEGIN OF ty_result,
icon TYPE icon_d,
seq TYPE i,
type TYPE bapiret2-type,
ebeln TYPE ekko-ebeln,
message TYPE string,
END OF ty_result.
DATA: lt_return TYPE TABLE OF bapiret2,
lt_result TYPE TABLE OF ty_result,
go_alv TYPE REF TO cl_salv_table.
START-OF-SELECTION.
" (실제로는 BAPI / BDC 호출 후 lt_return 채움 - 여기서는 샘플)
APPEND VALUE #( type = 'E' id = 'M3' number = '050'
message = '자재 유형이 플랜트에서 허용되지 않습니다.'
message_v1 = '4500000001' ) TO lt_return.
APPEND VALUE #( type = 'W' id = 'F5' number = '015'
message = '회계 기간이 마감되었습니다.'
message_v1 = '4500000002' ) TO lt_return.
APPEND VALUE #( type = 'S' id = '00' number = '398'
message = '문서가 정상 처리되었습니다.'
message_v1 = '4500000003' ) TO lt_return.
" ★ BAPIRET2 → 결과 itab 빌드
LOOP AT lt_return INTO DATA(ls_ret).
DATA lv_msg TYPE string.
IF ls_ret-message IS NOT INITIAL.
lv_msg = ls_ret-message.
ELSE.
MESSAGE ID ls_ret-id
TYPE ls_ret-type
NUMBER ls_ret-number
WITH ls_ret-message_v1
ls_ret-message_v2
ls_ret-message_v3
ls_ret-message_v4
INTO lv_msg.
ENDIF.
DATA(ls_row) = VALUE ty_result(
seq = sy-tabix
type = ls_ret-type
ebeln = ls_ret-message_v1
message = lv_msg ).
CASE ls_ret-type.
WHEN 'E' OR 'A'. ls_row-icon = '@5C@'.
WHEN 'W'. ls_row-icon = '@5D@'.
WHEN 'S'. ls_row-icon = '@5B@'.
WHEN 'I'. ls_row-icon = '@8B@'.
ENDCASE.
APPEND ls_row TO lt_result.
ENDLOOP.
" ★ ALV 팝업 표시
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = go_alv
CHANGING t_table = lt_result ).
" 팝업 모드
go_alv->set_screen_popup(
start_column = 1
end_column = 100
start_line = 1
end_line = 20 ).
" 표준 기능 (필터·정렬·엑셀 내보내기 등)
go_alv->get_functions( )->set_all( abap_true ).
" 컬럼 라벨
DATA(lo_columns) = go_alv->get_columns( ).
lo_columns->get_column( 'ICON' )->set_short_text( '상태' ).
lo_columns->get_column( 'SEQ' )->set_short_text( '순번' ).
lo_columns->get_column( 'TYPE' )->set_short_text( '유형' ).
lo_columns->get_column( 'EBELN' )->set_short_text( 'PO 번호' ).
lo_columns->get_column( 'MESSAGE' )->set_short_text( '메시지' ).
go_alv->display( ).
CATCH cx_salv_msg INTO DATA(lo_ex).
MESSAGE lo_ex->get_text( ) TYPE 'E'.
ENDTRY.
같이 보면 좋은 글:
- "BAPI · BDC 에러 메시지 확인 방법 — MESSAGE INTO · FORMAT_MESSAGE 빌드" — BAPIRET2 → 메시지 텍스트 빌드 패턴
- "BAdI 찾는 방법 5가지 — CL_EXITHANDLER 디버깅" — 메시지 발생 위치 추적 디버깅
- "Search Help 매크로 활용 — F4IF_INT_TABLE_VALUE_REQUEST DEFINE 한 줄 호출" — 같은 ALV 영역 매크로 패턴
요약
| 방법 | 핵심 API | 적합 시나리오 |
|---|---|---|
| 1 | BAL 표준 흐름 | BAL_LOG_CREATE + BAL_LOG_MSG_ADD + BAL_DSP_LOG_DISPLAY |
| 2 | BAL 팝업 프로파일 | BAL_DSP_PROFILE_POPUP_GET 함께 사용 |
| 3 | CL_SALV_TABLE 팝업 | factory + set_screen_popup + display |
| 4 | 아이콘 컬럼 | ICON_D 타입 + 메시지별 아이콘 매핑 |
| 5 | 메시지 빌드 | MESSAGE ... INTO 로 텍스트 자동 빌드 |
여러 건의 메시지를 한 번에 보여주는 UX 가 필요할 때 BAL 시리즈는 BAPI / BDC 결과를 빠르게 표시, CL_SALV_TABLE 팝업은 메시지 + 추가 키 컬럼이 함께 필요한 시나리오에 적합합니다. 둘 다 표준 ALV 의 필터 · 정렬 · 엑셀 내보내기를 그대로 활용 가능하고, 팝업이라 화면 흐름을 가볍게 유지할 수 있습니다. 메시지 타입 아이콘 표시 · 메시지 텍스트 자동 빌드 · 비즈니스 키 컬럼 연결 세 가지를 패턴으로 잡아두면 일괄 처리 결과 화면을 빠르게 구현할 수 있습니다.
Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.
BAL_DSP_LOG_DISPLAY Function Module 시그니처 · CL_SALV_TABLE 메소드 · BAL 표준 흐름은 SAP NetWeaver 표준(패키지 SZAL · ECC 6.0 / S/4HANA on-premise) 기준이며, 사내 메시지 클래스 정책 · ALV 변형 · 화면 권한에 따라 일부 동작이 다를 수 있으니 운영 시스템 적용 전 개발·QA 환경에서 검증하시기 바랍니다. 팝업 크기 / 위치는 SAP GUI 해상도에 따라 다르게 보일 수 있으므로 다양한 사용자 환경에서 테스트 권장.