SAP

회사코드 vs 원가통제단위 — 1:N 할당 제약 #shorts #SAP #FI

이 글에서 다루는 내용과 목표

SAP를 처음 접하는 분들이 가장 자주 혼동하는 개념이 바로 회사코드(Company Code)와 원가통제단위(Controlling Area)의 차이입니다. 둘 다 "조직 단위"라는 점은 같지만, 하나는 법적 재무회계(FI)를 위한 그릇이고 다른 하나는 내부 관리회계(CO)를 위한 그릇입니다. 이 글을 끝까지 읽으면 다음을 스스로 판단할 수 있게 됩니다.

  • 회사코드와 원가통제단위가 각각 어떤 회계 목적을 담당하는지 설명할 수 있다
  • 1:1과 1:N 할당 구조의 차이와 선택 기준을 이해한다
  • 1:N 할당 시 통화 유형과 회계연도 변형(Fiscal Year Variant)이 왜 일치해야 하는지 원리로 이해한다
  • ABAP로 할당 상태를 조회·검증하는 간단한 프로그램을 작성할 수 있다

미리 갖추면 좋은 배경

재무회계(FI)와 관리회계(CO)가 "외부 보고용"과 "내부 의사결정용"으로 나뉜다는 회계 기초 개념만 알고 있으면 충분합니다. ABAP 예제가 포함되어 있지만 SELECT 문 수준이므로, 프로그래밍 경험이 없어도 흐름을 따라오는 데 무리가 없습니다. SPRO(구성 메뉴)를 한 번이라도 열어본 경험이 있다면 더 수월합니다.

시스템 환경과 준비 사항

이 글의 화면 경로와 테이블 구조는 SAP S/4HANA 2023 On-Premise 기준이며, ECC 6.0에서도 거의 동일하게 적용됩니다. S/4HANA Cloud Public Edition에서는 원가통제단위가 A000 하나로 사전 구성되어 오는 것이 일반적이라 직접 생성할 일은 드물지만, 개념 이해는 동일하게 필요합니다.

  • 구성 트랜잭션: OX02(회사코드 정의), OKKP(원가통제단위 유지), OX19(회사코드 → 원가통제단위 할당)
  • 핵심 테이블: T001(회사코드 마스터), TKA01(원가통제단위 마스터), TKA02(할당 테이블)
  • 권한: 구성 조회를 위해 S_TABU_DIS 등 테이블 조회 권한, 실습 시스템(샌드박스) 사용을 권장합니다

핵심 개념 — 법적 회계 단위와 관리회계 단위

비유로 시작해 보겠습니다. 회사코드는 국세청에 제출하는 공식 장부이고, 원가통제단위는 경영진 회의실의 화이트보드입니다. 공식 장부는 법인 단위로 하나씩, 그 나라의 법과 통화에 맞춰 작성해야 합니다. 반면 화이트보드에는 여러 법인의 숫자를 한데 모아 "어느 사업부가 돈을 벌고 어느 코스트센터가 낭비하는지"를 자유롭게 그려볼 수 있습니다.

  • 회사코드(BUKRS): 독립적인 재무제표(대차대조표·손익계산서)를 작성하는 최소 법적 단위입니다. 법인마다 하나씩 만들며, 현지 통화·현지 회계기준(Local GAAP)·세무 요건이 여기에 귀속됩니다.
  • 원가통제단위(KOKRS): 코스트센터 회계, 내부 오더, 제품원가, 수익성 분석(CO-PA)이 수행되는 관리회계의 울타리입니다. 원가 배부(Allocation)나 내부 정산은 이 울타리를 넘을 수 없습니다.

구조를 도식으로 표현하면 다음과 같습니다.

# 한빛전자 그룹의 조직구조 예시 (1:N 구조)
ControllingArea: HB00        # 그룹 통합 관리회계
  currency: KRW              # 통화 유형 30 (그룹 통화)
  fiscalYearVariant: K4      # 1~12월 + 특별기간 4개
  chartOfAccounts: HBCA      # 운영 계정과목표 공유
  companyCodes:
    - HB10  # 한빛전자 한국법인 (KRW)
    - HB20  # 한빛전자 미국법인 (USD)
    - HB30  # 한빛전자 베트남법인 (VND)

할당 규칙은 명확합니다. 하나의 원가통제단위에 여러 회사코드를 붙일 수 있지만(1:N), 하나의 회사코드는 정확히 하나의 원가통제단위에만 속합니다. 그리고 1:N 구조를 선택하는 순간 세 가지 제약이 따라옵니다.

  1. 운영 계정과목표(Operating Chart of Accounts) 일치: 모든 회사코드가 같은 계정과목표를 써야 원가요소가 공통 언어로 통합됩니다.
  2. 회계연도 변형 일치: 전기 기간(Posting Period)의 개수와 구간이 같아야 합니다. 특별기간 수만 다른 경우는 일반적으로 허용되지만, 1~12월 법인과 4월 시작 법인을 한 원가통제단위에 묶을 수는 없습니다. 기간이 어긋나면 "3월의 원가"가 법인마다 다른 기간을 의미하게 되어 배부 사이클 자체가 성립하지 않기 때문입니다.
  3. 통화 유형의 신중한 선택: 통화 유형 10(회사코드 통화)은 1:1 구조에서만 의미가 있고, 1:N 다국적 구조에서는 유형 30(그룹 통화)을 쓰는 것이 일반적입니다. 한 번 운영을 시작하면 변경이 사실상 불가능하므로 초기 설계가 결정적입니다.

