본문 바로가기
ABAP 문법 & 기법

[SAP ABAP] CL_GOS_MANAGER 첨부파일 활용 — 자체 화면에 표준 GOS 서비스 끼우기 (BORIDENT · SRGBRBREL)

by Song.sh 2026. 5. 22.

SAP 표준 트랜잭션(ME23N · FB03 · MM03 등) 의 화면 좌측 상단에 보이는 작은 서비스 아이콘 — 그게 바로 GOS(Generic Object Services) 아이콘 입니다. 클릭하면 첨부파일·노트·송신·워크플로우 같은 표준 서비스가 한 번에 펼쳐집니다. SAP 가 객체(PO·자재문서·전표 등) 와 첨부 데이터를 연결해주는 공용 인프라이며, 이걸 회사 자체 화면이나 ALV 에 끼워 넣는 표준 클래스가 CL_GOS_MANAGER 입니다.

 

CL_GOS_MANAGER 는 단순히 아이콘 하나가 아니라 BOR(Business Object Repository) 객체와 첨부 데이터 간의 관계(SRGBRBREL) 를 자동 관리 합니다. 첨부 / 노트 추가 / 삭제 / 권한 / 송신 흐름까지 표준이 다 잡아주므로 회사 자체 ALV 에 한 줄 추가만으로 표준 ME23N 과 동일한 첨부 UX 를 구현할 수 있습니다.

 

이 글에서는 CL_GOS_MANAGER 시그니처·BOR 객체 매핑·인스턴스 생성·화면 컨테이너 배치·조회 / 변경 모드 분기·첨부 유무 체크·자주 빠뜨리는 함정 까지 표준 패턴으로 정리합니다. 자체 ALV / 화면에 GOS 를 처음 붙이는 케이스를 그대로 따라할 수 있게 단계별로 구성했습니다.

핵심 — CL_GOS_MANAGER 의 정체와 BOR 객체

구성 요소 역할
CL_GOS_MANAGER 표준 GOS 서비스를 화면에 배치하는 매니저 클래스 (Package SGOS)
BORIDENT (IS_OBJECT) 첨부 대상 객체 키 — OBJTYPE(BUS2012 등) + OBJKEY(PO 번호 등)
SRGBRBREL BOR 객체 ↔ 첨부 관계 마스터 테이블
SOFFCONT1 실제 첨부파일 본문 저장 (SAP Office Content)
CL_GUI_CONTAINER GOS 아이콘이 그려질 컨테이너 (Docking / Custom Subscreen)

자주 사용하는 BOR 객체 유형:

OBJTYPE 대상 OBJKEY 예시
BUS2012 구매오더 (PO) 4500000001
BUS2017 자재문서 (GR) 50000000012026 (MBLNR + MJAHR)
BUS2081 송장 (MIRO) 51000000012026
BUS1001 자재 마스터 TEST-MAT-001
BKPF 회계전표 회사코드 + 전표번호 + 회계연도
LFA1 거래처 마스터 거래처 번호

회사 자체 Z 객체에도 첨부를 붙이려면 SE80 에서 BOR 객체를 신규 생성하거나(SWO1) Generic OAC0 저장소를 활용하는 방법이 있지만, 표준 객체에 붙이는 게 가장 일반적입니다.


1단계 — 인스턴스 생성 (가장 기본)

PO 번호 4500000001 에 첨부파일 서비스를 붙이는 표준 패턴.

DATA: go_gos_manager TYPE REF TO cl_gos_manager,
      go_container   TYPE REF TO cl_gui_custom_container,
      ls_object      TYPE borident.

" 1) 컨테이너 생성 (예: Custom Subscreen 안의 'GOS_AREA')
go_container = NEW #( container_name = 'GOS_AREA' ).

" 2) BOR 객체 키 채우기
ls_object-objtype = 'BUS2012'.       " PO
ls_object-objkey  = '4500000001'.

" 3) GOS Manager 인스턴스 생성
go_gos_manager = NEW #(
    io_container = go_container
    is_object    = ls_object
    ip_mode      = 'E'                " E = Edit · A = Display
    ip_no_commit = 'X'
).

4가지 핵심 파라미터:

  • io_container — GOS 아이콘이 그려질 화면 컨테이너
  • is_object — 첨부 대상 BOR 객체 키 (없으면 아이콘 안 생김)
  • ip_mode'E' 변경 가능 · 'A' 조회 전용
  • ip_no_commit'X' 권장(호출자가 COMMIT 책임)

