ABAP

COEP 직접 JOIN하면 큰일 — CO 활동 CDS View #shorts #SAP #ABAP

▶ YouTube에서 보기

1. CO 모듈에서 원가 센터 활동이란 무엇인가

SAP Controlling(CO) 모듈에서 원가 센터(Cost Center)는 기업 내부에서 비용이 발생하는 책임 단위를 의미합니다. 그러나 단순히 비용을 모으는 그릇에 그치지 않고, 다른 원가 객체로 비용을 흘려보내는 송신처 역할도 수행합니다. 이때 "얼마나 일했는가"를 측정하는 단위가 바로 활동(Activity)입니다. 예컨대 생산 부서의 원가 센터가 한 달 동안 1,200 머신 시간을 가동했다면, 이 머신 시간이 활동량(Activity Quantity)이 되고, 사전에 계획된 활동 단가(Activity Price)를 곱해 수요처(제품 오더, 프로젝트, 다른 원가 센터)로 비용이 배분됩니다.

S/4HANA 환경에서는 이러한 활동 정보를 전통적인 테이블(COSL, COSP, COEP)에서 직접 읽기보다 가상 데이터 모델(VDM, Virtual Data Model)로 재구성한 CDS View를 통해 노출합니다. I_CostCenterActivity는 그러한 VDM 계층에서 원가 센터별 활동 데이터를 표준화된 형태로 제공하는 인터페이스 뷰입니다. 이 글에서는 해당 뷰의 구조와 운영 적용 방법을 깊이 있게 살펴봅니다.

활동 배분(Activity Allocation)은 CO 모듈의 핵심 메커니즘으로, 직접 활동 배분(KB21N), 간접 활동 배분(KSC5), 템플릿 배분 등 다양한 방식이 존재하며 모두 공통적으로 원가 센터·활동 유형·수신자라는 3차원 구조를 따릅니다.

2. I_CostCenterActivity CDS View의 위치와 역할

SAP S/4HANA의 VDM은 일반적으로 3계층(Basic Interface View → Composite Interface View → Consumption View)으로 설계됩니다. I_ 접두사가 붙은 뷰는 Interface View로, 재사용을 전제로 한 안정적인 데이터 인터페이스 역할을 수행합니다. I_CostCenterActivity는 그 중에서도 CO 영역의 원가 센터-활동 조합 정보를 다른 분석/거래 View가 참조할 수 있도록 표준화한 모델입니다.

실제 데이터 원천은 활동 유형 마스터(테이블 CSLA, CSLT), 원가 센터 마스터(CSKS, CSKT), 그리고 계획/실적 라인 아이템(COEP, ACDOCA)이 결합된 형태로 구성됩니다. S/4HANA 1909 이후로는 Universal Journal(ACDOCA)에 활동 배분 결과가 통합되어 있어, CDS View가 이를 깔끔하게 추상화하여 노출합니다.

이 뷰는 단독으로도 활용 가능하지만, Fiori Elements 기반 분석 앱, CDS Analytical Query, Embedded Analytics, 또는 SAP Analytics Cloud Live Connection 시나리오에서 빌딩 블록으로 사용되는 빈도가 높습니다. 다시 말해, 직접 SELECT 문으로 호출하는 것뿐 아니라 Composite View가 association으로 끌어쓰는 케이스를 함께 고려해야 합니다.

3. 핵심 필드 구조 상세 분석

뷰가 노출하는 주요 필드는 마스터성 정보와 측정값으로 구분됩니다. 키 필드는 컨트롤링 영역과 원가 센터, 활동 유형, 회계연도 단위로 구성되는 것이 일반적입니다.

// I_CostCenterActivity 인터페이스 뷰 활용 시 자주 참조되는 필드 예시
// (실제 시그니처는 시스템 릴리스에 따라 차이가 있을 수 있음)

key ControllingArea          // 컨트롤링 영역 (KOKRS)
key CostCenter               // 원가 센터 (KOSTL)
key ActivityType             // 활동 유형 (LSTAR)
key FiscalYear               // 회계연도

    CostCenterActivityUUID   // 기술 식별자
    ValidityStartDate        // 유효 시작일
    ValidityEndDate          // 유효 종료일

    ActivityUnit             // 활동 단위 (MEINH)
    ActivityTypeCategory     // 활동 유형 카테고리 (1: 수기, 2: 간접배분 등)
    AllocationCostElement    // 배분 원가 요소 (2차 원가 요소)

    PlannedActivityQuantity  // 계획 활동량
    ActualActivityQuantity   // 실적 활동량
    PlannedActivityPrice     // 계획 단가
    ActualActivityPrice      // 실적 단가

