본문 바로가기
ABAP

[ABAP] 애플리케이션 로그 마스터하기: BAL과 CBO 테이블 로깅, 언제 무엇을 써야 할까?

by 키노s 2025. 7. 13.

요즘 로그를 남기기 위해서는 CBO 테이블을 만들어서 기록을 합니다.

저만 그러는것은 아니겠죠?, 하지만 1회성 오류 확인을 하기 위해서 CBO 테이블을 만드는 것은 좀 비효율적일 때가 있습니다.

그때 SAP에서 제공하는 BAL 로그 남기는 것을 고려할 수 있습니다.

 

최근에 15년 전부터 사용되는 오래된 프로그램이 있는데  프로그램-펑션-펑션-펑션-펑션.. 등으로

아주 복잡하게 되어 있어 어디서 오류가 발생하는지 도저히 못 찾는 경우가 있었습니다.

로그는 남겨서 확인 경우가 있어 BAL 로그 방식을 이야기 해볼까 합니다.

 

서론:  로그의 중요성

SAP ABAP 개발자라면 프로그램 실행 중 발생하는 다양한 상황을 추적하고, 오류를 진단하며, 비즈니스 프로세스의 흐름을 파악하는 데 로그가 얼마나 중요한지 잘 아실 겁니다. 특히 백그라운드 배치 작업이나 인터페이스 프로그램처럼 사용자 인터페이스가 없는 환경에서는 로그가 유일한 통신 수단이 되기도 합니다.

이번 포스팅에서는 SAP ABAP 환경에서 로그를 기록하는 두 가지 핵심 방법을 깊이 있게 다룹니다.

바로 SAP 표준 프레임워크인 BAL(Business Application Log) 과 개발자가 직접 설계하는 CBO(Custom Business Object) 테이블 로깅입니다. 

 

1. SAP 표준 로깅의 정석: Business Application Log (BAL)

BAL은 SAP가 제공하는 표준 애플리케이션 로그 프레임워크입니다.

이를 활용하면 프로그램에서 발생하는 정보, 경고, 오류 메시지를 체계적으로 기록하고, 표준 트랜잭션(SLG1)을 통해 편리하게 조회할 수 있습니다. 이는 특히 시스템 운영 및 모니터링 관점에서 매우 강력한 도구입니다.

1.1. BAL 개요 및 주요 트랜잭션

  • SLG0: BAL 오브젝트(Object) 및 서브오브젝트(Subobject)를 정의하는 트랜잭션입니다.
    로그를 기록하기 전에 반드시 로깅 대상에 대한 분류 체계를 이곳에서 정의해야 합니다.
    예를 들어, 'ZMM' (자재 관리) 오브젝트 아래에 'POINFO' (구매 오더 정보)와 같은 서브오브젝트를 만들 수 있습니다.
  • SLG1: 기록된 BAL 로그를 조회하는 핵심 트랜잭션입니다.
    오브젝트, 서브오브젝트, 외부 번호(EXTNUMBER), 사용자, 날짜 등 다양한 조건으로 필터링하여 원하는 로그를 빠르게 찾을 수 있습니다.
  • SLG2: 오래된 BAL 로그를 삭제하여 시스템 성능을 최적화하고 데이터베이스 공간을 관리하는 트랜잭션입니다.

1.2. BAL 기록 단계별 예시: 범용 write_free_log 서브루틴

BAL을 사용하기 위한 첫 단계는 SLG0 트랜잭션에서 로그를 저장할 오브젝트(Object) 와  서브오브젝트(Subobject) 를 정의하는 것입니다. 이 설정이 되어 있지 않으면 로그가 제대로 기록되지 않습니다.

단계별 등록 방법:

  1. SLG0 트랜잭션 실행: SAP GUI에서 SLG0을 입력하고 실행합니다.
  2. 오브젝트 생성:
    • '애플리케이션 로그: 오브젝트' 화면에서 '신규 엔트리(F5)' 버튼을 클릭합니다.
    • 오브젝트(Object) 필드에 원하는 오브젝트 코드(예: ZMM – Z로 시작하는 커스텀 오브젝트)를 입력합니다.
    • 오브젝트 텍스트(Object Text)에 오브젝트에 대한 설명(예: '자재 관리 애플리케이션 로그')을 입력합니다.
    • 저장 버튼을 클릭하고 Transport Request(TR)에 포함시킵니다.

  3. 서브오브젝트 생성:
    • 방금 생성한 오브젝트를 선택하고 왼쪽 탐색 영역에서 '서브오브젝트 정의'를 더블클릭합니다.
    • '신규 엔트리(F5)' 버튼을 클릭합니다.
    • 서브오브젝트(Subobject) 필드에 원하는 서브오브젝트 코드(예: POINFO – 구매 오더 정보)를 입력합니다.
    • **서브오브젝트 텍스트(Subobject Text)**에 설명을 입력합니다(예: '구매 오더 정보 처리').
    • 저장 버튼을 클릭하고 TR에 포함시킵니다.