인스턴스 생성 직후 컨테이너 영역에 GOS 아이콘이 표시됩니다. 사용자가 클릭하면 표준 서비스 메뉴(첨부파일 만들기 · 첨부 목록 · 노트 · 송신 등) 가 펼쳐집니다.


2단계 — IS_OBJECT 없는 경우 (아이콘 없이 첨부 list 만 출력)

PO 번호가 아직 확정 안 된 신규 생성 화면 같은 케이스에서는 is_object 를 비우고 호출하면 아이콘 없이 첨부 list 만 출력 됩니다.

go_gos_manager = NEW #(
    io_container = go_container
*   is_object    = ls_object          " 비움
    ip_mode      = 'E'
    ip_no_commit = 'X'
).

이 방식은 신규 생성 시점에 첨부를 임시로 받아두고, 저장 후 PO 번호가 생기면 그때 SET_ID_OF_PUBLISHED_OBJECT 로 연결하는 흐름에 사용합니다.

" 신규 생성 직후 PO 번호 확정 → 첨부와 연결
ls_object-objtype = 'BUS2012'.
ls_object-objkey  = lv_new_ebeln.        " 방금 생성된 PO 번호

CALL METHOD go_gos_manager->set_id_of_published_object
  EXPORTING
    is_object = ls_object
  EXCEPTIONS
    no_publication = 1.

생성 흐름에서 활용도가 높은 메소드입니다. BAPI_PO_CREATE1 + GOS 첨부를 함께 묶을 때 표준 패턴.


3단계 — Dynpro 화면에 컨테이너 배치

GOS 아이콘을 보여줄 영역은 Dynpro 화면에 미리 잡아둡니다.

SE51 → Dynpro 100 → Layout
 → "Custom Control" 도구 선택
 → 영역 드래그 (가로 4 / 세로 1 정도)
 → 이름: GOS_AREA

흐름 로직(PBO) 에서 컨테이너 생성:

PROCESS BEFORE OUTPUT.
  MODULE pbo_0100.
MODULE pbo_0100 OUTPUT.
  " 컨테이너 + GOS Manager 가 아직 안 만들어졌을 때만 생성
  IF go_container IS INITIAL.
    go_container = NEW #( container_name = 'GOS_AREA' ).

    ls_object-objtype = 'BUS2012'.
    ls_object-objkey  = lv_ebeln.

    go_gos_manager = NEW #(
        io_container = go_container
        is_object    = ls_object
        ip_mode      = 'E'
        ip_no_commit = 'X'
    ).
  ENDIF.
ENDMODULE.

PBO 에서 매번 인스턴스를 새로 만들지 않도록 IF 가드 — 한 번 생성된 GOS Manager 는 화면이 다시 그려져도 그대로 유지됩니다. 매번 생성하면 메모리 누수 + 성능 저하.


4단계 — 조회 vs 변경 모드 분기

표준 트랜잭션 동작과 일관되게 — 조회 화면에서는 첨부 추가 / 삭제가 안 되도록 잠금.

DATA lv_mode TYPE sgs_rwmod.

" T-Code 가 MM03 / ME23N 같은 조회면 'A', 아니면 'E'
IF sy-tcode CP 'M*03' OR sy-tcode CP '*23N'.
  lv_mode = 'A'.        " Display only
ELSE.
  lv_mode = 'E'.        " Edit
ENDIF.

go_gos_manager = NEW #(
    io_container = go_container
    is_object    = ls_object
    ip_mode      = lv_mode
    ip_no_commit = 'X'
).

또는 사용자 권한에 따라 분기:

AUTHORITY-CHECK OBJECT 'Z_GOS_ATTACH'
  ID 'ACTVT' FIELD '02'.            " 02 = Change

IF sy-subrc = 0.
  lv_mode = 'E'.
ELSE.
  lv_mode = 'A'.
ENDIF.

5단계 — 첨부파일 유무 체크

첨부가 있는지 미리 알고 화면 라벨에 "📎" 표시를 추가하거나, 첨부 강제 정책을 검증할 때 사용. 두 가지 방식.

방법 A — SRGBRBREL 직접 조회

SELECT COUNT(*)
  INTO @DATA(lv_atta_count)
  FROM srgbrbrel
 WHERE instid_a = @lv_ebeln
   AND typeid_a = 'BUS2012'
   AND catid_a  = 'BO'
   AND reltype  = 'ATTA'.

IF lv_atta_count > 0.
  " 첨부 있음 — 아이콘 표시 등
ENDIF.

방법 B — 표준 FM BINARY_RELATION_GET_ALL_PREDEC

DATA: lt_relations TYPE TABLE OF brelations,
      ls_lpor      TYPE sibflporb.

