본문 바로가기
BAPI · BADI · RFC · Interface

[SAP ABAP] BAPI_MATERIAL_SAVEDATA 완전정복 - 자재 마스터 생성·변경 표준 BAPI (HEADDATA + X-구조 패턴)

by Song.sh 2026. 5. 21.

자재마스터(MM01) 를 자동으로 만들어야 하는 시나리오는 ABAP 개발에서 자주 만납니다. 외부 시스템에서 자재 정보를 수신해 SAP 에 동기화하거나, 엑셀 업로드 프로그램에서 한 번에 수십~수백 건의 자재를 생성하거나, MM01 자체에 BDC 를 거는 대신 표준 BAPI 로 깔끔하게 처리하고 싶을 때 — 표준 도구가 BAPI_MATERIAL_SAVEDATA 입니다.

 

다만 이 BAPI 는 옵션이 많아 첫 호출이 부담스럽습니다. 어떤 뷰를 만들지(기본·구매·MRP·회계·저장위치·원가) HEADDATA 의 플래그로 결정해야 하고, 뷰별로 데이터 구조체(BAPI_MARA·BAPI_MARC·BAPI_MBEW 등) 와 그 X-구조체(BAPI_MARAX·BAPI_MARCX 등) 를 한 쌍으로 매번 채워야 합니다. 회사 자체 확장 필드(BAPI_TE_MARA) 까지 들어가면 코드 라인 수가 더 늘어납니다.

 

이 글은 BAPI_MATERIAL_SAVEDATA 의 시그니처 전체 → HEADDATA 의 뷰 플래그 → CLIENTDATA·PLANTDATA·VALUATIONDATA·STORAGELOCATIONDATA 4종 뷰 데이터 + X-구조체 패턴 → MATERIALDESCRIPTION(자재내역) → EXTENSIONIN(자사 확장 필드) → COMMIT/ROLLBACK 흐름을 한 화면에 모은 메모입니다. 노트의 실제 호출 패턴을 그대로 살려 신규 자재 ROH(원료) 한 건을 생성하는 풀 예제를 끝에 같이 둡니다.


핵심 — IMPORTING 구조체 + X-구조체 한눈 비교

BAPI_MATERIAL_SAVEDATA 의 IMPORTING 은 "뷰별 데이터 구조체 + X-구조체 한 쌍" 패턴이 반복되는 구조.

파라미터 타입 담는 뷰 / 데이터
HEADDATA (필수) BAPIMATHEAD 자재번호·산업분야·자재유형 + 어떤 뷰를 만들지 플래그
CLIENTDATA + X BAPI_MARA·BAPI_MARAX 기본 뷰 — 자재그룹·기본단위·제품군·배치관리·중량
PLANTDATA + X BAPI_MARC·BAPI_MARCX 플랜트 뷰 — MRP 유형·가용성점검·로트사이즈·손익센터
VALUATIONDATA + X BAPI_MBEW·BAPI_MBEWX 회계 뷰 — 평가유형·평가영역·평가클래스
STORAGELOCATIONDATA + X BAPI_MARD·BAPI_MARDX 저장위치 뷰 — 플랜트 + 저장위치 키
SALESDATA + X BAPI_MVKE·BAPI_MVKEX 영업 뷰 — 영업조직·유통채널·품목범주그룹
FORECASTPARAMETERS + X BAPI_MPOP·BAPI_MPOPX 예측 파라미터 — Forecasting 뷰
PLANNINGDATA + X BAPI_MPGD·BAPI_MPGDX 계획 파라미터 — Demand Planning

핵심 한 줄: "데이터 + X-구조체 한 쌍" 패턴이 모든 뷰에 동일하게 적용됩니다. CLIENTDATA 에 값을 채우고 CLIENTDATAX 의 같은 필드에 'X' 마크 — BAPI_PO_CHANGE / BAPI_BATCH_CHANGE 와 동일한 패턴.


1단계 — HEADDATA: 자재 키 + 뷰 플래그

가장 먼저 채우는 부분. 자재번호·산업분야·자재유형 + 어떤 뷰를 만들지 를 결정하는 플래그가 들어 있습니다.

