ABAP

I_CompanyCode vs T001 — 회사코드 조회 차이 #shorts #SAP #ABAP

▶ YouTube에서 보기

개요

이 글에서는 SAP S/4HANA의 가상 데이터 모델(VDM) 중 하나인 I_CompanyCode CDS 뷰를 다룹니다. I_CompanyCode는 전통적인 T001 회사 코드 마스터 테이블을 추상화하여 회계 연도(Fiscal Year Variant), 통화, 차트 오브 어카운트(Chart of Accounts) 등을 일관된 인터페이스로 제공하는 기본 뷰(Basic View)입니다. 이 글을 통해 다음을 점검할 수 있습니다.

  • T001 테이블과 I_CompanyCode 뷰의 매핑 관계 이해
  • OPEN SQL에서 CDS 뷰를 호출하는 표준 패턴 작성
  • 회계 연도 변형(Fiscal Year Variant) 필드의 의미와 활용
  • Association을 활용해 통화/국가 정보를 JOIN 없이 조회
  • 구매오더·재무전기 등 실무 시나리오에서의 적용

알아두면 좋은 배경

이 글의 코드는 ABAP for Cloud Development 또는 ABAP on-premise(7.55 이상) 환경을 가정합니다. CDS DDIC 기반 뷰에 대한 기본 문법(DEFINE VIEW, ASSOCIATION), OPEN SQL의 SELECT ... FROM 구문, 그리고 ABAP Development Tools(ADT)에서 데이터 미리보기 기능을 다뤄본 경험이 있다면 따라가기 수월합니다. 또한 SAP FI 모듈의 회사 코드(BUKRS)와 회계 연도 개념을 어렴풋이라도 알고 있어야 합니다.

환경과 준비물

예제는 다음 환경에서 검증되었습니다.

  • SAP S/4HANA 2022 (on-premise) 또는 SAP S/4HANA Cloud, ABAP Environment
  • ABAP Platform 2022 (Release 7.57) 이상 — Released CDS Views 카탈로그 기준
  • ABAP Development Tools (ADT) for Eclipse 2024-03 이상
  • 권한: S_DEVELOP (오브젝트 타입 DDLS 표시 권한), S_TABU_DIS 권한 그룹 FC31 (T001 조회용)
  • 테스트 데이터: 표준 IDES 회사 코드 1000, 1010, 2000 등이 존재한다고 가정합니다.

ADT에서 Ctrl+Shift+AI_CompanyCode를 열어 Data Preview(F8)를 먼저 실행해 두면 필드 구조를 빠르게 파악할 수 있습니다. 일반적으로 Released API 분류는 C1(Released for Cloud) 또는 사내 활용 기준에 맞춰 확인이 필요합니다.

핵심 개념: T001을 감싸는 뷰 계층

전통적인 ABAP 개발에서는 회사 코드를 다룰 때 SELECT ... FROM t001로 직접 접근하는 패턴이 흔했습니다. 그러나 S/4HANA의 가상 데이터 모델(VDM)은 이런 직접 접근을 권장하지 않고, 의미가 부여된 Basic Interface View 계층을 통하도록 가이드합니다. 비유하자면 T001은 "원자재 창고"이고, I_CompanyCode는 "정제된 부품 진열대"라고 볼 수 있습니다.

VDM은 보통 다음 3계층으로 구성됩니다.

  1. Basic View (I_*): 원천 테이블(예: T001)을 1:1에 가깝게 노출하되 필드명을 의미론적으로 변경합니다. 예: BUKRS → CompanyCode, WAERS → Currency, PERIV → FiscalYearVariant.
  2. Composite View (C_*): 여러 Basic View를 결합해 분석/리포팅 관점을 제공합니다.
  3. Consumption View (C_* / Service): Fiori 앱이나 OData 서비스로 노출됩니다.

주요 필드 매핑은 다음과 같습니다.

T001 필드I_CompanyCode 필드의미
BUKRSCompanyCode회사 코드 (PK)
BUTXTCompanyCodeName회사명
LAND1Country국가 키
WAERSCurrency회사 코드 통화
KTOPLChartOfAccounts차트 오브 어카운트
PERIVFiscalYearVariant회계 연도 변형
SPRASLanguage회사 언어

특히 FiscalYearVariant는 회계 연도가 1월~12월(K4)인지, 4월~3월(V3)인지, 또는 4-4-5주 패턴인지를 결정하는 핵심 키입니다. 이 변형은 T009(Fiscal Year Variants) 및 T009B(Periods)와 연결되며, I_CompanyCode는 Association _FiscalYearVariant를 통해 이를 노출합니다.