ls_lpor-typeid = 'BUS2012'.
ls_lpor-instid = lv_ebeln.
ls_lpor-catid  = 'BO'.

CALL FUNCTION 'BINARY_RELATION_GET_ALL_PREDEC'
  EXPORTING
    object_a = ls_lpor
    relation = 'ATTA'
  TABLES
    objects  = lt_relations
  EXCEPTIONS
    OTHERS   = 1.

IF lines( lt_relations ) > 0.
  " 첨부 있음
ENDIF.

대용량 ALV 에서는 방법 A 가 빠릅니다 — 표준 FM 은 라인별 호출 시 오버헤드. 천 건 단위라면 SELECT 한 번으로 끝.


6단계 — 첨부파일 종류와 SRGBRBREL 의 RELTYPE

GOS 가 다루는 관계는 RELTYPE 으로 구분됩니다.

RELTYPE 의미
ATTA 일반 첨부파일 (PDF · XLS · 이미지 등)
NOTE 텍스트 노트
URL 외부 URL 링크
BDS_TOID Business Document Service 첨부

회사 정책에 따라 ATTA 만 허용하고 URL / NOTE 는 막아두는 경우도 있습니다. it_service_selection 파라미터에서 노출할 서비스를 필터링 가능합니다.


흔히 빠뜨리는 함정

Custom Subscreen 컨테이너 미준비

Dynpro 화면에 GOS_AREA 같은 Custom Control 을 미리 그려두지 않으면 CL_GUI_CUSTOM_CONTAINER 생성에서 예외. Layout 단계에서 영역을 먼저 그리고 그 영역명을 코드에서 동일하게 사용.

IS_OBJECT 없는데 ip_start_direct 도 없음

is_object 가 비고 ip_start_direct 도 'X' 안 주면 아이콘도 안 보이고 list 도 안 뜹니다. 신규 생성 시나리오는 ip_start_direct = 'X' 추가.

PBO 매 사이클마다 인스턴스 생성

화면이 PAI → PBO 다시 그려질 때마다 NEW cl_gos_manager 가 호출되면 메모리 누수 + 깜빡임 + 컨테이너 중복. IF 가드로 한 번만 생성.

ip_no_commit 미설정 시 자동 COMMIT

기본값 'X'(no commit) 이지만 명시적으로 ' '로 넘기면 GOS 가 첨부 저장 시 COMMIT WORK 를 직접 호출합니다. 호출 프로그램의 트랜잭션 LUW 와 충돌 가능성이 있어 거의 항상 'X' 권장.

BOR 객체 키 길이

BORIDENT-OBJKEY 는 최대 70자. PO 번호처럼 짧은 키는 문제없지만 자재문서(MBLNR 10 + MJAHR 4 = 14자) 처럼 복합 키는 정확한 자리수로 채워야 합니다.

한 화면에 여러 GOS

같은 화면에 PO + 자재문서 두 개의 GOS 를 동시에 띄우려면 컨테이너 + GOS Manager 인스턴스를 각각 별개로 두 개 만들어야 합니다. 한 객체로 둘 다 처리 불가.

Z 객체에 첨부 붙이기

표준 BOR 객체가 없는 회사 자체 객체에 첨부를 붙이려면 SWO1 으로 BOR 객체를 신규 생성하거나 generic 객체(OAC0) 를 활용. 단순 ZAP* T-Code 에 그냥 GOS Manager 만 띄우면 SAP 가 객체를 인식 못 해 첨부 저장이 안 됩니다.

동시 사용자 락 / 권한

표준 트랜잭션이 이미 PO 를 락(SM12) 중일 때 GOS 첨부 추가가 안 되거나 권한 부족으로 실패할 수 있습니다. 사용자 권한(S_BDS_FOLD 등) 도 함께 점검.


전체 코드 — 복사용 통합본

*&---------------------------------------------------------------------*
*& 모듈 풀  Z_XX_GOS_DEMO  (Custom Subscreen 0100 + GOS_AREA 영역)
*&---------------------------------------------------------------------*

REPORT z_xx_gos_demo.

DATA: go_gos_manager TYPE REF TO cl_gos_manager,
      go_container   TYPE REF TO cl_gui_custom_container,
      ls_object      TYPE borident,
      lv_ebeln       TYPE ekko-ebeln VALUE '4500000001',
      lv_mode        TYPE sgs_rwmod.

CALL SCREEN 100.

