SAP

Joule vs 직접 코딩 — ABAP 개발자 역할이 바뀐다 #shorts #SAP #Joule

1. 개요 및 이 글에서 다룰 것

SAP Joule은 SAP가 자사 제품군 전반에 통합하고 있는 생성형 AI 코파일럿입니다. ABAP 개발 영역에서는 ADT(ABAP Development Tools) 및 SAP Build Code와 결합해 코드 초안 생성, 단위 테스트 스캐폴딩, 리팩토링 제안 등을 지원합니다. 하지만 Joule이 만능은 아닙니다. 실제 운영 환경에서는 비즈니스 규칙의 정확성, SQL 성능, RFC 통신의 안정성 같은 영역은 여전히 사람이 직접 다루어야 하는 경우가 일반적입니다.

이 글에서 다룰 것:

  • Joule이 잘 처리하는 작업 유형(보일러플레이트, 테스트 스텁, ALV 초안)과 그 한계
  • 개발자가 직접 작성해야 하는 영역(복잡한 비즈니스 규칙, 성능 튜닝 SQL, RFC 예외 처리)
  • Joule과 개발자가 협업하는 3단계 패턴: 초안 생성 → 로직 채움 → 코드 리뷰
  • 실전 ABAP 예제와 흔한 실수, 트러블슈팅 사례
이 글은 Joule을 "단순 자동완성"이 아닌 "신입 페어 프로그래머"로 다루는 관점을 권장합니다.

2. 사전 가정

읽는 분이 다음 항목에 어느 정도 익숙하다고 가정합니다.

  • ABAP OO 기본 문법(클래스, 인터페이스, 예외 클래스 CX_*)
  • Open SQL과 CDS View, 기본 SELECT 최적화 개념
  • ADT(Eclipse 기반 ABAP Development Tools) 사용 경험
  • 단위 테스트 프레임워크 ABAP Unit의 기본 구조(FOR TESTING, cl_abap_unit_assert)
  • SAP BTP 또는 S/4HANA 환경에서의 RAP(RESTful ABAP Programming) 기본 개념

3. 환경 / 버전 / 준비물

Joule의 ABAP 지원 범위는 빠르게 변화하고 있으며, SAP는 일반적으로 다음 환경을 권장합니다.

  • ABAP 플랫폼: SAP S/4HANA 2023 이상 또는 SAP BTP ABAP Environment(Steampunk) 최신 릴리스
  • 개발 도구: ADT 3.40 이상이 설치된 Eclipse 2024-03 이상
  • Joule 통합: SAP Build Code 또는 ADT용 Joule 확장(테넌트별 활성화 필요)
  • 권한: Joule 사용을 위한 BTP 역할 컬렉션, 대상 ABAP 시스템의 개발 권한(S_DEVELOP)
  • 네트워크: Joule 백엔드(LLM 게이트웨이)로의 아웃바운드 HTTPS 허용

로컬에서 사전 점검할 사항을 체크리스트로 정리하면 다음과 같습니다.

  • ADT에서 Window > Preferences > ABAP Development > Joule 항목 존재 여부
  • 샘플 패키지 Z_JOULE_DEMO 생성 및 트랜스포트 할당
  • 테스트용 CDS Entity, 클래스, 인터페이스 한 세트 준비

4. 핵심 개념

Joule은 LLM(대형 언어 모델)을 기반으로 ABAP 코드를 생성하지만, 단순 텍스트 생성기가 아닙니다. SAP는 일반적으로 다음 세 가지 레이어로 Joule의 응답 품질을 끌어올립니다.

  • 컨텍스트 레이어: 현재 열린 ABAP 객체, 패키지, 시스템 메타데이터를 LLM에 함께 전달합니다. 즉, 같은 프롬프트라도 어떤 클래스에서 호출했는지에 따라 결과가 달라집니다.
  • 가드레일 레이어: 코드 스타일, 사용 금지 구문(예: SELECT *), 보안 규칙을 사후 필터링합니다.
  • 모델 레이어: 범용 LLM이 ABAP 토큰을 생성한 뒤, ATC(ABAP Test Cockpit) 친화적인 형태로 정제합니다.

이 구조를 비유하자면 Joule은 "매뉴얼을 통째로 읽은 신입 개발자"입니다. 문법은 알지만, 우리 회사의 비즈니스 도메인은 모릅니다. 따라서 도메인 지식이 적게 필요한 작업일수록 Joule의 적중률이 높습니다.

역할 분담 매트릭스(권장):

  • Joule이 잘 하는 것: 보일러플레이트 클래스, ALV 그리드 초안, 단위 테스트 스켈레톤, RAP Behavior Definition 스텁, 주석 생성, 변수 이름 제안
  • 개발자가 직접 해야 하는 것: 복잡한 비즈니스 규칙(예: 가격 계산 로직), 인덱스를 고려한 성능 SQL, RFC/IDoc 에러 핸들링, 트랜잭션 일관성 보장, 권한 체크(AUTHORITY-CHECK)
  • 협업이 필요한 것: 도메인 모델링, 리팩토링, 코드 리뷰, 테스트 케이스 확장