S/4HANA에서는 유니버설 저널(ACDOCA)이 FI와 CO 전표를 하나의 테이블로 통합했지만, 원가통제단위라는 조직 단위와 위 제약은 여전히 유효합니다. 오히려 실시간 FI-CO 통합 때문에 초기 조직구조 설계의 중요성이 더 커졌습니다.

실전 예제 — 조직구조 확인부터 검증 자동화까지 3단계

1단계: 현재 할당 구조 조회하기

한빛전자 그룹의 시나리오로 시작합니다. 어떤 회사코드가 어느 원가통제단위에 붙어 있는지 테이블 세 개를 조인해 확인합니다.

REPORT zhb_org_structure_check.

" 회사코드 → 원가통제단위 할당 현황 조회
SELECT a~kokrs,            " 원가통제단위
       t~bezei AS ca_name, " 원가통제단위 명칭
       a~bukrs,            " 회사코드
       c~butxt AS cc_name, " 회사코드 명칭
       c~waers AS cc_curr, " 회사코드 통화
       c~periv AS cc_fyv   " 회계연도 변형
  FROM tka02 AS a
  INNER JOIN tka01 AS t ON t~kokrs = a~kokrs
  INNER JOIN t001  AS c ON c~bukrs = a~bukrs
  WHERE a~kokrs = 'HB00'
  INTO TABLE @DATA(lt_assignment).

LOOP AT lt_assignment INTO DATA(ls_row).
  WRITE: / ls_row-kokrs, ls_row-bukrs,
           ls_row-cc_curr, ls_row-cc_fyv.
ENDLOOP.

실행하면 HB00 아래 HB10(KRW, K4), HB20(USD, K4), HB30(VND, K4)이 나란히 출력됩니다. 통화는 서로 달라도 되지만 회계연도 변형 K4는 모두 같다는 점을 눈으로 확인하는 것이 이 단계의 목적입니다.

2단계: 신규 법인 편입 전 사전 검증 (에러 처리와 로깅)

한빛전자가 일본법인 HB40을 새로 만들어 HB00에 편입한다고 가정합니다. 일본 법인은 4월 시작 회계연도(V3)를 쓰고 싶어 하는 상황 — 바로 여기서 사고가 납니다. 편입 전에 자동으로 걸러내는 검증 로직을 만들어 봅니다.

CLASS zcl_hb_org_validator DEFINITION.
  PUBLIC SECTION.
    METHODS check_assignment
      IMPORTING iv_kokrs        TYPE kokrs
                iv_bukrs        TYPE bukrs
      RETURNING VALUE(rv_valid) TYPE abap_bool
      RAISING   zcx_hb_org_error.
ENDCLASS.

CLASS zcl_hb_org_validator IMPLEMENTATION.
  METHOD check_assignment.
    SELECT SINGLE lmona, ktopl
      FROM tka01 WHERE kokrs = @iv_kokrs
      INTO @DATA(ls_ca).

    SELECT SINGLE periv, ktopl, waers
      FROM t001 WHERE bukrs = @iv_bukrs
      INTO @DATA(ls_cc).

    IF sy-subrc <> 0.
      " 존재하지 않는 회사코드 → 예외 + 로그
      RAISE EXCEPTION TYPE zcx_hb_org_error
        EXPORTING textid = zcx_hb_org_error=>cc_not_found.
    ENDIF.

    " 핵심 검증 1: 계정과목표 일치 여부
    IF ls_cc-ktopl <> ls_ca-ktopl.
      MESSAGE e001(zhb_org) WITH iv_bukrs ls_cc-ktopl
        INTO DATA(lv_msg).
      " 애플리케이션 로그(BAL)에 기록 후 실패 반환
      rv_valid = abap_false.
      RETURN.
    ENDIF.

    " 핵심 검증 2: 회계연도 변형의 전기 기간 구조 비교
    " (특별기간 수 차이는 허용, 기간 경계 차이는 차단)
    rv_valid = compare_period_structure(
                 iv_cc_fyv = ls_cc-periv
                 iv_kokrs  = iv_kokrs ).
  ENDMETHOD.
ENDCLASS.

이 검증기를 편입 프로세스 앞단에 두면, HB40이 V3 변형을 들고 오는 순간 "기간 구조 불일치"로 차단되고 로그가 남습니다. 실무에서는 이 시점에 두 가지 선택지를 논의하게 됩니다. HB40의 회계연도를 K4로 맞추거나(현지 법정 보고는 FI 레저 차원에서 별도 처리), HB40 전용 원가통제단위를 따로 만드는 것입니다.