*---------------------------------------------------------------------*
*  PBO Module
*---------------------------------------------------------------------*
MODULE pbo_0100 OUTPUT.

  " ★ 한 번만 생성 가드
  IF go_container IS INITIAL.

    " 컨테이너 생성 (Dynpro Layout 에 GOS_AREA Custom Control 그려져 있어야 함)
    go_container = NEW #( container_name = 'GOS_AREA' ).

    " BOR 객체 키 채움
    ls_object-objtype = 'BUS2012'.       " PO
    ls_object-objkey  = lv_ebeln.

    " T-Code 따라 조회/변경 모드 결정
    IF sy-tcode CP '*03' OR sy-tcode CP '*23N'.
      lv_mode = 'A'.
    ELSE.
      lv_mode = 'E'.
    ENDIF.

    " ★ GOS Manager 인스턴스 생성
    go_gos_manager = NEW #(
        io_container = go_container
        is_object    = ls_object
        ip_mode      = lv_mode
        ip_no_commit = 'X'
    ).

  ENDIF.

ENDMODULE.

*---------------------------------------------------------------------*
*  PAI Module
*---------------------------------------------------------------------*
MODULE user_command_0100 INPUT.

  CASE sy-ucomm.

    WHEN 'BACK' OR 'EXIT' OR 'CANC'.

      " GOS Manager 정리
      IF go_gos_manager IS NOT INITIAL.
        CALL METHOD go_gos_manager->unpublish.
      ENDIF.

      LEAVE PROGRAM.

  ENDCASE.

ENDMODULE.

*---------------------------------------------------------------------*
*  첨부 유무 체크 (활용 예시)
*---------------------------------------------------------------------*
FORM check_attachment USING p_ebeln TYPE ekko-ebeln
                     CHANGING p_has_atta TYPE abap_bool.

  SELECT COUNT(*)
    INTO @DATA(lv_cnt)
    FROM srgbrbrel
   WHERE instid_a = @p_ebeln
     AND typeid_a = 'BUS2012'
     AND catid_a  = 'BO'
     AND reltype  = 'ATTA'.

  IF lv_cnt > 0.
    p_has_atta = abap_true.
  ELSE.
    p_has_atta = abap_false.
  ENDIF.

ENDFORM.

같이 보면 좋은 글:

  • "BAPI_PO_CREATE1 — 구매오더 생성 BAPI 호출 방법" — PO 생성 직후 SET_ID_OF_PUBLISHED_OBJECT 로 첨부 연결
  • "Screen Exit 커스텀 필드 추가 — MAP_DYNPRO_FIELDS BAdI 활용 방법" — 표준 화면에 GOS 컨테이너 끼우는 시나리오와 짝꿍
  • "BAdI 정의로 Screen Exit 구축 — Function Group · Screen · SUBSCRIBE 매핑" — 자체 BAdI 화면에 GOS 배치

요약

단계 하는 일 핵심 포인트
1 BOR 객체 결정 BUS2012·BUS2017·BUS2081 등 표준 객체
2 컨테이너 준비 SE51 Custom Control + CL_GUI_CUSTOM_CONTAINER
3 인스턴스 생성 is_object + ip_mode + ip_no_commit
4 PBO 가드 IF 가드로 1회만 생성 (메모리 누수 방지)
5 모드 분기 조회 = 'A' · 변경 = 'E' · 권한 / T-Code 기반
6 첨부 유무 체크 SRGBRBREL SELECT (대용량) / BINARY_RELATION_GET_ALL_PREDEC FM

CL_GOS_MANAGER 는 회사 자체 ALV / 화면에 표준 ME23N 수준의 첨부 UX 를 한 번에 끼워 넣어주는 가장 가벼운 도구입니다. 컨테이너 + IS_OBJECT + 모드 3가지만 정확히 채우면 첨부 / 노트 / 송신 / 워크플로우 같은 표준 서비스가 자동으로 따라옵니다. 신규 생성 흐름에서 객체 키가 나중에 정해지는 시나리오는 SET_ID_OF_PUBLISHED_OBJECT 로 후 연결하고, 대용량 ALV 의 첨부 유무 체크는 SRGBRBREL 직접 SELECT 가 가장 빠릅니다.


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

CL_GOS_MANAGER 시그니처 · BORIDENT 구조체 · SRGBRBREL 테이블 동작은 SAP NetWeaver 표준(패키지 SGOS · ECC 6.0 / S/4HANA on-premise) 기준이며, 사내 BOR 객체 / 권한 / 첨부 정책에 따라 일부 동작이 다를 수 있으니 운영 시스템 적용 전 개발·QA 환경에서 검증하시기 바랍니다. Z 자체 객체에 첨부를 붙이는 경우 SWO1 BOR 객체 정의 또는 Generic OAC0 저장소를 함께 검토하시기 바랍니다.