DATA(ls_headdata) = VALUE bapimathead(
  material       = 'TEST-MAT-001'      " 자재번호
  ind_sector     = 'M'                 " 산업분야 (M=Mechanical Engineering)
  matl_type      = 'ROH'               " 자재유형 (ROH=원료, FERT=완제품)

  " ★ 뷰 플래그 — 어떤 뷰를 만들지 결정
  basic_view     = abap_true           " 기본데이터 뷰
  purchase_view  = abap_true           " 구매 뷰
  mrp_view       = abap_true           " MRP 1~4 뷰
  account_view   = abap_true           " 회계 뷰
  storage_view   = abap_true           " 저장위치 뷰 + 일반 플랜트 데이터
  cost_view      = abap_true ).        " 원가 뷰
뷰 플래그 활성화되는 화면
BASIC_VIEW 기본데이터 1 / 기본데이터 2
PURCHASE_VIEW 구매 / 해외무역(수입) / 구매오더 텍스트
MRP_VIEW MRP 1 / 2 / 3 / 4
ACCOUNT_VIEW 회계 1 / 2
STORAGE_VIEW 일반 플랜트 데이터 / 저장위치 1·2
SALES_VIEW 영업 1 / 영업 2 / 영업 일반
COST_VIEW 원가계산 1 / 2

플래그를 켜지 않은 뷰는 BAPI 가 만들지 않습니다. 즉 "이 자재는 구매하지 않고 사내 생산만" 이라면 PURCHASE_VIEWabap_false 로 두면 됩니다.


2단계 — CLIENTDATA: 기본 뷰 데이터 + X-구조체

BASIC_VIEW = abap_trueCLIENTDATA 에 값 채우기.

DATA(ls_clientdata) = VALUE bapi_mara(
  matl_group  = '001'              " 자재그룹
  base_uom    = 'KG'               " 기본단위
  division    = '10'               " 제품군
  prod_hier   = 'W'                " 제품계층구조
  item_cat    = 'NORM'             " 일반품목범주 그룹
  batch_mgmt  = abap_true          " 배치 관리
  po_unit     = 'MT'               " 구매 단위
  net_weight  = '1'                " 순중량
  unit_of_wt  = 'KG' ).            " 중량 단위

" 변경 의도 매핑 — 채운 필드만 'X'
DATA(ls_clientdatax) = VALUE bapi_marax(
  matl_group  = abap_true
  base_uom    = abap_true
  division    = abap_true
  prod_hier   = abap_true
  item_cat    = abap_true
  batch_mgmt  = abap_true
  po_unit     = abap_true
  net_weight  = abap_true
  unit_of_wt  = abap_true ).

 

X-구조체의 동작 원리: BAPI 는 CLIENTDATAX 의 같은 필드에 'X' 가 있는 필드만 실제로 적용합니다. CLIENTDATA 에 값을 채워도 X-구조체에 마크 안 하면 무시됨. 두 구조체를 항상 한 쌍으로 관리.


3단계 — PLANTDATA: 플랜트 확장 (MRP·재고)

같은 패턴. 플랜트 단위로 MRP 유형·가용성점검·손익센터 등을 지정.

DATA(ls_plantdata) = VALUE bapi_marc(
  plant       = '0001'             " 플랜트
  mrp_type    = 'X0'               " MRP 유형
  availcheck  = '02'               " 가용성 점검
  mrp_ctrler  = '200'              " MRP 관리자
  sm_key      = '000'              " 일정 마진 키
  lotsizekey  = 'WB'               " 로트 크기
  profit_ctr  = 'P100' ).          " 손익센터

DATA(ls_plantdatax) = VALUE bapi_marcx(
  plant       = '0001'              " 키 필드는 X-구조체에도 값 그대로 (X 가 아닌 값)
  mrp_type    = abap_true
  availcheck  = abap_true
  mrp_ctrler  = abap_true
  sm_key      = abap_true
  lotsizekey  = abap_true
  profit_ctr  = abap_true ).

키 필드(플랜트) 의 특이점: 플랜트(PLANT) 같은 키 필드는 X-구조체에도 'X' 가 아니라 실제 값 을 채워야 합니다. BAPI 가 "어느 플랜트의 데이터인지" 식별하는 데 사용.


4단계 — VALUATIONDATA: 회계 뷰 (평가)

회계 뷰는 평가유형·평가영역(플랜트)·평가클래스를 가집니다.

DATA(ls_valuationdata) = VALUE bapi_mbew(
  val_type   = '01'                 " 평가유형
  val_area   = '0001'               " 평가영역 (= 플랜트)
  val_class  = '3000' ).            " 평가클래스 (회계 코드 카테고리)

DATA(ls_valuationdatax) = VALUE bapi_mbewx(
  val_type   = '01'                 " 키 — 그대로 값
  val_area   = '0001'               " 키 — 그대로 값
  val_class  = abap_true ).         " 'X' 마크