주목할 부분은 ActivityTypeCategory입니다. 이 값에 따라 배분 방식이 달라집니다. 카테고리 1은 수기 입력(KB21N) 기반 직접 배분, 2는 수신자 정보가 자동 산정되는 간접 배분, 3은 수동 입력 + 간접 결정의 혼합, 4는 계획에만 사용되고 5는 목표 배분 시나리오에서 활용됩니다.

또한 AllocationCostElement는 반드시 2차 원가 요소(Secondary Cost Element, 카테고리 43)여야 합니다. S/4HANA에서는 G/L 계정과 통합되었으므로 동일 계정이 G/L 계정 테이블(SKA1)에도 존재합니다.

4. 활동 유형(Activity Type)과 배분 메커니즘

활동 유형은 원가 센터가 "어떤 일을 했는지"를 분류하는 차원입니다. 예를 들어 정비 부서 원가 센터는 "예방정비시간"과 "긴급정비시간"이라는 두 개의 활동 유형을 가질 수 있습니다. 활동 유형별로 단가가 다르게 매겨지고, 단가의 산정 방법(ActivityTypePricingIndicator)도 정치적으로 결정됩니다.

배분의 흐름은 다음 도식으로 이해하면 쉽습니다.

[송신 원가센터]              [수신자]
정비부서 CC1000              생산오더 PO-4711
+ 활동유형 LABOR    ──────▶  + 시간 8h
+ 단가 $50/h                 + 차변 $400
+ 활동량 8h
       │
       └─ 2차 원가요소 943000 (LABOR 배분)을 통해 회계 처리

이때 I_CostCenterActivity는 송신 측 정보(원가 센터·활동 유형·계획 단가·실적 단가)를 제공하고, 수신 측 라인 아이템은 별도의 CDS View(예: I_JournalEntryItem 또는 I_ActualCostsByCstCtrAndActivityType 류)와 association으로 결합됩니다. 권장되는 접근은 I_CostCenterActivity를 마스터 차원으로 두고, 트랜잭션 데이터는 Universal Journal CDS View에서 조회한 뒤 association으로 마스터를 lookup하는 구조입니다.

5. ABAP으로 I_CostCenterActivity 데이터 조회하기 (실전 예제)

가장 기본적인 형태부터 시작합니다. 특정 컨트롤링 영역과 회계연도의 활동 마스터를 조회하는 예제입니다.

REPORT zr_co_activity_basic.

DATA: lt_activity TYPE TABLE OF i_costcenteractivity,
      lv_kokrs    TYPE kokrs VALUE 'A000',
      lv_year     TYPE gjahr VALUE '2026'.

SELECT controllingarea,
       costcenter,
       activitytype,
       activityunit,
       plannedactivityquantity,
       actualactivityquantity,
       plannedactivityprice
  FROM i_costcenteractivity
  WHERE controllingarea = @lv_kokrs
    AND fiscalyear      = @lv_year
  INTO TABLE @lt_activity.

LOOP AT lt_activity ASSIGNING FIELD-SYMBOL(<fs_act>).
  WRITE: / <fs_act>-costcenter,
           <fs_act>-activitytype,
           <fs_act>-plannedactivityquantity,
           <fs_act>-activityunit.
ENDLOOP.

실무에서는 단순 조회로 끝나지 않습니다. 활동량과 단가를 곱해 계획 비용을 산출하고, 예외 상황(단가 미입력, 활동량 0)에 대한 방어 코드를 함께 작성해야 합니다.

REPORT zr_co_planned_cost_calc.

TYPES: BEGIN OF ty_planned,
         cost_center  TYPE kostl,
         activity_typ TYPE lstar,
         planned_qty  TYPE p LENGTH 13 DECIMALS 3,
         planned_prc  TYPE p LENGTH 13 DECIMALS 2,
         planned_cost TYPE p LENGTH 15 DECIMALS 2,
         currency     TYPE waers,
       END OF ty_planned.

DATA: lt_result TYPE TABLE OF ty_planned.

