SAP 생산 원가 분석 — 만드는 데 얼마가 들었는가
BOM 다단계 원가와 네 가지 원가 추이를 한 화면에 놓고, 어느 자재에서 언제 원가가 움직였는지 짚는 화면입니다.
제품 원가가 올랐다는 사실은 월말 보고서로도 압니다. 정작 필요한 질문은 BOM의 어느 하위 자재에서, 어느 달부터 움직였느냐입니다.
이 앱은 왼쪽에 BOM 다단계 트리를 두고 각 자재의 월별 표준원가와 실제원가를 나란히 보여 줍니다. 오른쪽에는 자재원가·생산투입·판매원가·재고잔액 네 가지 추이를 상위 10개 자재로 그립니다. 이번 개정에서 차트를 Apache ECharts로 교체했고, 교체 후 서버에서 직접 구동해 캡처한 화면 4종을 함께 공개합니다.
SAP 표준 기능을 그대로 이어받은 부분
- BOM 구조 — 최상위 자재와 레벨(hierlevel)로 표현한 다단계 구성
- 표준원가 — 월별 표준원가 롤업 결과
- 실제원가 — 월별 실제 투입 원가
- 추이 금액 — 판매원가(매출원가)·생산투입·재고잔액
- 수량·단위·통화 — 구성 수량, 단위, 통화키
| 항목 | 내용 |
|---|---|
| 업무 영역 | 생산(PP) · 제품원가(CO-PC) |
| Namespace | pp004_productioncost |
| 셸 구조 | DynamicPage + FilterBar + 3열 ResponsiveSplitter (BOM 트리 │ 자재원가·판매원가 │ 생산투입·재고잔액) |
| 데이터 | ZFCMC_F02_C010A(BOM 월별 원가) + 함수임포트 4종 funcGetChart* |
| 성격 | 조회형 — 원가 계산은 표준이 담당, 엑셀 템플릿 임포트 지원 |
| 차트 | Apache ECharts 5.6.0 (Apache-2.0) — 기존 sap.viz VizFrame 대체 |
| 분석 축 | BOM 레벨 · 자재 · 기간(월) |
| UI 테마 | sap_horizon 단일 적용 |
실제 화면 4종 둘러보기
자재코드로 조회하면 BOM 원가와 네 가지 추이가 함께 나옵니다 → 툴팁으로 표준과 실제의 차이를 읽고 → 막대를 골라 여러 달 금액을 합산합니다.
아래는 서버에 반영된 앱을 실제 브라우저로 열어 기능을 눌러 가며 캡처한 화면입니다. 이미지를 클릭하면 원본 크기로 확대됩니다. 데이터는 시연용 목업입니다.
조작 방법
- 자재코드를 입력하거나 값도움으로 고릅니다. 비워 두면 전체를 조회합니다.
- 조회 버튼을 누르거나 입력필드에서 Enter 를 누릅니다.
- BOM 트리의 펼치기·접기 버튼으로 레벨을 조절합니다. 월 칸의 윗줄은 표준원가, 아랫줄은 실제원가입니다.
- 차트에 마우스를 올려 툴팁을 봅니다. 누적 차트는 해당 기간의 합계까지 함께 나옵니다.
- 하단 범례를 클릭하면 그 자재의 계열이 숨겨지거나 다시 나타납니다. 자재원가 차트는 표준·실제 선이 함께 토글됩니다.
- 막대나 점을 클릭하면 선택되고, 여러 개를 이어서 누르면 합계가 누적됩니다. 다시 누르면 선택에서 빠집니다.
- 팝오버의 선택 해제로 선택을 한 번에 비웁니다. 다른 차트를 클릭하면 이전 차트의 선택은 자동으로 해제됩니다.
- BOM 원가는 엑셀 다운로드로 내려받고, 파일임포트로 원가 분석 엑셀 템플릿을 올릴 수 있습니다.
핵심 판정·산식
차트는 계산을 새로 하지 않습니다. 백엔드가 준 기간별 금액을 순위에 맞춰 배치하고, 읽기 쉬운 형태로 합산·표기만 합니다.
순위 자재 = 마지막 기간 행의 1_matnr ~ 10_matnr
원가 차이 = 실제원가(N_actcost) − 표준원가(N_stdcost)
→ 양수 = 표준 초과(빨강), 음수 = 표준 미달(초록)
기간 합계 = Σ 1~10위 금액(N_dmbtr) ← 누적 차트 툴팁
선택 합계 = Σ 사용자가 클릭한 포인트 금액 ← 팝오버 첫 행
축 표기 1억 이상 → x.x억 / 1만 이상 → x만 (툴팁·팝오버는 원 단위 전체)
기간 표기 202307 → 2023.07
| 추이 | 기존 sap.viz | ECharts 표현 | 읽는 법 |
|---|---|---|---|
| 자재원가 | dual_line | 자재별 실선(표준)·점선(실제) 라인 | 선 사이 간격이 원가차이 |
| 생산투입 | vertical_bullet | 세로 누적 막대 | 막대 높이 = 월 투입 합계 |
| 판매원가 | bar(가로) | 가로 누적 막대 | 막대 길이 = 월 매출원가 합계 |
| 재고잔액 | area | 누적 영역 | 면적 윗선 = 월말 잔액 합계 |
마지막 달을 순위 기준으로 삼는 이유
원가 검토는 보통 가장 최근 달에서 출발합니다. 최근 달에 큰 자재를 1순위로 두면 범례 앞쪽과 누적 막대 아래쪽에 지금 가장 무거운 자재가 오고, 그 자재가 과거에 어떻게 커졌는지를 왼쪽으로 거슬러 읽을 수 있습니다.
처리 단계
| 단계 | 처리 | 비고 |
|---|---|---|
| 1. 조회 | FilterBar 값으로 OData $filter 생성 | 자재코드 조건 |
| 2. BOM 원가 | ZFCMC_F02_C010A 를 1월~12월 순차 조회해 월별 stdcostN · actcostN 열로 병합 | TreeBuilder 가 hierlevel 로 트리 구성 |
| 3. 추이 조회 | 함수임포트 funcGetChartStdAct · Sales · Prod · Inv 호출 | BOM 조회와 함께 Promise.all 병렬 대기 |
| 4. 차트 생성 | 응답 행 → ECharts option 생성 → setOption | 차트별 busy 표시, 오류 시 빈 차트 + 메시지 |
| 5. 완료 | 전체 완료 후 화면 busy 해제와 조회 완료 토스트 | 실패 시 오류 MessageBox |
조회조건
| 필드 | 필수 | 설명 |
|---|---|---|
| 자재코드 | 선택 | MultiInput — 값도움으로 여러 자재 지정, 비우면 전체 |
| 변형(Variant) | 선택 | 자주 쓰는 조회조건 저장·기본값 지정 |
결과 컬럼
BOM 트리
| 컬럼 | 의미 · 표시 |
|---|---|
| 품목 | 자재명(자재코드), 레벨에 따라 들여쓰기 |
| 수량 · 단위 | 구성 수량과 단위 |
| 금액(1)~(12) | 월별 윗줄 표준원가 · 아랫줄 실제원가(통화 포맷) |
추이 차트 응답 행(기간 1행)
| 필드 | 의미 |
|---|---|
spmon | 기간(YYYYMM) |
N_matnr | N순위 자재코드(N = 1~10) |
N_stdcost · N_actcost | 자재원가 추이용 표준·실제원가 |
N_dmbtr | 판매원가 · 생산투입 · 재고잔액 금액 |
SAP 표준 기능 매핑
| 표준 | 역할 | 이 화면에서의 확장 |
|---|---|---|
CS12 | BOM 다단계 전개 | 원가를 붙인 트리로 표시 |
CK13N · CK40N | 표준원가 조회 · 원가 롤업 | 월별 표준원가 열 |
CKM3N | 자재원장 실제원가 | 월별 실제원가 열 · 차이 툴팁 |
KKBC_ORD | 생산오더 원가 분석 | 생산투입 추이 |
KE24 | 수익성분석 실적(매출원가) | 판매원가 추이 |
MB5B | 기간별 재고 잔액 | 재고잔액 추이 |
도입 시 확인이 필요한 부분
표준원가와 실제원가를 같은 월에 비교하려면 원가 추정 버전과 자재원장 마감 시점을 맞춰야 합니다. 월중에 표준원가를 다시 릴리즈하는 회사라면 어느 시점의 표준을 월 표준으로 볼지 먼저 정해야 차이 금액이 흔들리지 않습니다.
참고 CDS 뷰
@AbapCatalog.sqlViewName: 'ZCPRODTREND'
@EndUserText.label: '생산 원가 월별 추이 (Z)'
define view Z_C_PRODUCTION_COST_TREND
as select from acdoca as Item
left outer join makt as MatText on Item.matnr = MatText.matnr
and MatText.spras = 'K'
{
key Item.rbukrs as CompanyCode,
key Item.matnr as Material,
key concat( Item.gjahr, Item.poper ) as Period, -- spmon
MatText.maktx as MaterialName,
Item.rhcur as Currency,
@Semantics.amount.currencyCode: 'Currency'
sum( case when Item.bwart between '261' and '262'
then Item.hsl else 0 end ) as ProductionInput, -- 생산투입(자재 출고)
@Semantics.amount.currencyCode: 'Currency'
sum( case when Item.bwart between '601' and '602'
then Item.hsl else 0 end ) as CostOfSales -- 판매원가(출고 원가)
}
where Item.rldnr = '0L' and Item.matnr <> ''
group by Item.rbukrs, Item.matnr, Item.gjahr, Item.poper,
MatText.maktx, Item.rhcur
// 순위(1_matnr~10_matnr)는 소비 뷰나 함수임포트에서 마지막 기간 기준으로 부여
매핑 이해를 돕기 위한 참고용 설계입니다. 이동유형·계정결정 키는 회사 설정에 따라 다르므로 실제 도입 시 운영 환경에 맞춰 조정합니다.
OpenUI5 구성
| 기능 | 사용 컨트롤 · 구현 |
|---|---|
| 화면 골격 | sap.f.DynamicPage + sap.ui.layout.ResponsiveSplitter 3열 |
| 조회조건 | FilterBar · VariantManagement · sap.m.MultiInput — 조회 버튼은 조회조건 영역 오른쪽 끝 |
| BOM 원가 | sap.ui.table.TreeTable — 월별 표준·실제원가를 한 칸에 두 줄로 표시 |
| 추이 차트 | pp004_productioncost.control.EChart — ECharts 를 감싼 UI5 컨트롤(option 속성, selectData 이벤트) |
| 크기 대응 | sap.ui.core.ResizeHandler — 스플리터 이동·헤더 접힘 시 자동 resize |
| 선택 합계 | sap.m.Popover + sap.m.Table — 합계 행 강조, [선택 해제] 버튼 |
| 라이브러리 로드 | ECharts 5.6.0 을 cdnjs CDN 에서 전역(UMD)으로 로드 |
sap.viz 대신 ECharts를 쓴 이유
OpenUI5에는 SAPUI5 전용 sap.viz 차트가 없어, 이전에는 c3.js 위에 VizFrame 흉내를 낸 호환 레이어를 쓰고 있었습니다. 이 방식은 차트 종류가 제한되고 선택·툴팁 동작이 원본과 달랐습니다. ECharts는 Apache-2.0 라이선스라 배포 제약이 없고, 이중 라인·누적 막대·누적 영역·다중 선택을 기본 기능으로 제공합니다. 컨트롤을 한 겹 감싸 두었기 때문에 다른 앱에서도 같은 방식으로 재사용할 수 있습니다.
파일 구성
| 경로 | 역할 |
|---|---|
index.html | OpenUI5 부트스트랩(sap_horizon) · ECharts CDN 로드 |
webapp/manifest.json | 앱 디스크립터 — OData 서비스와 차트 모델 |
webapp/view/Main.view.xml | 조회조건과 3열 스플리터 레이아웃 |
webapp/view/fragments/tree_bom.fragment.xml | BOM 원가 트리 |
webapp/view/fragments/linechart_*.fragment.xml | 추이 차트 4종(EChart 컨트롤) |
webapp/view/fragments/chart_popup.fragment.xml | 선택 합계 팝오버 |
webapp/control/EChart.js | ECharts 래핑 UI5 컨트롤 |
webapp/js/ChartOdata.js | 함수임포트 조회 · ECharts option 생성 · 오류 처리 |
webapp/controller/Main.controller.js | 조회 · BOM 병합 · 선택 합계 · 엑셀 |
webapp/localdata/funcGetChart*.json | 추이 차트 목업(12개월 · 상위 10개 자재) |
검증 결과
| 검증 항목 | 결과 |
|---|---|
| 추이 차트 4종 렌더링 — 12개 기간 | 4/4 |
| 계열 수 — 자재원가 20(표준·실제 × 10), 나머지 각 10 | 통과 |
| 툴팁 차이 = 실제 − 표준 (2023.07 1순위: 44,675,472 − 42,144,001 = +2,531,471) | 통과 |
| 선택 합계 = 72,269,393 + 75,110,947 + 76,262,363 = 223,642,703 | 통과 |
| 차트 값과 목업 JSON 원본 대조 | 일치 |
| 서버 반영본과 로컬 빌드 파일 해시 비교(핵심 5개) | 일치 |
| JS 문법 · XML 파싱 | 오류 0건 |
| 헤더 접힘·스플리터 변경 시 차트 크기 조정 | 통과 |
| ECharts 버전 · 테마 런타임 확인 | 5.6.0 · sap_horizon |
자주 묻는 질문
차트 라이브러리를 왜 ECharts로 바꿨나요?
OpenUI5에는 SAPUI5의 sap.viz 차트가 들어 있지 않습니다. Apache ECharts는 Apache-2.0 라이선스로 상용 배포에 제약이 없고, 이중 라인·누적 막대·누적 영역·다중 선택·크기 자동 조정을 별도 플러그인 없이 지원해 기존 VizFrame 화면을 그대로 옮길 수 있었습니다.
차트의 1~10위 순서는 무엇 기준인가요?
조회 기간의 마지막 달 금액 기준입니다. 백엔드가 기간별 행에 1_matnr~10_matnr 순위 자재를 담아 보내고, 화면은 마지막 기간 행의 순위를 범례와 계열 순서로 씁니다. 기간 수가 12개월이 아니어도 동작합니다.
자재원가 추이의 차이 색상은 어떻게 읽나요?
차이는 실제원가에서 표준원가를 뺀 값입니다. 양수(빨간색)는 표준보다 더 들었다는 뜻이고, 음수(초록색)는 표준보다 덜 들었다는 뜻입니다.
여러 달 금액을 합쳐 보고 싶으면요?
차트의 막대나 점을 연달아 클릭하면 선택이 누적되고, 팝오버 맨 위에 선택 항목의 합계가 표시됩니다. 같은 점을 다시 누르면 빠지고, [선택 해제]로 한 번에 비울 수 있습니다.
SAP 표준 기능과 어떻게 이어지나요?
표준원가 롤업·실제원가 계산·재고 평가는 표준 CO-PC와 자재원장이 담당합니다. 이 화면은 그 결과를 BOM 구조와 월별 추이로 나란히 놓아, 어느 하위 자재에서 원가가 움직였는지 한 번에 짚도록 만든 조회형 확장입니다.