본문 바로가기
ABAP 문법 & 기법/Dialog & Screen Painter

[SAP ABAP] SubScreen + Tabstrip Control — Dialog 화면 안에 다른 화면 임베드 (CALL SUBSCREEN INCLUDING)

by Song.sh 2026. 5. 15.

Dialog 프로그램 화면이 복잡해지면 한 화면에 모든 항목을 넣을 수 없습니다. 공통 영역 + 탭별로 바뀌는 영역 으로 분할하거나, 메인 폼 + 하단에 ALV 목록 식으로 영역을 나누는 게 자연스러운데, SAP 가 이를 위해 제공하는 표준 메커니즘이 SubScreen 입니다.

 

핵심은 메인 화면 안에 빈 영역(SubScreen Area) 을 두고, 그 영역에 다른 화면을 끼워넣는 것. 호출은 ABAP Flow Logic 의 CALL SUBSCREEN area INCLUDING program dynnr 한 줄. 정적으로 고정 SubScreen 을 호출할 수도 있고, Tabstrip Control 과 결합하면 탭마다 다른 화면을 동적으로 표시할 수 있습니다.

 

이 글은 SubScreen 영역 생성·CALL SUBSCREEN 정적/동적 호출·Tabstrip 결합·PAI 분기·자주 빠뜨리는 함정 까지 한 번에 정리한 메모입니다.


핵심 원리

SubScreen 의 위치와 ALV/Custom Container 와의 차이.

방법 특징 언제 쓰나
SubScreen 화면 안에 다른 Dialog Screen 임베드 (입력 필드 포함) 입력 폼 분할 — 공통 + 탭별
Custom Container GUI 컨트롤(ALV·Tree·HTML) 임베드 ALV·HTML 그릴 영역
Tabstrip Control 탭 컨테이너 — 각 탭이 SubScreen 영역 여러 화면을 탭으로 전환
POP-UP (Modal Dialog) 별도 창에 자식 화면 메인을 가린 채 입력 받을 때

핵심 트레이드오프: 입력 항목이 너무 많아 한 화면이 답답 하면 SubScreen 으로 영역 분할이 정답. 같은 메인 안에 여러 화면을 전환 해야 하면 Tabstrip + SubScreen 조합. ALV/Tree 등 컨트롤 만 필요하면 Custom Container 가 더 맞습니다.


1단계 — 메인 화면에 SubScreen 영역 그리기

Screen Painter(SE51) 에서 메인 화면(예: SCREEN 0100) 을 열고 요소 종류: 서브스크린영역(Subscreen Area) 으로 빈 영역을 그립니다.

설정 내용
요소 종류 서브스크린영역 선택 (드롭다운에서 선택)
이름 예) MAINAREA — 코드에서 이 이름으로 호출
크기 자식 화면이 들어갈 크기 (라인 × 컬럼) — 자식 화면 크기 ≤ 영역 크기
참조필드 (Tabstrip 시) 탭 PUSH BUTTON 속성에서 이 SubScreen 이름을 지정해야 탭과 영역 연결


2단계 — 자식 화면 생성 (Screen Type = Subscreen)

자식 화면(예: SCREEN 0110) 을 만들 때 화면 속성에서 Screen Type: Subscreen 으로 설정합니다.

SE51 → 화면 0110 생성
  속성 → Screen Type: ○ Normal Screen
                     ● Subscreen          ← 이걸 선택
                     ○ Modal Dialog Box
                     ○ Selection Screen

  Next Screen: 0       (Subscreen 은 자체적으로 다음 화면 없음)

핵심 차이:

  • Subscreen 은 자체적으로 PF-STATUS 없음 — 메인 화면이 STATUS 제공
  • Subscreen 의 PAI 는 메인 PAI 와 함께 호출됨
  • LEAVE TO SCREEN 0 같은 흐름 제어는 메인에서만