이렇게 SLG0에 오브젝트(ZMM)와 서브오브젝트(POINFO)가 등록되면, ABAP 코드에서 이들을 사용하여 BAL 로그를 생성할 수 있습니다.

1.3. BAL 기록 단계별 예시: 범용 write_free_log 서브루틴

다음 write_free_log 서브루틴은 BAL을 사용하여 메시지를 기록하는 범용적인 코드 예시입니다.
메시지 유형, 메시지 텍스트, 그리고 로그를 식별할 수 있는  외부 번호(External Number)를 파라미터로 받아 효율적인 ABAP 로깅을 가능하게 합니다.

*&---------------------------------------------------------------------*
* 애플리케이션 로그에 메시지를 기록하는 공통 서브루틴
*----------------------------------------------------------------------*
FORM write_free_log USING    pv_msgty      TYPE balmi-msgty    " 메시지 유형 (S, I, W, E, A)
                             pv_message    TYPE bapiret2-message " 기록할 메시지 텍스트
                             pv_ext_number TYPE balnrext.      " 외부 식별자 (예: 문서 번호, 프로세스 ID)

  DATA: lv_handle      TYPE balloghndl.       " 생성된 로그의 고유 핸들
  DATA: ls_s_log       TYPE bal_s_log.        " 로그 헤더 정보 구조체
  DATA: lt_log_handles TYPE bal_t_logh.       " 로그 핸들을 저장하는 내부 테이블

  " 1. 로그 헤더 설정: 로그의 기본 속성을 정의합니다.
  "    object와 subobject는 SLG0에서 미리 정의해야 합니다.
  ls_s_log-object    = 'ZMM'.       " 예: 자재 관리 관련 커스텀 오브젝트
  ls_s_log-subobject = 'POINFO'.    " 예: 구매 오더 정보 서브오브젝트
  ls_s_log-extnumber = pv_ext_number. " SLG1에서 검색할 핵심 식별자
  ls_s_log-aldate    = sy-datum.    " 현재 시스템 날짜
  ls_s_log-altime    = sy-uzeit.    " 현재 시스템 시간
  ls_s_log-aluser    = sy-uname.    " 현재 사용자명
  ls_s_log-altcode   = sy-tcode.    " 현재 트랜잭션 코드
  ls_s_log-alprog    = sy-repid.    " 현재 프로그램명

  " 2. 로그 생성: 설정된 헤더 정보로 새로운 로그를 생성하고 핸들을 반환합니다.
  CALL FUNCTION 'BAL_LOG_CREATE'
    EXPORTING
      i_s_log      = ls_s_log
    IMPORTING
      e_log_handle = lv_handle
    EXCEPTIONS
      OTHERS       = 1.
  IF sy-subrc <> 0.
    EXIT. " 로그 생성 실패 시 종료
  ENDIF.

  " 3. 로그 핸들 테이블에 추가: 여러 로그를 한 번에 저장하기 위해 핸들을 모읍니다.
  APPEND lv_handle TO lt_log_handles.

  " 4. 메시지 추가: 생성된 로그에 실제 메시지 텍스트와 유형을 기록합니다.
  CALL FUNCTION 'BAL_LOG_MSG_ADD_FREE_TEXT'
    EXPORTING
      i_log_handle  = lv_handle
      i_msgty       = pv_msgty
      i_text        = pv_message
    EXCEPTIONS
      OTHERS        = 1.
  IF sy-subrc <> 0.
    " 메시지 추가 실패 시 오류 처리 (선택 사항)
  ENDIF.

  " 5. DB 저장: 메모리에 있는 로그를 데이터베이스에 영구적으로 저장합니다. 이 단계가 있어야 SLG1에서 조회 가능합니다.
  CALL FUNCTION 'BAL_DB_SAVE'
    EXPORTING
      i_t_log_handle = lt_log_handles
    EXCEPTIONS
      OTHERS         = 1.
  IF sy-subrc <> 0.
    " DB 저장 실패 시 오류 처리 (선택 사항)
  ENDIF.