프롬프트 엔지니어링 측면에서는 구조화된 프롬프트가 권장됩니다. 즉, "무엇을, 어떤 입력으로, 어떤 출력 형태로, 어떤 제약 하에서"의 4요소를 명시할수록 결과가 안정적입니다.

5. 실전 코드

아래 세 단계를 통해 동일한 요구사항("판매 오더 헤더 조회 ALV 리포트")을 Joule, 개발자, 협업 패턴으로 각각 구현해 봅니다.

5-1. 1단계: Joule 활용 — 보일러플레이트와 ALV 초안

ADT에서 Joule 채팅 창에 다음과 같이 프롬프트를 입력합니다.

목적: 판매 오더 헤더(VBAK) 조회 ALV 리포트 클래스 초안
입력: 판매 조직(VKORG), 오더 일자 범위(AUDAT FROM/TO)
출력: cl_salv_table 기반 ALV
제약: SELECT * 금지, INTO TABLE 사용, OO 패턴

Joule이 생성하는 초안은 일반적으로 다음과 같은 형태입니다.

CLASS zcl_so_report DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS run
      IMPORTING iv_vkorg     TYPE vkorg
                iv_audat_fr  TYPE audat
                iv_audat_to  TYPE audat.
  PRIVATE SECTION.
    TYPES: BEGIN OF ty_row,
             vbeln TYPE vbeln_va,
             erdat TYPE erdat,
             ernam TYPE ernam,
             netwr TYPE netwr_ak,
             waerk TYPE waerk,
           END OF ty_row.
    DATA mt_data TYPE STANDARD TABLE OF ty_row.
ENDCLASS.

CLASS zcl_so_report IMPLEMENTATION.
  METHOD run.
    SELECT vbeln, erdat, ernam, netwr, waerk
      FROM vbak
      WHERE vkorg = @iv_vkorg
        AND audat BETWEEN @iv_audat_fr AND @iv_audat_to
      INTO TABLE @mt_data.

    DATA(lo_alv) = cl_salv_table=>factory(
                     EXPORTING r_container = cl_gui_container=>screen0
                     IMPORTING r_salv_table = DATA(lr_alv)
                     CHANGING  t_table = mt_data ).
    lr_alv->display( ).
  ENDMETHOD.
ENDCLASS.

이 초안은 컴파일은 되지만 예외 처리, 권한 체크, 빈 결과 처리가 누락되어 있습니다. 그대로 운영에 쓰면 위험합니다. Joule의 역할은 여기까지가 적절합니다.

5-2. 2단계: 직접 코딩 — 비즈니스 규칙과 에러 핸들링

개발자가 Joule이 만들어 놓은 뼈대를 받아 비즈니스 요구사항을 채워 넣습니다. 예를 들어 "미결제 오더만 조회", "권한 없는 판매 조직 차단", "공급사 결정 로직" 등은 Joule이 회사의 정확한 룰을 알 수 없으므로 사람이 작성합니다.

METHOD run.
  " 1) 권한 체크 - 회사 표준 권한 객체 사용
  AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
    ID 'VKORG' FIELD iv_vkorg
    ID 'ACTVT' FIELD '03'.
  IF sy-subrc <> 0.
    RAISE EXCEPTION TYPE zcx_so_report
      EXPORTING textid = zcx_so_report=>no_auth
                vkorg  = iv_vkorg.
  ENDIF.

  " 2) 미결제 오더만 - 회사 비즈니스 규칙
  TRY.
      SELECT k~vbeln, k~erdat, k~ernam, k~netwr, k~waerk
        FROM vbak AS k
        INNER JOIN vbuk AS u ON u~vbeln = k~vbeln
        WHERE k~vkorg = @iv_vkorg
          AND k~audat BETWEEN @iv_audat_fr AND @iv_audat_to
          AND u~gbstk <> 'C'   " 완결 제외
        INTO TABLE @mt_data.
    CATCH cx_sy_open_sql_db INTO DATA(lx_sql).
      " 로깅 + 사용자 메시지 분리
      zcl_app_log=>error( iv_area = 'SO_REPORT'
                          iv_text = lx_sql->get_text( ) ).
      RAISE EXCEPTION TYPE zcx_so_report
        EXPORTING previous = lx_sql.
  ENDTRY.

  IF mt_data IS INITIAL.
    MESSAGE i001(zso) WITH iv_vkorg.
    RETURN.
  ENDIF.
ENDMETHOD.

이 단계의 핵심은 도메인 지식이 코드에 반영된다는 점입니다. gbstk <> 'C' 같은 조건은 우리 회사의 "미결제"의 정의이며, Joule은 이를 추측할 수 없습니다.

5-3. 3단계: 협업 패턴 — Joule에게 코드 리뷰 받기

완성된 코드를 Joule에게 다시 던져 "리뷰" 역할을 시킬 수 있습니다. 프롬프트 예시는 다음과 같습니다.