평가클래스는 회사가 IMG 에서 사전 정의한 값이므로 회사 정책 확인 후 채움. VAL_TYPE 은 일반적으로 비어 있고, 평가가 여러 유형으로 나뉘는 자재에만 채웁니다.


5단계 — STORAGELOCATIONDATA: 저장위치

플랜트 + 저장위치 키만 채우면 끝. 다른 필드는 거의 없습니다(저장위치는 키 자체가 데이터).

DATA(ls_storagelocationdata) = VALUE bapi_mard(
  plant     = '0001'                " 플랜트
  stge_loc  = '0001' ).             " 저장위치

DATA(ls_storagelocationdatax) = VALUE bapi_mardx(
  plant     = '0001'                " 키
  stge_loc  = '0001' ).             " 키

저장위치는 X-구조체에 별도 마크할 필드가 거의 없어 두 구조체가 거의 동일합니다.


6단계 — MATERIALDESCRIPTION: 자재 내역 (TABLES)

자재내역은 언어별 여러 줄이 가능하므로 TABLES 파라미터.

DATA: lt_makt TYPE TABLE OF bapi_makt.

APPEND VALUE #(
  langu      = sy-langu                                                        " 한국어
  langu_iso  = cl_i18n_languages=>sap1_to_sap2( im_lang_sap1 = sy-langu )      " ISO 코드 (KO)
  matl_desc  = '테스트 자재 - 원료' )
  TO lt_makt.

" 영어 자재내역도 같이 등록하려면 한 줄 더
APPEND VALUE #(
  langu      = 'E'
  langu_iso  = 'EN'
  matl_desc  = 'Test Material - Raw' )
  TO lt_makt.

LANGU_ISO 가 필수 입력. SY-LANGU(SAP 한 자리) 와 ISO(KO/EN) 변환은 CL_I18N_LANGUAGES=>SAP1_TO_SAP2 메소드 사용.


7단계 — EXTENSIONIN: 자사 확장 필드

자재마스터에 회사 자체 필드(ZZ_*) 를 추가한 경우 표준 CLIENTDATA 에는 그 필드가 없습니다. 대신 EXTENSIONIN(BAPIPAREX) 에 자사 확장 구조체(BAPI_TE_MARA) 를 넣어 전달.

" 자사 확장 구조체 (Append Structure)
DATA(ls_teitem) = VALUE bapi_te_mara(
  material = 'TEST-MAT-001'
  zgubun   = 'D' ).                 " 자사 추가 필드

DATA(ls_teitemx) = VALUE bapi_te_marax(
  material = 'TEST-MAT-001'
  zgubun   = abap_true ).

" EXTENSIONIN 테이블에 담기
DATA: lt_extensionin  TYPE TABLE OF bapiparex,
      lt_extensioninx TYPE TABLE OF bapiparexx.

APPEND VALUE #(
  structure  = 'BAPI_TE_MARA'        " 자사 확장 구조체 이름
  valuepart1 = ls_teitem )           " 데이터를 캐스팅
  TO lt_extensionin.

APPEND VALUE #(
  structure  = 'BAPI_TE_MARAX'
  valuepart1 = ls_teitemx )
  TO lt_extensioninx.

주의: EXTENSIONIN 이 작동하려면 IMG 의 BAPI 매핑 등록 + BAdI 구현 이 사전에 되어 있어야 합니다. 단순 코드만 짜고 매핑이 빠지면 BAPI 가 EXTENSIONIN 데이터를 받기는 받지만 자재마스터에 반영 안 됨.

자사 환경에 따라 BAPI_TE_MARA·BAPI_TE_MARAX 외에 플랜트 확장(BAPI_TE_MARC)·회계 확장(BAPI_TE_MBEW) 도 같은 패턴으로 추가.


8단계 — BAPI 호출 + COMMIT/ROLLBACK

데이터 준비 끝나면 BAPI 한 줄 호출. 결과 메시지 확인 후 명시적 COMMIT 또는 ROLLBACK.

DATA: ls_return         TYPE bapiret2,
      lt_returnmessages TYPE TABLE OF bapi_matreturn2.

CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
  EXPORTING
    headdata             = ls_headdata
    clientdata           = ls_clientdata
    clientdatax          = ls_clientdatax
    plantdata            = ls_plantdata
    plantdatax           = ls_plantdatax
    valuationdata        = ls_valuationdata
    valuationdatax       = ls_valuationdatax
    storagelocationdata  = ls_storagelocationdata
    storagelocationdatax = ls_storagelocationdatax
  IMPORTING
    return               = ls_return
  TABLES
    materialdescription  = lt_makt
    returnmessages       = lt_returnmessages
    extensionin          = lt_extensionin
    extensioninx         = lt_extensioninx.