ENDFORM.

 

호출예제
아래와 같이 프로그램에서 저장한 후
SLG1 트랜잭션으로 이동하여 
Object: ZMM, Subobject: POINFO를 입력하면 기록된 ABAP 애플리케이션 로그를 확인할 수 있습니다. EXTNUMBER 필드를 활용하면 특정 문서나 프로세스에 대한 로그를 쉽게 필터링할 수 있습니다.
REPORT Z_TEST_APP_LOG_BLOG.

* 위에서 정의된 FORM write_free_log ... 코드가 여기에 포함됩니다.

START-OF-SELECTION.

  " 성공 메시지 기록: 구매 오더 'PO_123456' 생성 성공 로그
  PERFORM write_free_log USING 'S' " Success 유형
                               '구매 오더 123456이 성공적으로 생성되었습니다.'
                               'PO_123456'. " 외부 번호로 PO 번호 지정

  " 경고 메시지 기록: 재고 관련 경고 로그
  PERFORM write_free_log USING 'W' " Warning 유형
                               '재고 부족: 품목 ABC에 대해 재고 확인이 필요합니다.'
                               'ITEM_ABC'. " 외부 번호로 품목 ID 지정

  " 오류 메시지 기록: 데이터 유효성 검사 실패 오류 로그
  PERFORM write_free_log USING 'E' " Error 유형
                               '데이터 유효성 검사 실패: 필수 필드가 누락되었습니다.'
                               'VALIDATION_ERROR'. " 외부 번호로 오류 유형 지정

  " 정보 메시지 기록: 백그라운드 작업 완료 정보 로그
  PERFORM write_free_log USING 'I' " Information 유형
                               '백그라운드 작업 완료: 일괄 처리 프로세스 성공.'
                               'BATCH_JOB_001'. " 외부 번호로 배치 작업 ID 지정

  MESSAGE '로그 기록이 완료되었습니다! SLG1 트랜잭션에서 확인하세요.' TYPE 'I'.

 

여기까지입니다.

 

아래부턴 CBO 남기는 것과 비교하여 일을 추가하였습니다. 참고 정도로 보시면 좋을 것 같습니다.

<< 참고사항 >>

* 커스텀 로깅의 힘: CBO 테이블에 직접 로그 기록하기

CBO(Custom Business Object) 테이블에 직접 로그를 기록하는 방식은 SAP 시스템 내에 개발자가 직접 생성한 투명 테이블(Transparent Table)에 프로그램의 특정 이벤트나 데이터 변경 이력을 저장하는 방법입니다.
이 방식은 SAP 표준 프레임워크의 제약에서 벗어나 완벽한 커스터마이징이 가능하다는 것이 가장 큰 특징입니다.

1. 작동 방식 및 주요 특징

  1. 커스텀 테이블 설계 및 생성: SE11 트랜잭션에서 로그를 저장할 필드(예: 변경 일시, 변경 사용자, 이전 값, 새 값, 관련 문서 번호, 상세 메시지, 특정 플래그 등)를 포함하는 투명 테이블을 직접 설계하고 생성합니다.
  2. ABAP 코드 작성: 프로그램 내에서 특정 이벤트(예: 마스터 데이터 생성/변경/삭제, 트랜잭션 상태 변화)가 발생할 때마다 해당 CBO 테이블에 데이터를 INSERT하거나 MODIFY하는 ABAP 코드를 직접 작성합니다.
  3. 조회 프로그램 개발: SE16N으로 테이블 내용을 직접 조회하거나, ALV 리포트 등 별도의 ABAP 프로그램을 개발하여 로그를 상세하게 조회하고 분석할 수 있습니다.

CBO 테이블 로깅의 주요 특징:

  • 극강의 커스터마이징: 필요한 모든 정보를 원하는 구조와 형태로 자유롭게 저장할 수 있습니다.
  • 데이터 접근 용이성: 표준 테이블처럼 SELECT 문을 통해 직접 데이터에 접근하여 복잡한 통계 분석이나 사용자 맞춤형 리포팅이 매우 용이합니다.
  • 비즈니스 데이터와의 긴밀한 연관성: 특정 비즈니스 데이터의 변경 이력이나 상태 변화를 매우 상세하게 추적하고 감사(Audit) 목적으로 활용하는 데 탁월합니다.

2. BAL vs. CBO 테이블 로그: 핵심 비교 분석