3단계: 프로덕션 — CDS 뷰와 단위 테스트로 상시 모니터링

운영 환경에서는 일회성 리포트보다 CDS 뷰로 노출해 Fiori 리포트나 권한 통제와 연결하는 편이 유지보수에 유리합니다.

@AbapCatalog.sqlViewName: 'ZHBORGMAP'
@AccessControl.authorizationCheck: #CHECK  // DCL로 회사코드 권한 통제
@EndUserText.label: '원가통제단위-회사코드 할당 맵'
define view Z_HB_OrgAssignmentMap
  as select from tka02 as Assignment
  inner join   tka01 as ControllingArea
    on ControllingArea.kokrs = Assignment.kokrs
  inner join   t001  as CompanyCode
    on CompanyCode.bukrs = Assignment.bukrs
{
  key Assignment.kokrs        as ControllingAreaId,
  key Assignment.bukrs        as CompanyCodeId,
      CompanyCode.waers       as LocalCurrency,
      CompanyCode.periv       as FiscalYearVariant,
      ControllingArea.ktopl   as ChartOfAccounts,
      // 회계연도 변형 불일치 여부를 뷰에서 즉시 판별
      case when CompanyCode.periv = ControllingArea.lmona
           then 'CONSISTENT' else 'REVIEW' end as ConsistencyFlag
}

여기에 2단계 검증 클래스를 대상으로 ABAP Unit 테스트를 붙여 두면, 신규 롤아웃 프로젝트마다 회귀 검증이 자동으로 돌아갑니다. 테스트 더블로 TKA01/T001 조회를 격리하고, "기간 구조 불일치 케이스에서 반드시 실패해야 한다"는 시나리오를 고정해 두는 방식이 일반적입니다. 접근 통제(DCL) 없이 할당 정보를 열어두면 법인별 재무 조직 정보가 불필요하게 노출되므로, 프로덕션에서는 authorizationCheck를 #CHECK로 두는 것을 권장합니다.

흔한 실수와 트러블슈팅 FAQ

  • Q1. 법인마다 원가통제단위를 하나씩(1:1) 만들었는데 나중에 문제가 되나요?
    가장 흔한 설계 실수입니다. 1:1 구조는 단순해 보이지만, 법인 간 원가 배부·그룹 차원의 수익성 분석·공통 코스트센터 운영이 모두 불가능해집니다. 원가통제단위 간 데이터 통합은 표준 기능으로 지원되지 않아, 그룹 리포팅을 별도 솔루션으로 메꾸는 비용이 발생합니다. 그룹 경영이 조금이라도 예상된다면 처음부터 1:N을 검토하는 것이 일반적입니다.
  • Q2. 회사코드 통화가 서로 다른데 정말 한 원가통제단위에 묶을 수 있나요?
    가능합니다. 통화가 "같아야" 하는 것이 아니라, 원가통제단위의 통화 유형을 다통화 구조에 맞게 선택해야 한다는 것이 정확한 제약입니다. 유형 10(회사코드 통화)은 사실상 1:1 전용이고, 다국적 1:N에서는 유형 30(그룹 통화)으로 CO 내부 통화를 통일합니다. 운영 개시 후에는 변경이 사실상 막히므로 골든 클라이언트 단계에서 확정해야 합니다.
  • Q3. OX19에서 할당하려는데 "회계연도 변형이 다르다"는 오류가 납니다.
    회사코드의 PERIV와 원가통제단위의 회계연도 변형이 기간 경계 수준에서 다르기 때문입니다. 특별기간 개수만 다른 경우는 통과되지만, 12월 결산 vs 3월 결산처럼 기간 자체가 어긋나면 차단됩니다. 현지 법정 결산 주기가 다른 법인은 FI 병렬 레저(비교 레저)로 현지 보고를 처리하고, 리딩 레저와 CO는 그룹 기준으로 맞추는 접근이 널리 쓰입니다.
  • Q4. 계정과목표가 달라도 되나요?
    운영 계정과목표는 반드시 같아야 합니다. 현지 요건은 국가별 계정과목표(Country Chart of Accounts)를 회사코드에 병행 지정하는 방식으로 흡수하는 것이 일반적입니다.

여기서 더 나아가려면

조직구조의 두 축을 이해했다면, 다음 주제로 자연스럽게 확장할 수 있습니다. 먼저 운영 조직(Operating Concern) — 원가통제단위 위에 놓이는 CO-PA의 최상위 단위로, 원가통제단위와 다시 1:N 관계를 이룹니다. 그다음은 S/4HANA의 유니버설 저널(ACDOCA)이 FI 전표와 CO 전표를 어떻게 한 줄로 통합하는지, 그리고 병렬 레저와 통화 유형 확장이 다국적 결산에서 어떤 역할을 하는지 살펴보면 이 글의 제약 조건들이 왜 존재하는지 한층 깊게 이해됩니다.

함께 보면 좋은 문서 모음

댓글 0

아직 댓글이 없습니다.