" 상세 메시지 출력
LOOP AT lt_returnmessages ASSIGNING FIELD-SYMBOL(<msg>).
  WRITE: / |[{ <msg>-type }] { <msg>-id } { <msg>-number } { <msg>-message }|.
ENDLOOP.

" 결과 분기
IF ls_return-type = 'E' OR ls_return-type = 'A'.
  CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  WRITE: / |❌ 자재 생성 실패: { ls_return-message }|.
ELSE.
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'.
  WRITE: / |✅ 자재 { ls_headdata-material } 생성 완료|.
ENDIF.

핵심 포인트:

  • RETURN(단일) + RETURNMESSAGES(TABLES) 두 가지 메시지 — 둘 다 확인
  • BAPI_TRANSACTION_COMMIT 안 부르면 DB 반영 안 됨
  • wait = 'X' 동기 커밋 권장 (이어지는 코드가 자재 즉시 조회 가능)

흔히 빠뜨리는 함정

CLIENTDATAX 'X' 마크 누락

" ❌ 값만 채우고 X-구조체 안 채움
ls_clientdata-matl_group = '001'.
" ls_clientdatax-matl_group = abap_true.    누락

BAPI 가 "변경 의도 없음" 으로 해석해 그 필드를 무시. 자재는 생성되지만 자재그룹이 비어 있는 사고. 값 채우는 줄과 X 마크 줄을 한 쌍으로 관리.

BAPI_TRANSACTION_COMMIT 누락

CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA' ...
" ❌ COMMIT 안 부름 → DB 반영 X
SELECT SINGLE * FROM mara WHERE matnr = lv_matnr ...   " 결과 없음

BAPI 자체는 DB 직접 안 씀. BAPI_TRANSACTION_COMMIT 호출 필수.

자재유형(MTART) 누락

ls_headdata-material   = 'TEST-MAT-001'.
" ❌ matl_type 누락 → BAPI 에러

MATL_TYPE·IND_SECTOR 는 자재 생성 시 필수. 변경(이미 있는 자재) 시는 생략 가능하지만 신규는 필수.

뷰 플래그 안 켜고 데이터만 채움

ls_headdata-mrp_view = abap_false.   " ❌ MRP 뷰 안 만듦
ls_plantdata-mrp_type = 'X0'.        " 그런데 MRP 데이터는 채움

뷰 플래그가 꺼져 있으면 해당 데이터는 무시됩니다. 데이터를 채우면 그 뷰의 플래그도 같이 켜기.

LANGU_ISO 누락

APPEND VALUE #(
  langu     = sy-langu
  matl_desc = '테스트' )
  TO lt_makt.
" ❌ langu_iso 누락 → BAPI 가 거부

자재내역(BAPI_MAKT) 은 LANGU(1자리 SAP 코드) + LANGU_ISO(2자리 ISO) 둘 다 필수. 변환은 CL_I18N_LANGUAGES.

EXTENSIONIN IMG 매핑 누락

자사 확장 필드(BAPI_TE_MARA)를 코드로 넘겨도 SAP IMG 에 BAPI 매핑 + BAdI 구현 등록이 안 되어 있으면 BAPI 가 받기만 하고 자재마스터에 반영 안 합니다. 운영팀과 사전 셋업 확인 필수.

RETURNMESSAGES 무시

IF ls_return-type = 'E'.
  " ❌ lt_returnmessages 안 보고 단일 RETURN 만 확인
ENDIF.

RETURN 은 마지막 한 줄만 담고, RETURNMESSAGES 가 전체 메시지. 부분 실패(예: 자재는 생성됐는데 특정 뷰 일부만 실패) 같은 케이스는 RETURNMESSAGES 봐야 정확한 진단.

동일 키 재호출 시 에러 처리

" 자재가 이미 존재하는데 신규 생성 의도로 같은 키 호출
" → BAPI 가 변경 모드로 처리 (생성 안 함)
" → RETURN 은 성공이지만 데이터 갱신만 됨

BAPI_MATERIAL_SAVEDATA 는 자재 존재 여부에 따라 자동으로 생성/변경을 결정. 의도적으로 "존재하면 실패" 가 필요하면 호출 전 SELECT SINGLE FROM mara 로 존재 확인.