1단계: 기본 조회 예제

먼저 ABAP 클래스에서 I_CompanyCode를 직접 호출해 회사 코드 목록을 조회합니다. 콘솔 출력은 cl_demo_output을 사용합니다.

CLASS zcl_demo_ccode_basic DEFINITION
  PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
ENDCLASS.

CLASS zcl_demo_ccode_basic IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.

    TYPES: BEGIN OF ty_ccode,
             company_code      TYPE i_companycode-companycode,
             company_code_name TYPE i_companycode-companycodename,
             country           TYPE i_companycode-country,
             currency          TYPE i_companycode-currency,
             fyv               TYPE i_companycode-fiscalyearvariant,
           END OF ty_ccode.

    DATA lt_ccode TYPE STANDARD TABLE OF ty_ccode.

    SELECT CompanyCode,
           CompanyCodeName,
           Country,
           Currency,
           FiscalYearVariant
      FROM I_CompanyCode
      WHERE Country = 'KR'
      ORDER BY CompanyCode
      INTO TABLE @lt_ccode.

    out->write( lt_ccode ).
  ENDMETHOD.
ENDCLASS.

위 코드의 포인트는 두 가지입니다. 첫째, 필드명이 의미론적입니다(BUKRS가 아니라 CompanyCode). 둘째, 클라이언트 처리는 OPEN SQL이 자동 수행하므로 CLIENT SPECIFIED를 명시할 필요가 없습니다.

2단계: 실무 시나리오 — 회계 연도 변형 결합

실무에서는 단순히 회사 코드 목록만 필요한 경우보다, "이 회사 코드의 현재 회계 연도가 무엇인가?"를 알아야 하는 경우가 많습니다. 예를 들어 구매오더 헤더(I_PurchaseOrder)에 회사 코드가 들어 있을 때, 해당 회사의 FY 변형을 가져와 기말 처리 로직을 분기해야 합니다. 이때 _FiscalYearVariant Association을 활용합니다.

CLASS zcl_fy_lookup DEFINITION
  PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
  PRIVATE SECTION.
    METHODS log_error
      IMPORTING iv_msg TYPE string.
ENDCLASS.

CLASS zcl_fy_lookup IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.

    TYPES: BEGIN OF ty_result,
             company_code TYPE i_companycode-companycode,
             company_name TYPE i_companycode-companycodename,
             fyv          TYPE i_companycode-fiscalyearvariant,
             fyv_desc     TYPE i_fiscalyearvariant-fiscalyearvariantname,
             is_calendar  TYPE abap_bool,
           END OF ty_result.

    DATA lt_result TYPE STANDARD TABLE OF ty_result.

    TRY.
        SELECT cc~CompanyCode,
               cc~CompanyCodeName,
               cc~FiscalYearVariant,
               fyv~FiscalYearVariantName,
               CASE WHEN fyv~IsCalendarYear = 'X'
                    THEN @abap_true
                    ELSE @abap_false
               END AS IsCalendar
          FROM I_CompanyCode AS cc
          LEFT OUTER JOIN I_FiscalYearVariant AS fyv
            ON  cc~FiscalYearVariant = fyv~FiscalYearVariant
          WHERE cc~Country IN ( 'KR', 'JP', 'DE' )
          ORDER BY cc~CompanyCode
          INTO CORRESPONDING FIELDS OF TABLE @lt_result.

        IF sy-subrc <> 0 OR lines( lt_result ) = 0.
          log_error( |회사 코드를 찾지 못했습니다. SY-SUBRC={ sy-subrc }| ).
        ENDIF.

        out->write( lt_result ).

      CATCH cx_sy_open_sql_db INTO DATA(lx_sql).
        log_error( lx_sql->get_text( ) ).
      CATCH cx_root INTO DATA(lx_root).
        log_error( lx_root->get_text( ) ).
    ENDTRY.

  ENDMETHOD.

  METHOD log_error.
    MESSAGE iv_msg TYPE 'I'.
  ENDMETHOD.
ENDCLASS.

여기서 I_FiscalYearVariantT009의 VDM 래퍼이며, IsCalendarYear 플래그를 통해 회계 연도가 정확히 달력 연도와 일치하는지 빠르게 판단할 수 있습니다. JOIN 대신 Association Path Expression(cc~\_FiscalYearVariant-FiscalYearVariantName)을 사용해도 동일한 결과를 얻을 수 있고, 코드가 더 간결해집니다.