이 자식 화면 안에 입력 필드·라벨 등 일반 화면 요소를 그리고 PROCESS BEFORE/AFTER 에서 module 호출합니다.


3단계 — CALL SUBSCREEN 정적 호출

가장 단순한 패턴 — 고정된 자식 화면 N개 를 메인의 SubScreen 영역에 한 번에 호출.

PROCESS BEFORE OUTPUT.
  MODULE status_0100.

  " 영역마다 자식 화면 매핑 (정적)
  CALL SUBSCREEN sub_scr  INCLUDING sy-repid '0110'.
  CALL SUBSCREEN sub_scr2 INCLUDING sy-repid '0120'.
  CALL SUBSCREEN sub_scr3 INCLUDING sy-repid '0130'.

PROCESS AFTER INPUT.
  " ★ PAI 도 같이 호출 — 안 하면 자식 화면 입력값이 ABAP 으로 안 들어옴
  CALL SUBSCREEN sub_scr.
  CALL SUBSCREEN sub_scr2.
  CALL SUBSCREEN sub_scr3.

  MODULE user_command_0100.

 

핵심 포인트:

  • CALL SUBSCREEN area INCLUDING program dynnr 형식 — area 는 SubScreen 영역명, program/dynnr 은 자식 화면
  • 같은 메인 프로그램이면 sy-repid, 다른 프로그램이면 그 프로그램명 (보통 함수그룹) 지정
  • PAI 에도 반드시 CALL SUBSCREEN area. — 빠뜨리면 자식 입력값이 메인 변수로 안 들어옴

4단계 — Tabstrip Control + 동적 화면 전환

탭을 클릭할 때마다 메인의 SubScreen 영역에 다른 자식 화면을 끼워넣는 패턴.

" ─── TOP 인클루드 ─────────────────────────
DATA: gv_screen TYPE sy-dynnr,             " 현재 보여줄 자식 화면 번호
      ok_code   TYPE sy-ucomm.

CONTROLS: g_tabstrip TYPE TABSTRIP.        " Tabstrip 컨트롤

" 화면용 컨테이너·ALV 등도 보통 같이 선언
DATA: go_con  TYPE REF TO cl_gui_custom_container,
      go_grid TYPE REF TO cl_gui_alv_grid.

" ─── 메인 100 Flow Logic ─────────────────
PROCESS BEFORE OUTPUT.
  MODULE status_0100.
  CALL SUBSCREEN mainarea INCLUDING sy-repid gv_screen.   " ★ 동적 호출

PROCESS AFTER INPUT.
  CALL SUBSCREEN mainarea.   " 빈 인자 → 현재 활성 자식 화면의 PAI 자동 실행
  MODULE user_command_0100.

" ─── STATUS_0100 (PBO) ───────────────────
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'STD'.
  SET TITLEBAR 'T100'.

  " 현재 활성 탭에 따라 보여줄 자식 화면 번호 결정
  CASE g_tabstrip-activetab.
    WHEN 'TAB1'. gv_screen = '0110'.
    WHEN 'TAB2'. gv_screen = '0120'.
    WHEN 'TAB3'. gv_screen = '0130'.
    WHEN OTHERS. gv_screen = '0110'.       " 디폴트
  ENDCASE.
ENDMODULE.

" ─── USER_COMMAND_0100 (PAI) ─────────────
MODULE user_command_0100 INPUT.
  " 탭 클릭은 ok_code 로 들어옴 → 활성 탭 갱신
  g_tabstrip-activetab = ok_code.

  CASE ok_code.
    WHEN 'BACK' OR 'EXIT' OR 'CANC'.
      LEAVE TO SCREEN 0.
  ENDCASE.

  CLEAR ok_code.
ENDMODULE.

 

핵심 포인트:

  • CONTROLS g_tabstrip TYPE TABSTRIP — Tabstrip 전용 선언
  • g_tabstrip-activetab 에 현재 선택된 탭의 FCODE 가 들어옴
  • 탭 PUSH BUTTON 의 참조필드 속성에 SubScreen 영역명(MAINAREA) 을 적어야 영역과 탭이 연결됨