전체 코드 — 복사용 통합본

신규 자재 ROH(원료) 한 건을 6개 뷰로 생성하는 전체 예제. 노트의 패턴 그대로 + 마스킹.

REPORT zr_bapi_material_savedata_demo.

TYPES: ty_makt TYPE TABLE OF bapi_makt WITH DEFAULT KEY,
       ty_extin TYPE TABLE OF bapiparex WITH DEFAULT KEY,
       ty_extinx TYPE TABLE OF bapiparexx WITH DEFAULT KEY.

DATA: ls_return         TYPE bapiret2,
      lt_returnmessages TYPE TABLE OF bapi_matreturn2.

* === HEADDATA: 자재 키 + 뷰 플래그 ===
DATA(ls_headdata) = VALUE bapimathead(
  material       = 'TEST-MAT-001'
  ind_sector     = 'M'
  matl_type      = 'ROH'
  basic_view     = abap_true
  purchase_view  = abap_true
  mrp_view       = abap_true
  account_view   = abap_true
  storage_view   = abap_true
  cost_view      = abap_true ).

* === CLIENTDATA: 기본 뷰 ===
DATA(ls_clientdata) = VALUE bapi_mara(
  matl_group  = '001'
  base_uom    = 'KG'
  division    = '10'
  prod_hier   = 'W'
  item_cat    = 'NORM'
  batch_mgmt  = abap_true
  po_unit     = 'MT'
  net_weight  = '1'
  unit_of_wt  = 'KG' ).

DATA(ls_clientdatax) = VALUE bapi_marax(
  matl_group  = abap_true
  base_uom    = abap_true
  division    = abap_true
  prod_hier   = abap_true
  item_cat    = abap_true
  batch_mgmt  = abap_true
  po_unit     = abap_true
  net_weight  = abap_true
  unit_of_wt  = abap_true ).

* === PLANTDATA: 플랜트 (MRP 1~4) ===
DATA(ls_plantdata) = VALUE bapi_marc(
  plant       = '0001'
  mrp_type    = 'X0'
  availcheck  = '02'
  mrp_ctrler  = '200'
  sm_key      = '000'
  lotsizekey  = 'WB'
  profit_ctr  = 'P100' ).

DATA(ls_plantdatax) = VALUE bapi_marcx(
  plant       = '0001'
  mrp_type    = abap_true
  availcheck  = abap_true
  mrp_ctrler  = abap_true
  sm_key      = abap_true
  lotsizekey  = abap_true
  profit_ctr  = abap_true ).

* === VALUATIONDATA: 회계 뷰 ===
DATA(ls_valuationdata) = VALUE bapi_mbew(
  val_area   = '0001'
  val_class  = '3000' ).

DATA(ls_valuationdatax) = VALUE bapi_mbewx(
  val_area   = '0001'
  val_class  = abap_true ).

* === STORAGELOCATIONDATA: 저장위치 ===
DATA(ls_storagelocationdata) = VALUE bapi_mard(
  plant     = '0001'
  stge_loc  = '0001' ).

DATA(ls_storagelocationdatax) = VALUE bapi_mardx(
  plant     = '0001'
  stge_loc  = '0001' ).

* === MATERIALDESCRIPTION: 자재 내역 (TABLES) ===
DATA(lt_makt) = VALUE ty_makt(
  ( langu     = sy-langu
    langu_iso = cl_i18n_languages=>sap1_to_sap2( im_lang_sap1 = sy-langu )
    matl_desc = '테스트 자재 - 원료' )
  ( langu     = 'E'
    langu_iso = 'EN'
    matl_desc = 'Test Material - Raw' ) ).

* === EXTENSIONIN: 자사 확장 필드 (선택) ===
DATA(ls_teitem) = VALUE bapi_te_mara(
  material = 'TEST-MAT-001'
  zgubun   = 'D' ).
DATA(ls_teitemx) = VALUE bapi_te_marax(
  material = 'TEST-MAT-001'
  zgubun   = abap_true ).

DATA(lt_extensionin) = VALUE ty_extin(
  ( structure  = 'BAPI_TE_MARA' valuepart1 = ls_teitem ) ).
DATA(lt_extensioninx) = VALUE ty_extinx(
  ( structure  = 'BAPI_TE_MARAX' valuepart1 = ls_teitemx ) ).