TRY.
    SELECT controllingarea,
           costcenter,
           activitytype,
           plannedactivityquantity,
           plannedactivityprice,
           currency
      FROM i_costcenteractivity
      WHERE controllingarea = @( CONV kokrs( 'A000' ) )
        AND fiscalyear      = @( CONV gjahr( sy-datum+0(4) ) )
      INTO TABLE @DATA(lt_src).

    LOOP AT lt_src ASSIGNING FIELD-SYMBOL(<fs>).
      IF <fs>-plannedactivityprice IS INITIAL.
        MESSAGE |단가 미설정: { <fs>-costcenter } / { <fs>-activitytype }|
                TYPE 'W'.
        CONTINUE.
      ENDIF.

      APPEND VALUE #(
        cost_center  = <fs>-costcenter
        activity_typ = <fs>-activitytype
        planned_qty  = <fs>-plannedactivityquantity
        planned_prc  = <fs>-plannedactivityprice
        planned_cost = <fs>-plannedactivityquantity * <fs>-plannedactivityprice
        currency     = <fs>-currency
      ) TO lt_result.
    ENDLOOP.

  CATCH cx_sy_open_sql_db INTO DATA(lx_db).
    MESSAGE lx_db->get_text( ) TYPE 'E'.
ENDTRY.

6. CDS Association을 활용한 관련 데이터 확장 조회

활동 마스터만으로는 분석 가치가 제한적입니다. 원가 센터 이름, 활동 유형 설명, 조직 단위(회사코드·사업영역) 같은 텍스트와 차원 정보를 함께 가져오려면 association을 활용한 커스텀 Composite View가 일반적입니다.

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'CC Activity Enriched View'
define view entity ZC_CostCenterActivityEnriched
  as select from I_CostCenterActivity as Act

  association [0..1] to I_CostCenterText      as _CCText
    on  _CCText.ControllingArea = Act.ControllingArea
    and _CCText.CostCenter      = Act.CostCenter
    and _CCText.Language        = $session.system_language

  association [0..1] to I_ActivityTypeText    as _ATText
    on  _ATText.ControllingArea = Act.ControllingArea
    and _ATText.ActivityType    = Act.ActivityType
    and _ATText.Language        = $session.system_language
{
  key Act.ControllingArea,
  key Act.CostCenter,
      _CCText.CostCenterName             as CostCenterName,
  key Act.ActivityType,
      _ATText.ActivityTypeName           as ActivityTypeName,
  key Act.FiscalYear,
      Act.ActivityUnit,
      Act.PlannedActivityQuantity,
      Act.ActualActivityQuantity,
      Act.PlannedActivityPrice,
      @Semantics.amount.currencyCode: 'Currency'
      cast( Act.PlannedActivityQuantity * Act.PlannedActivityPrice
            as abap.curr( 15, 2 ) )      as PlannedTotalCost,
      Act.Currency
}

위 Composite View는 마스터 텍스트를 left outer 형태로 결합해 사용자 친화적 결과를 만들어 줍니다. 텍스트 association은 $session.system_language를 사용해 로그온 언어에 자동 대응하도록 처리하는 것이 안전합니다.

7. 원가 배분 리포팅 시나리오 실전 구현

실제 컨설팅 프로젝트에서 자주 마주치는 요구사항은 "원가 센터별 계획 대비 실적 활동량의 편차"를 월 단위로 보여주는 리포트입니다. 이를 위해 Universal Journal(I_JournalEntryItem 또는 I_ActualCostsByCstCtrAndActivityType)과 마스터를 결합합니다.

REPORT zr_cc_activity_variance.

TYPES: BEGIN OF ty_variance,
         cost_center  TYPE kostl,
         cc_name      TYPE text40,
         activity_typ TYPE lstar,
         at_name      TYPE text40,
         period       TYPE poper,
         plan_qty     TYPE p LENGTH 13 DECIMALS 3,
         actual_qty   TYPE p LENGTH 13 DECIMALS 3,
         variance_pct TYPE p LENGTH 5 DECIMALS 2,
       END OF ty_variance.

DATA: lt_variance TYPE TABLE OF ty_variance.

SELECT a~controllingarea,
       a~costcenter,
       a~activitytype,
       a~plannedactivityquantity,
       a~actualactivityquantity,
       cc~costcentername,
       at~activitytypename
  FROM zc_costcenteractivityenriched AS a
  WHERE a~controllingarea = @( CONV kokrs( 'A000' ) )
    AND a~fiscalyear      = @( CONV gjahr( sy-datum+0(4) ) )
  INTO TABLE @DATA(lt_raw).