5단계 — 자식 화면 PBO 모듈 (ALV 임베드 예시)

자식 화면 안에서 ALV·HTML 같은 컨트롤을 띄우는 패턴 — SubScreen 안에 Custom Container 까지 임베드 가능합니다.

" ─── 자식 화면 0110 PBO 모듈 ─────────────
MODULE create_alv110 OUTPUT.

  " 데이터 준비
  SELECT * INTO TABLE @DATA(lt_scarr)
    FROM scarr.

  " ALV 인스턴스 1회만 생성
  IF go_con1 IS INITIAL.
    go_con1 = NEW #( container_name = 'CON1' ).   " Screen 0110 안의 Custom Container 이름
    go_grid1 = NEW #( i_parent = go_con1 ).

    go_grid1->set_table_for_first_display(
      EXPORTING
        i_structure_name = 'SCARR'
      CHANGING
        it_outtab        = lt_scarr ).
  ENDIF.

ENDMODULE.

자식 화면들의 PBO 에서 각각 자기만의 ALV 를 띄우는 식. 객체 인스턴스는 한 번만 생성하고 재사용 — IF IS INITIAL 패턴 필수.


흔히 빠뜨리는 함정

PAI 의 CALL SUBSCREEN 누락

PBO 에만 CALL SUBSCREEN 쓰고 PAI 에 빠뜨리면, 자식 화면 입력 필드의 값이 ABAP 변수로 안 들어옴. 입력만 보이고 저장 안 되는 가장 흔한 원인.

자식 화면을 Subscreen Type 으로 안 만들기

기본 Normal Screen 으로 만든 뒤 CALL SUBSCREEN 으로 호출하면 런타임 덤프(SCREEN_TYPES_INCOMPATIBLE). 속성에서 반드시 Subscreen 선택.

SubScreen 영역 크기 < 자식 화면 크기

자식 화면이 영역보다 크면 잘려서 표시. 영역 크기 ≥ 모든 자식 화면 크기 가 되도록 가장 큰 자식에 맞춰 디자인.

Tab 의 참조필드 미설정

Tabstrip 의 각 탭(PUSH BUTTON) 속성에서 참조필드 에 SubScreen 영역명(MAINAREA) 지정 안 하면 탭 클릭해도 화면 전환 안 됨.

g_tabstrip-activetab 초기값 비어있음

프로그램 시작 시 activetab 이 비어있으면 첫 진입 시 빈 화면. CASE OTHERS 에 디폴트 자식 화면 설정 또는 시작 직전 g_tabstrip-activetab = 'TAB1'.

CALL SUBSCREEN 안에서 LEAVE TO SCREEN 0

자식 화면에서 화면 전환(LEAVE TO SCREEN·SET SCREEN) 하면 안 됨 — 메인 화면에서만 제어. 자식은 흐름 제어 안 함.

Custom Container 객체를 매 PBO 마다 새로 생성

PBO 는 매번 호출되므로 그때마다 NEW cl_gui_custom_container 하면 메모리 누수·GUI 컨트롤 중복. IF go_con IS INITIAL. 가드로 1회만.

TOP 인클루드 분리 안 됨

여러 자식 화면이 같은 변수(gv_screen·g_tabstrip·컨테이너 참조) 를 공유해야 함. TOP 인클루드 1개에 모든 글로벌 변수 두고 모든 화면 모듈에서 접근.

ok_code CLEAR 안 함

PAI 끝에서 CLEAR ok_code 안 하면 다음 화면에서 옛 FCODE 가 살아있어 의도치 않은 분기. 항상 CASE 끝나면 CLEAR.


전체 코드 — 복사용 통합본

위 단계를 함수그룹/리포트 한 세트로 합친 통합본입니다. SE38 신규 리포트 + SE51 메인 화면(0100, SubScreen 영역 MAINAREA + Tabstrip TAB1/TAB2/TAB3) + 자식 화면 3개(0110·0120·0130, Subscreen Type) 생성 후 사용합니다.