3단계: 프로덕션 — 캐싱·테스트·권한

회사 코드는 변경 빈도가 낮은 마스터 데이터입니다. 매 호출마다 DB로 가지 않고 메모리에 캐싱하면 성능을 크게 개선할 수 있습니다. 또한 ABAP Unit Test Double Framework로 CDS 뷰를 모킹해 단위 테스트를 권장합니다.

CLASS zcl_company_resolver DEFINITION
  PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_company,
             code     TYPE bukrs,
             name     TYPE string,
             currency TYPE waers,
             fyv      TYPE periv,
           END OF ty_company.

    CLASS-METHODS get_by_code
      IMPORTING iv_code           TYPE bukrs
      RETURNING VALUE(rs_company) TYPE ty_company
      RAISING   cx_sy_itab_line_not_found.

  PRIVATE SECTION.
    CLASS-DATA gt_cache TYPE HASHED TABLE OF ty_company
                       WITH UNIQUE KEY code.
ENDCLASS.

CLASS zcl_company_resolver IMPLEMENTATION.
  METHOD get_by_code.

    READ TABLE gt_cache INTO rs_company WITH KEY code = iv_code.
    IF sy-subrc = 0.
      RETURN.
    ENDIF.

    SELECT SINGLE
           CompanyCode      AS code,
           CompanyCodeName  AS name,
           Currency         AS currency,
           FiscalYearVariant AS fyv
      FROM I_CompanyCode
      WHERE CompanyCode = @iv_code
      INTO @rs_company.

    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
    ENDIF.

    INSERT rs_company INTO TABLE gt_cache.
  ENDMETHOD.
ENDCLASS.

보안 측면에서는 OPEN SQL이 I_CompanyCode의 DCL(Access Control)을 자동 적용한다는 점을 기억하세요. 만약 권한을 우회해야 한다면 WITH PRIVILEGED ACCESS를 명시해야 하지만, 일반 비즈니스 로직에서는 권장되지 않습니다.

자주 마주치는 함정과 FAQ

Q1. I_CompanyCode를 조회했는데 결과가 비어 있습니다.
T001은 클라이언트 종속 테이블이며, CDS 뷰도 동일합니다. 해당 클라이언트(MANDT)에 회사 코드가 정의되어 있는지 SE16N에서 먼저 확인하세요. 또한 DCL이 사용자의 권한 객체 F_BKPF_BUK를 검사할 수 있으므로 권한 누락도 의심해야 합니다.

Q2. 필드명이 기억나지 않습니다. T001의 BUKRS는 뭐였죠?
ADT에서 I_CompanyCode를 열고 Outline 뷰의 Fields 섹션을 보면 원본 컬럼과 매핑이 표시됩니다. 일반적으로 카멜케이스 의미 이름이 적용됩니다(BUKRS→CompanyCode, WAERS→Currency). 이 매핑은 SAP Note 및 Released API 카탈로그에서 재확인이 권장됩니다.

Q3. 회계 연도 변형이 K4인데 현재 회계 연도/기간을 계산하려면?
I_CompanyCode는 변형 키만 제공합니다. 현재 회계 연도/기간 계산은 FIMA_DATE_CREATE 또는 FI_PERIOD_DETERMINE 함수 모듈, 혹은 더 최신 방식인 cl_fis_calendar 클래스를 활용하세요. 4-4-5 같은 비표준 변형이라면 반드시 표준 API를 호출해야 합니다.

Q4. T001을 직접 SELECT해도 동작은 됩니다. 굳이 CDS를 써야 하나요?
Clean Core 가이드에 따르면 직접 테이블 접근은 업그레이드 호환성과 확장성을 깨뜨릴 수 있어 일반적으로 권장되지 않습니다. CDS 뷰는 향후 컬럼 추가/의미 변경 시에도 추상화 계층이 흡수해 줍니다.

이어서 살펴보면 좋은 주제

회사 코드 마스터를 이해했다면 다음 단계로 I_GLAccountInChartOfAccounts(차트 오브 어카운트 마스터), I_ControllingArea(관리 회계 영역), I_FiscalYearVariant의 하위 I_FiscalYearPeriod까지 살펴보면 FI 모듈 VDM 전체 그림이 그려집니다. 더 나아가 RAP(ABAP RESTful Application Programming Model)에서 I_CompanyCode를 Value Help로 노출하거나, Analytical Query(C_*Q)에서 차원(Dimension)으로 활용하는 방법도 학습 가치가 높습니다.

댓글 0

아직 댓글이 없습니다.