* === BAPI 호출 ===
CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
  EXPORTING
    headdata             = ls_headdata
    clientdata           = ls_clientdata
    clientdatax          = ls_clientdatax
    plantdata            = ls_plantdata
    plantdatax           = ls_plantdatax
    valuationdata        = ls_valuationdata
    valuationdatax       = ls_valuationdatax
    storagelocationdata  = ls_storagelocationdata
    storagelocationdatax = ls_storagelocationdatax
  IMPORTING
    return               = ls_return
  TABLES
    materialdescription  = lt_makt
    returnmessages       = lt_returnmessages
    extensionin          = lt_extensionin
    extensioninx         = lt_extensioninx.

* === 상세 메시지 출력 ===
LOOP AT lt_returnmessages ASSIGNING FIELD-SYMBOL(<m>).
  WRITE: / |[{ <m>-type }] { <m>-id }-{ <m>-number } { <m>-message }|.
ENDLOOP.

* === COMMIT / ROLLBACK ===
IF ls_return-type = 'E' OR ls_return-type = 'A'.
  CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  WRITE: /, / |❌ 자재 생성 실패: { ls_return-message }|.
ELSE.
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'.
  WRITE: /, / |✅ 자재 { ls_headdata-material } 생성 완료|.
ENDIF.

이 미니 리포트를 SE38 에 그대로 붙여 실행하면 자재번호 + 6개 뷰 + 한글/영문 자재내역 + 자사 확장 필드까지 한 번에 생성됩니다. 자사 환경의 자재그룹·평가클래스·플랜트·MRP 컨트롤러 코드만 사내 표준값으로 교체.


요약

단계 파라미터 핵심
1 HEADDATA 자재키 + 6개 뷰 플래그 (BASIC/PURCHASE/MRP/ACCOUNT/STORAGE/COST)
2 CLIENTDATA + X 기본 뷰 — 자재그룹·단위·중량
3 PLANTDATA + X MRP 유형·로트사이즈·손익센터
4 VALUATIONDATA + X 평가클래스·평가영역
5 STORAGELOCATIONDATA + X 플랜트 + 저장위치 키
6 MATERIALDESCRIPTION 언어별 자재내역 (LANGU + LANGU_ISO)
7 EXTENSIONIN + X 자사 확장 필드 (BAPI_TE_MARA / IMG 매핑 필요)
8 COMMIT BAPI_TRANSACTION_COMMIT 명시 호출 (wait = 'X')

BAPI_MATERIAL_SAVEDATA 의 핵심은 "데이터 구조체 + X-구조체 한 쌍" 패턴이 모든 뷰에 동일하게 적용된다는 점입니다. 첫 호출은 부담스럽지만 한 번 패턴을 잡으면 자재유형별·플랜트별 변형을 쉽게 만들 수 있고, 외부 시스템에서 받은 자재 정보를 자동 동기화하는 인터페이스에 그대로 재사용 가능합니다. 자재유형 누락·X-마크 누락·BAPI_TRANSACTION_COMMIT 누락 세 가지 함정만 피하면 안정적으로 동작하며, 자사 확장 필드(EXTENSIONIN) 는 코드 외에 IMG 매핑이 같이 가야 작동한다는 점만 기억하면 됩니다.


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

BAPI_MATERIAL_SAVEDATA 는 SAP MM 표준 BAPI(Function Group 1001UEB, Package MGA) 로 ECC 6.0 / S/4HANA on-premise 환경에서 동일하게 동작합니다.

 

HEADDATA(BAPIMATHEAD) 의 view 플래그(BASIC_VIEW · PURCHASE_VIEW · MRP_VIEW · ACCOUNT_VIEW · STORAGE_VIEW · COST_VIEW · SALES_VIEW) 가 어떤 뷰를 생성/변경할지 결정하며, 데이터 구조체(BAPI_MARA · BAPI_MARC · BAPI_MBEW · BAPI_MARD 등) 의 변경 의도는 항상 대응되는 X-구조체(BAPI_MARAX · BAPI_MARCX 등) 의 같은 필드에 'X' 마크로 표현되어야 합니다.

 

BAPI 호출 후 BAPI_TRANSACTION_COMMIT 을 명시적으로 호출해야 DB 에 반영되며, 자사 확장 필드(BAPI_TE_MARA 등) 를 EXTENSIONIN 으로 전달할 경우 SAP IMG 의 BAPI 매핑 등록 + BAdI 구현이 사전에 되어 있어야 데이터가 실제로 자재마스터에 반영됩니다. 본문의 자재번호·플랜트·평가클래스·MRP 컨트롤러 등은 회사 정책에 따라 다르므로 사내 표준값으로 교체하여 사용하시기 바랍니다.