*&---------------------------------------------------------------------*
*& SubScreen + Tabstrip Control 표준 패턴
*&---------------------------------------------------------------------*
REPORT zexample_subscreen.

* ========== TOP 인클루드 — 글로벌 선언 ==========
TABLES: scarr.

DATA: gv_screen TYPE sy-dynnr,
      ok_code   TYPE sy-ucomm.

CONTROLS: g_tabstrip TYPE TABSTRIP.

" Custom Container 참조 (자식 화면 안의 ALV 용)
DATA: go_con1  TYPE REF TO cl_gui_custom_container,
      go_grid1 TYPE REF TO cl_gui_alv_grid,
      go_con2  TYPE REF TO cl_gui_custom_container,
      go_grid2 TYPE REF TO cl_gui_alv_grid,
      go_con3  TYPE REF TO cl_gui_custom_container,
      go_grid3 TYPE REF TO cl_gui_alv_grid.

DATA: gt_scarr TYPE TABLE OF scarr,
      gt_spfli TYPE TABLE OF spfli,
      gt_sflight TYPE TABLE OF sflight.

START-OF-SELECTION.
  CALL SCREEN 100.

* ======================================================================
* SCREEN 100 (메인) Flow Logic — SE51 에서 입력
* ----------------------------------------------------------------------
* PROCESS BEFORE OUTPUT.
*   MODULE status_0100.
*   CALL SUBSCREEN mainarea INCLUDING sy-repid gv_screen.   " 동적
*
* PROCESS AFTER INPUT.
*   CALL SUBSCREEN mainarea.
*   MODULE user_command_0100.
* ======================================================================

* ========== 메인 100 PBO ==========
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'STD'.
  SET TITLEBAR  'T100'.

  " 활성 탭에 따라 표시할 자식 화면 결정
  CASE g_tabstrip-activetab.
    WHEN 'TAB1'. gv_screen = '0110'.
    WHEN 'TAB2'. gv_screen = '0120'.
    WHEN 'TAB3'. gv_screen = '0130'.
    WHEN OTHERS. gv_screen = '0110'.   " 디폴트
  ENDCASE.
ENDMODULE.

* ========== 메인 100 PAI ==========
MODULE user_command_0100 INPUT.

  " 탭 클릭 → activetab 갱신
  IF ok_code CP 'TAB*'.
    g_tabstrip-activetab = ok_code.
  ENDIF.

  CASE ok_code.
    WHEN 'BACK' OR 'EXIT' OR 'CANC'.
      LEAVE TO SCREEN 0.
  ENDCASE.

  CLEAR ok_code.
ENDMODULE.

* ======================================================================
* 자식 화면 0110 PBO (SCARR 조회 ALV)
* ----------------------------------------------------------------------
* PROCESS BEFORE OUTPUT.
*   MODULE create_alv110.
*
* PROCESS AFTER INPUT.
*   MODULE user_command_0110.
* ======================================================================
MODULE create_alv110 OUTPUT.

  SELECT * INTO TABLE gt_scarr FROM scarr.

  IF go_con1 IS INITIAL.
    go_con1  = NEW #( container_name = 'CON1' ).
    go_grid1 = NEW #( i_parent = go_con1 ).

    go_grid1->set_table_for_first_display(
      EXPORTING
        i_structure_name = 'SCARR'
      CHANGING
        it_outtab        = gt_scarr ).
  ENDIF.

ENDMODULE.

MODULE user_command_0110 INPUT.
  " 자식 화면 PAI 는 메인 PAI 와 함께 호출됨 — 여기선 자식 전용 처리만
ENDMODULE.