두 가지 SAP 로깅 방법은 "로그를 남긴다"는 공통점을 가지지만, 목적과 활용 방식에서 큰 차이를 보입니다.
프로젝트의 요구사항에 따라 적절한 방식을 선택하는 것이 중요합니다.

구분 Business Application Log (BAL) CBO 테이블 로그
주요 목적 프로그램 실행 결과, 오류, 정보 메시지 기록 및 모니터링, 오류 진단 특정 비즈니스 데이터의 상세 변경 이력, 작업 흐름의 감사 추적
표준/커스텀 SAP 표준 프레임워크 (BAL 함수 모듈) 활용 개발자가 직접 설계하고 구현하는 커스텀 방식
데이터 구조 SAP 표준 테이블(BALHDR, BALDAT, BAL_INDX 등) 사용. 메시지, 헤더 위주. 개발자가 정의한 자유로운 커스텀 테이블 구조. 모든 비즈니스 데이터 필드 포함 가능.
조회 방식 SLG1 트랜잭션 (표준 조회 화면) SE16N 또는 개발자가 만든 맞춤형 리포트/트랜잭션
유연성 정해진 BAL 프레임워크 내에서 유연성 제공. (EXTNUMBER 활용) 데이터 구조, 저장 로직, 조회 방식 모두 완벽한 커스터마이징 가능.
성능 BAL 프레임워크에 최적화되어 있어 대량의 메시지 처리에 유리. 개발자가 구현하는 방식에 따라 성능이 달라질 수 있음. 대량 로깅 시 성능 최적화 필요.
데이터 보존 SLG2 트랜잭션을 통해 표준 삭제 기능 제공. 개발자가 직접 삭제 로직(예: 배치 프로그램)을 구현해야 함.
개발 공수 BAL 함수 모듈 사용법 숙지 시 비교적 낮음. (SLG0 설정 필요) 테이블 설계, 로깅 로직, 조회 리포트까지 모두 개발해야 하므로 초기 공수 높음.
주요 활용 예시 배치 작업 성공/실패 결과, 인터페이스 처리 오류, 예외 상황 알림 마스터 데이터 변경 이력, 트랜잭션 데이터 상태 변화(예: 주문 승인 이력), 사용자 행위 기록
 

3 내 프로젝트에 맞는 로깅 방식 선택 가이드

프로젝트의 성격과 로그 데이터의 활용 목적을 명확히 이해하는 것이 가장 중요합니다.

3.1. BAL(Business Application Log)을 사용해야 하는 경우:

  • 프로그램 실행의 전반적인 흐름 및 결과 기록이 주 목적일 때
    (예: 백그라운드 작업의 성공/실패 여부, 인터페이스 프로그램의 처리 건수 및 오류).
  • SAP 표준화된 오류 및 정보 메시지 관리가 필요하며, SLG1과 같은 표준 조회 화면으로 충분할 때.
  • 운영 담당자나 시스템 관리자가 프로그램의 상태를 빠르게 파악하고 문제 발생 시 초기 진단을 할 필요가 있을 때.
  • 복잡한 비즈니스 데이터와의 상세한 연관성보다는 메시지 텍스트와 몇 가지 식별자(EXTNUMBER)만으로 충분할 때.
  • 다양한 프로그램에서 공통적으로 메시지를 기록해야 하는 범용 로깅 서브루틴을 구현할 때 매우 효과적입니다.

3.2. CBO 테이블에 직접 로그를 기록해야 하는 경우:

  • 특정 비즈니스 데이터의 상세하고 엄격한 변경 이력 추적이 필수적일 때 (예: 구매 오더의 상태 변경 이력, 자재 마스터의 특정 필드 변경 기록, 사용자 권한 변경 이력).
  • 감사(Audit) 목적으로 데이터 변경 이력을 법적 요구사항에 따라 상세하게 보존하고, 데이터의 무결성이 매우 중요할 때.
  • 로그 데이터를 기반으로 복잡한 통계 분석이나 사용자 맞춤형 리포팅이 필요하여, SELECT 문으로 직접 접근 가능한 테이블 구조가 유리할 때.
  • BAL의 표준 필드만으로는 부족하고, 더 많은 비즈니스 관련 필드(예: 플랜트, 회사 코드, 특정 금액, 변경 전 값, 변경 후 값 등)를 함께 저장하고 싶을 때.
  • 특정 비즈니스 프로세스의 단계별 진행 상황이나 결과를 맞춤형으로 기록하고, 이를 다른 비즈니스 로직에 활용해야 할 때.