아래 ABAP 메서드를 리뷰해 줘.
관점: 1) 성능 2) 예외 처리 3) Clean ABAP 위반 4) 단위 테스트 가능성
출력: 항목별로 우선순위(높음/중간/낮음)와 제안 코드

Joule의 리뷰 응답을 받은 뒤, 단위 테스트 스켈레톤도 함께 요청합니다.

CLASS ltc_so_report DEFINITION FINAL FOR TESTING
  DURATION SHORT RISK LEVEL HARMLESS.
  PRIVATE SECTION.
    DATA mo_cut TYPE REF TO zcl_so_report.
    METHODS:
      setup,
      run_returns_open_orders FOR TESTING,
      run_raises_when_no_auth FOR TESTING.
ENDCLASS.

CLASS ltc_so_report IMPLEMENTATION.
  METHOD setup.
    mo_cut = NEW #( ).
  ENDMETHOD.

  METHOD run_returns_open_orders.
    " given: 테스트 더블 주입(Test Double Framework)
    " when : mo_cut->run( ... )
    " then : cl_abap_unit_assert=>assert_not_initial( ... )
  ENDMETHOD.

  METHOD run_raises_when_no_auth.
    TRY.
        mo_cut->run( iv_vkorg = '9999'
                     iv_audat_fr = '20260101'
                     iv_audat_to = '20260131' ).
        cl_abap_unit_assert=>fail( 'Exception expected' ).
      CATCH zcx_so_report.
        " expected
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

이 패턴의 장점은 인간이 "무엇을 검증할지"를 결정하고, Joule이 "어떻게 적을지"를 채워준다는 데 있습니다. 보일러플레이트 작성 시간이 줄고, 도메인 사고에 더 많은 시간을 쓸 수 있습니다.

6. 흔한 실수 / 트러블슈팅

실수 1. Joule이 만든 SELECT를 그대로 운영에 배포

Joule은 통계 정보 없이 코드를 생성하므로, 인덱스에 맞지 않는 WHERE 조건을 추천할 수 있습니다. 운영 데이터 분포가 큰 테이블(VBAP, BSEG 등)은 반드시 ST05 트레이스 또는 SAT로 실행 시간을 확인하는 것이 권장됩니다.

실수 2. 예외 클래스를 cx_root로 잡기

초안 코드에서 흔히 보이는 CATCH cx_root는 ATC에서 경고가 발생합니다. 구체적인 예외(cx_sy_open_sql_db, cx_sy_conversion_error 등)로 좁히는 것이 일반적입니다.

실수 3. RFC 호출에서 통신 에러 누락

Joule은 CALL FUNCTION ... DESTINATION 코드를 만들 때 system_failure, communication_failure 처리를 자주 빠뜨립니다. 운영 코드에서는 두 가지 모두 명시적으로 잡고 재시도/로깅 정책을 적용해야 안전합니다.

FAQ

  • Q1. Joule이 만든 코드를 회사 코드 표준에 맞추려면? — 사내 Clean ABAP 가이드를 시스템 프롬프트 또는 ADT 설정에 등록하면 일관성이 올라갑니다. 가능한 환경이라면 ATC 변형(Variant)을 Joule에게 컨텍스트로 전달하는 방식이 권장됩니다.
  • Q2. 민감 정보가 LLM으로 전송되지 않나? — SAP는 Joule이 고객 데이터를 학습에 사용하지 않는다고 안내합니다. 그러나 운영 데이터의 일부가 컨텍스트로 전송될 수 있으므로, 마스킹된 테스트 데이터로 작업하는 것이 일반적으로 권장됩니다.
  • Q3. Joule이 잘못된 함수 모듈명을 만들어내요. — 이른바 "환각(hallucination)" 현상입니다. 함수명/CDS명은 반드시 ADT의 Where-Used나 Open Object로 실재 여부를 확인해야 합니다.

7. 다음 단계 / 관련 주제

역할 분담 패턴에 익숙해졌다면 다음 주제로 확장해 보는 것이 좋습니다.

  • RAP + Joule: Behavior Definition, Behavior Implementation의 보일러플레이트를 Joule에 맡기고, 도메인 액션은 직접 구현
  • ABAP Cloud 어댑테이션 레이어: 클라우드 호환 API만 사용하도록 Joule 가드레일 설정
  • ATC + Joule 자동 리팩토링: ATC 발견 항목을 Joule에게 입력으로 주고 수정안 받기
  • SAP Build Code 통합: Joule 채팅을 통한 풀스택 시나리오(CAP + Fiori Elements + ABAP) 자동화
  • 프롬프트 라이브러리 사내 구축: 자주 쓰는 ABAP 작업별 프롬프트 템플릿 관리

8. 핵심 한 줄

Joule은 "빠른 손", 개발자는 "느린 두뇌"입니다. 보일러플레이트는 Joule에게, 비즈니스 규칙과 성능은 사람에게 맡기는 분업이 가장 안정적인 패턴으로 권장됩니다.

참고 자료

댓글 0

아직 댓글이 없습니다.