* ======================================================================
* 자식 화면 0120 PBO (SPFLI 조회 ALV)
* ======================================================================
MODULE create_alv120 OUTPUT.

  SELECT * INTO TABLE gt_spfli FROM spfli UP TO 50 ROWS.

  IF go_con2 IS INITIAL.
    go_con2  = NEW #( container_name = 'CON2' ).
    go_grid2 = NEW #( i_parent = go_con2 ).

    go_grid2->set_table_for_first_display(
      EXPORTING
        i_structure_name = 'SPFLI'
      CHANGING
        it_outtab        = gt_spfli ).
  ENDIF.

ENDMODULE.

* ======================================================================
* 자식 화면 0130 PBO (SFLIGHT 조회 ALV)
* ======================================================================
MODULE create_alv130 OUTPUT.

  SELECT * INTO TABLE gt_sflight FROM sflight UP TO 50 ROWS.

  IF go_con3 IS INITIAL.
    go_con3  = NEW #( container_name = 'CON3' ).
    go_grid3 = NEW #( i_parent = go_con3 ).

    go_grid3->set_table_for_first_display(
      EXPORTING
        i_structure_name = 'SFLIGHT'
      CHANGING
        it_outtab        = gt_sflight ).
  ENDIF.

ENDMODULE.

* ※ Screen Painter 준비:
*   1) 화면 0100 (Normal Screen)
*      - 요소: SubScreen Area "MAINAREA"
*      - 요소: Tabstrip Control 그 위에 (탭 3개: TAB1/TAB2/TAB3)
*        - 각 탭 PUSH BUTTON 속성 → 참조필드 = "MAINAREA"
*      - Flow Logic 에 PBO/PAI 모듈 호출
*   2) 화면 0110/0120/0130 (Screen Type = Subscreen)
*      - 각 화면에 Custom Container "CON1"/"CON2"/"CON3"
*      - Flow Logic: PBO → MODULE create_alvXXX
*   3) PF-STATUS 'STD' + Title 'T100' (메인용)

요약

단계 처리 핵심
1 SubScreen 영역 메인 화면에 빈 영역(MAINAREA) 그리기 — 요소 종류: 서브스크린영역
2 자식 화면 생성 Screen Type = Subscreen 으로 생성 (필수)
3 정적 호출 CALL SUBSCREEN area INCLUDING sy-repid '0110' + PAI 도 CALL SUBSCREEN area.
4 Tabstrip 동적 CONTROLS g_tabstrip TYPE TABSTRIP + gv_screen CASE 분기
5 PAI 분기 g_tabstrip-activetab = ok_code + 메인에서만 LEAVE TO SCREEN

SubScreen 은 복잡한 Dialog 화면을 공통 영역 + 가변 영역 으로 분할하는 표준 도구입니다. 정적 호출(CALL SUBSCREEN area INCLUDING program dynnr) 만 알면 화면 분할은 끝나고, Tabstrip Control 과 결합하면 한 화면 안에서 여러 자식 화면을 탭으로 전환할 수 있습니다. PAI 에서도 반드시 CALL SUBSCREEN 부르기·자식 화면을 Subscreen Type 으로 생성·Custom Container 객체는 IF IS INITIAL 로 1회만 생성 — 이 세 가지만 챙기면 SubScreen 패턴의 90% 가 안정적으로 동작합니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다. CALL SUBSCREEN·CONTROLS ... TYPE TABSTRIP·cl_gui_custom_container·cl_gui_alv_grid 는 SAP NetWeaver 표준 ABAP 객체로 시스템 버전 의존 없이 동작합니다. 다만 SubScreen 은 SAP GUI for Windows 기준 동작을 가정하며, Web GUI / Fiori 환경에서는 Dialog 화면 자체의 사용성이 달라질 수 있습니다. Screen Painter 의 요소 속성·참조필드 설정 단계가 코드 못지않게 중요하므로, 운영 적용 전 화면 진입 / 탭 전환 / 입력값 반영 / 메모리 누수(컨테이너 객체) 등 시나리오를 충분히 테스트하시기 바랍니다.