LOOP AT lt_raw ASSIGNING FIELD-SYMBOL(<r>).
  DATA(lv_variance) = COND p(
    WHEN <r>-plannedactivityquantity > 0
    THEN ( <r>-actualactivityquantity - <r>-plannedactivityquantity )
         / <r>-plannedactivityquantity * 100
    ELSE 0 ).

  APPEND VALUE ty_variance(
    cost_center  = <r>-costcenter
    cc_name      = <r>-costcentername
    activity_typ = <r>-activitytype
    at_name      = <r>-activitytypename
    plan_qty     = <r>-plannedactivityquantity
    actual_qty   = <r>-actualactivityquantity
    variance_pct = lv_variance
  ) TO lt_variance.
ENDLOOP.

* SALV로 표시
TRY.
    cl_salv_table=>factory(
      IMPORTING r_salv_table = DATA(lo_alv)
      CHANGING  t_table      = lt_variance ).
    lo_alv->display( ).
  CATCH cx_salv_msg INTO DATA(lx_salv).
    MESSAGE lx_salv->get_text( ) TYPE 'E'.
ENDTRY.

대량 데이터를 다룰 때는 ABAP 루프 내 계산을 피하고 CDS View 안에서 case식이나 가상 요소(virtual element)로 계산하는 편이 HANA 푸시다운 측면에서 유리합니다. 일반적으로 10만 건 이상의 원가 센터/활동 조합에서는 클라이언트 계산이 응답 시간을 크게 늦춥니다.

8. 운영 환경에서 주의해야 할 데이터 품질 이슈

실제 운영에서 가장 자주 마주치는 데이터 품질 이슈는 다음과 같습니다.

  • 유효 기간 불일치: 활동 유형이 회계연도 중간에 신설되거나 폐기되면 ValidityStartDate/ValidityEndDate가 회계연도와 어긋납니다. 리포트 기준일을 명시적으로 필터링해야 누락이 없습니다.
  • 단가 0 또는 NULL: 계획 단가(KP26)가 입력되지 않은 채 실적 활동량만 기표되면 정치적 단가(political price) 재산정 전까지 비용 배분이 부정확해집니다. 권장 방어책은 단가 NULL 행을 별도 예외 리포트로 분리하는 것입니다.
  • 통화 혼재: 컨트롤링 영역 통화, 객체 통화, 거래 통화가 다른 경우 단순 합산이 의미 없는 결과를 만듭니다. @Semantics.amount.currencyCode 어노테이션을 정확히 지정해야 Fiori UI에서 통화 변환이 올바르게 처리됩니다.
  • 권한 체크: I_CostCenterActivity는 인터페이스 뷰로 권한 체크가 위임되어 있을 수 있습니다. Composite View에서 @AccessControl.authorizationCheck: #CHECK를 명시하고 별도 DCL(Data Control Language)로 조직 단위(원가 센터/컨트롤링 영역)별 권한을 정의하는 편이 안전합니다.
  • 버전 관리: 계획 데이터는 버전(VRGAR/Version) 차원이 추가됩니다. 통상 버전 0(실적/공식 계획)을 기본으로 보지만, 시뮬레이션 버전이 섞여 들어오는 경우 결과가 왜곡됩니다.

마지막으로, 활동 배분 결과는 Universal Journal에 반영되는 시점과 활동 단가 재산정(KSII) 시점이 다를 수 있다는 점을 기억해야 합니다. 월 마감 전에 단가가 확정되지 않은 상태로 조회하면 계획 단가 기반의 잠정값만 보이며, 실제 마감 후 값과 차이가 발생합니다. 운영 리포트에는 "데이터 기준 시각"과 "단가 재산정 상태"를 함께 표시해 사용자 혼란을 줄이는 것이 일반적인 모범 사례로 권장됩니다.

이 글에서 다룬 패턴(인터페이스 뷰 → Composite View → Consumption View 또는 ABAP 리포트)을 따라가면, S/4HANA의 원가 센터 활동 데이터를 안정적이고 확장 가능한 방식으로 활용할 수 있습니다. 특히 Embedded Analytics, RAP 기반 비즈니스 객체, Fiori Elements 리스트 리포트로 연결해 나가는 출발점으로 I_CostCenterActivity는 매우 견고한 토대가 되어 줍니다.

댓글 0

아직 댓글이 없습니다.