본문 바로가기
BAPI · BADI · RFC · Interface

[SAP ABAP] BAPI_USER_GET_DETAIL — 사용자 정보 한방 조회 (이메일·이름·회사·역할·락 상태까지)

by Song.sh 2026. 5. 21.

ABAP 으로 자동화·인터페이스 코드를 짜다 보면 "특정 사용자 ID 의 이메일·이름·전화번호·소속 회사를 한 번에 가져오고 싶다" 는 요구가 자주 들어옵니다. 결재 시스템 연동에서 결재자 이메일이 필요할 때, 자체 알림 발송 프로그램에서 사용자 정보가 필요할 때, 로그에 사용자 풀네임을 같이 남겨야 할 때 — SAP 의 사용자 마스터 테이블(USR02·USR21·ADRP·ADR6 등) 을 직접 조인해 가져올 수도 있지만, 표준 BAPI 한 번 호출이 훨씬 깔끔합니다.

 

이 역할을 하는 BAPI 가 BAPI_USER_GET_DETAIL 입니다. 사용자 ID 하나 넣으면 주소·로그온 데이터·역할·프로파일·라이선스·생성자 정보까지 14개 EXPORTING 구조체 + 22개 TABLES 파라미터로 한 번에 받아옵니다. 그중 실무에서 가장 자주 쓰는 부분은 ADDRESS(이름·이메일·전화) + ADMINDATA(생성자·생성일) + COMPANY(회사) + DEFAULTS(언어·타임존) 4개. 노트의 사용 패턴과도 일치합니다.

 

이 글은 BAPI_USER_GET_DETAIL 의 시그니처·핵심 EXPORTING 구조체 4개·요청한 파라미터만 채워주는 동작 원리·이메일이 ADDRESS 와 ADDSMTP 두 곳에 있는 이유·관련 BAPI 패밀리까지 한 화면에 모은 메모입니다.


핵심 — EXPORTING 구조체 4개 + TABLES 통신 데이터

자주 쓰는 EXPORTING 구조체 4개로 95% 의 사용자 정보 요건이 커버됩니다.

파라미터 타입 담는 정보
ADDRESS (★) BAPIADDR3 이름(firstname/lastname) · 대표 이메일(e_mail) · 대표 전화(tel1_numbr/ext) · 부서 · 직책
ADMINDATA BAPIUSERADMIN 생성자(aname) · 생성일(erdat) · 마지막 로그온일(trdat)
COMPANY BAPIUSCOMP 소속 회사 (company)
DEFAULTS BAPIDEFAUL 언어(langu) · 시간대(tzone) · 날짜·소수점 형식 · 프린터 · 코스트센터(kostl)
LOGONDATA BAPILOGOND 사용자 유형(ustyp) · 유효기간(gltgv/gltgb) · 클래스
ISLOCKED BAPISLOCKD 락 상태 (관리자 락·글로벌 락·실패 로그온 락)
ACTIVITYGROUPS (TABLES) BAPIAGR 할당된 역할 목록 (agr_name)

핵심 한 줄: 사용자 ID 만 넘기면 ADDRESS · ADMINDATA · COMPANY · DEFAULTS 4개로 99% 의 정보 요건 해결. 호출 시점에 IMPORTING 으로 받은 EXPORTING 만 BAPI 가 채워주는 패턴이라 사용 안 할 파라미터는 안 받으면 그만큼 빠릅니다.


1단계 — 기본 호출 패턴 (이메일·이름·회사 받기)

가장 단순한 케이스. 사용자 ID 하나로 풀네임 + 이메일 + 회사 받기.

DATA: ls_address     TYPE bapiaddr3,
      ls_admindata   TYPE bapiuseradmin,
      ls_company     TYPE bapiuscomp,
      ls_userdefault TYPE bapidefaul,
      lt_return      TYPE bapirettab.

CALL FUNCTION 'BAPI_USER_GET_DETAIL'
  EXPORTING
    username  = 'TESTUSER01'
  IMPORTING
    address   = ls_address
    admindata = ls_admindata
    company   = ls_company
    defaults  = ls_userdefault
  TABLES
    return    = lt_return.

" 결과 출력
WRITE: / |풀네임   : { ls_address-firstname } { ls_address-lastname }|,
       / |이메일   : { ls_address-e_mail }|,
       / |전화     : { ls_address-tel1_numbr } { ls_address-tel1_ext }|,
       / |회사     : { ls_company-company }|,
       / |언어     : { ls_userdefault-langu }|,
       / |시간대   : { ls_userdefault-tzone }|,
       / |생성자   : { ls_admindata-aname }|,
       / |생성일   : { ls_admindata-erdat }|.

 

핵심 동작:

  • USERNAME 은 BAPI 내부에서 자동으로 대문자 변환됨 — 소문자로 넘겨도 OK
  • IMPORTING 으로 받은 파라미터만 BAPI 내부에서 채워줌 → 사용 안 할 것은 안 받기
  • CACHE_RESULTS = 'X'(기본값) 으로 같은 사용자 반복 호출 시 캐시 활용

2단계 — ADDRESS(BAPIADDR3) 의 자주 쓰는 필드

ADDRESS 구조는 BAPI 중에 가장 풍부한 정보를 담고 있어 알아두면 좋습니다.

필드 의미
FIRSTNAME · LASTNAME 이름 / 성
FULLNAME 표시용 풀네임 (한국어 환경은 보통 비어 있을 수 있음)
E_MAIL 대표 이메일 (SU01 에서 등록된 첫 번째)
TEL1_NUMBR · TEL1_EXT 대표 전화 / 내선
DEPARTMENT 부서
FUNCTION 직책 / 직무
LANGU_P 개인 통신 언어 (이메일 발송 시 활용)
COUNTRY · CITY 국가 / 도시 (회사 주소 정보)

대표 이메일 외에 사용자가 등록한 모든 이메일을 받고 싶으면 ADDRESS 가 아니라 ADDSMTP(TABLES) 를 같이 받습니다 — 다음 단계에서 다룹니다.


3단계 — 모든 이메일 목록 받기 (ADDSMTP)

ADDRESS-E_MAIL 은 한 명의 사용자의 대표 이메일 한 개. 만약 한 사용자에게 여러 이메일이 등록되어 있고 그것을 다 받으려면 ADDSMTP TABLES 파라미터를 추가로 받습니다.

DATA: lt_addsmtp TYPE TABLE OF bapiadsmtp.

CALL FUNCTION 'BAPI_USER_GET_DETAIL'
  EXPORTING
    username = 'TESTUSER01'
  IMPORTING
    address  = ls_address
  TABLES
    addsmtp  = lt_addsmtp          " ★ 모든 이메일
    return   = lt_return.

" 대표 이메일 1개
WRITE: / |대표: { ls_address-e_mail }|.

" 등록된 모든 이메일 (R_3_USER = '1' 이 표준 이메일)
LOOP AT lt_addsmtp INTO DATA(ls_smtp).
  WRITE: / |{ COND #(
    WHEN ls_smtp-r_3_user = '1' THEN '★ 대표'
    ELSE '  추가'
  ) } { ls_smtp-e_mail }|.
ENDLOOP.

 

BAPIADSMTPR_3_USER = '1' 인 행이 SU01 의 "Std." 박스에 체크된 표준 이메일이며, ADDRESS-E_MAIL 과 같은 값입니다. 전화(ADDTEL)·팩스(ADDFAX) 도 동일한 패턴.


4단계 — 역할(Role) · 프로파일 받기

권한 분석이나 결재선 자동 결정 같은 시나리오에서는 사용자의 역할 목록이 필요합니다.

DATA: lt_roles    TYPE TABLE OF bapiagr,
      lt_profiles TYPE TABLE OF bapiprof.

CALL FUNCTION 'BAPI_USER_GET_DETAIL'
  EXPORTING
    username       = 'TESTUSER01'
  TABLES
    activitygroups = lt_roles      " 할당된 역할 목록
    profiles       = lt_profiles   " 할당된 프로파일
    return         = lt_return.

" 역할 출력
WRITE: / '=== 할당된 역할 ==='.
LOOP AT lt_roles INTO DATA(ls_role).
  WRITE: / |{ ls_role-agr_name } { ls_role-from_dat } ~ { ls_role-to_dat } - { ls_role-agr_text }|.
ENDLOOP.

" 프로파일 출력
WRITE: / '=== 할당된 프로파일 ==='.
LOOP AT lt_profiles INTO DATA(ls_prof).
  WRITE: / |{ ls_prof-bapiprof } - { ls_prof-bapiptext }|.
ENDLOOP.

 

FROM_DAT·TO_DAT 는 역할의 유효기간. 결재선 자동 결정 시 "현재 유효한 역할" 만 필터링하려면 sy-datum BETWEEN from_dat AND to_dat 분기.


5단계 — 락 상태 확인 (ISLOCKED)

자동화 프로그램에서 "락 걸린 사용자에게는 메일 보내지 않기" 같은 분기에 사용.

DATA: ls_islocked TYPE bapislockd.

CALL FUNCTION 'BAPI_USER_GET_DETAIL'
  EXPORTING
    username = 'TESTUSER01'
  IMPORTING
    islocked = ls_islocked
  TABLES
    return   = lt_return.

" 락 상태 4종 확인
WRITE: / |로컬 락 (관리자)    : { ls_islocked-local_lock }|,    " L = Locked, U = Unlocked
       / |글로벌 락 (CUA)     : { ls_islocked-glob_lock }|,
       / |실패 로그온 락      : { ls_islocked-wrng_logon }|,
       / |비밀번호 비활성      : { ls_islocked-no_user_pw }|.

" 전체 락 여부 한 줄 판단
IF ls_islocked-local_lock   = 'L'
OR ls_islocked-glob_lock    = 'L'
OR ls_islocked-wrng_logon   = 'L'
OR ls_islocked-no_user_pw   = 'L'.
  WRITE: / '❌ 이 사용자는 락 상태입니다 — 자동 처리 제외'.
ENDIF.

BAPISLOCKD 의 4개 락 필드 중 하나라도 'L'(Locked) 이면 사용자가 로그온 불가 상태. 'U'(Unlocked) 가 정상.


6단계 — BAPI 호출 결과 메시지 처리

RETURN 테이블에서 에러·경고 메시지 분리.

" 사용자 존재 안 함 / 권한 없음 / 락 등 에러 분리
READ TABLE lt_return INTO DATA(ls_return) WITH KEY type = 'E'.
IF sy-subrc = 0.
  WRITE: / |❌ 조회 실패: { ls_return-message }|.
  RETURN.
ENDIF.

" 경고 메시지도 같이 확인
LOOP AT lt_return INTO ls_return WHERE type CA 'EWAI'.
  WRITE: / |[{ ls_return-type }] { ls_return-message }|.
ENDLOOP.

자주 만나는 RETURN 메시지:

  • 사용자 없음'User XXX does not exist'
  • 권한 없음'No authorization to display users' (S_USER_GRP 권한 객체 필요)
  • 주소 정보 부분 누락 — 경고('W') 로 들어옴 / 다른 필드는 정상

7단계 — 관련 BAPI 패밀리

BAPI_USER_GET_DETAIL 은 단일 사용자 조회. 다른 시나리오에는 다른 BAPI 가 표준입니다.

BAPI 용도
BAPI_USER_GETLIST 사용자 목록 검색 (조건별 필터링 — 부서·이름·이메일 등)
BAPI_USER_EXISTENCE_CHECK 사용자 존재 여부만 빠르게 확인 (가벼움)
BAPI_USER_CREATE1 사용자 신규 생성
BAPI_USER_CHANGE 사용자 정보 변경 (BATCHATTRIBUTESX 같은 X-구조체 패턴 사용)
BAPI_USER_LOCK · BAPI_USER_UNLOCK 사용자 락 / 해제
BAPI_USER_PROFILES_ASSIGN 프로파일 할당
BAPI_USER_ACTGROUPS_ASSIGN 역할(Activity Group) 할당

대량 조회는 BAPI_USER_GETLIST 로 후보 사용자 ID 를 먼저 받고, 각 사용자 상세는 BAPI_USER_GET_DETAIL 로 보조하는 패턴이 표준.


흔히 빠뜨리는 함정

RETURN 안 보고 다음 단계 진행

CALL FUNCTION 'BAPI_USER_GET_DETAIL' ...
" ❌ lt_return 안 보고 ls_address-e_mail 바로 사용
SEND MAIL TO ls_address-e_mail.

사용자가 존재하지 않으면 ls_address 가 비어 있어 빈 이메일로 발송 시도됨. RETURN 의 TYPE = 'E' 체크 필수.

S_USER_GRP 권한 누락

자동화 프로그램 실행 사용자에게 S_USER_GRP (Activity 03 = Display) 권한이 없으면 BAPI 가 RETURN 에 권한 에러를 채워 돌려줍니다. 자동 잡 / RFC 호출용 사용자에게 이 권한 미리 부여.

대문자/소문자 혼동

username = 'testuser01'.   " 소문자
" → BAPI 가 내부에서 'TESTUSER01' 로 변환해 처리
" → 결과는 정상이지만 다른 코드에서 sy-uname 비교 시 헷갈림

BAPI 내부에서 자동으로 대문자 변환됨. 호출 측에서 명시적으로 TRANSLATE ... TO UPPER CASE 후 호출하는 패턴이 안전.

CACHE_RESULTS 의 효과 무시

" ❌ LOOP 안에서 같은 사용자 N 번 호출 — 캐시 효과 제대로 활용 X
LOOP AT lt_users INTO lv_user.
  CALL FUNCTION 'BAPI_USER_GET_DETAIL'
    EXPORTING username = lv_user
              cache_results = ' '.   " ❌ 캐시 끔
ENDLOOP.

CACHE_RESULTS = 'X'(기본) 유지하면 같은 사용자에 대한 반복 호출이 빠릅니다. 명시적으로 끄지 마세요.

ADDRESS-E_MAIL 하나만 보고 끝

사용자에게 여러 이메일이 등록된 경우 ADDRESS 의 E_MAIL 은 그중 표준 한 개. 다른 이메일이 필요하면 ADDSMTP 도 같이 받기.

락 상태 무시한 자동 발송

이메일 발송 자동화에서 락 걸린 사용자한테까지 발송하면 의미 없는 메일이 쌓이거나 그룹웨어 측 에러. ISLOCKED 체크 후 분기.

한국어 환경 FULLNAME 비어있음

" ❌ 풀네임을 FULLNAME 으로만 받음 → 빈 값
WRITE: / ls_address-fullname.

" ✅ 한국어 환경에서는 LASTNAME + FIRSTNAME 조합
WRITE: / |{ ls_address-lastname }{ ls_address-firstname }|.

한국어 사용자 마스터는 FULLNAME 이 비어 있는 경우가 흔합니다. LASTNAME + FIRSTNAME 조합으로 직접 만드는 게 안전. 영어 환경은 보통 자동 조합되어 있음.


전체 코드 — 복사용 통합본

자주 쓰는 4개 정보(이메일·이름·회사·역할) + 락 상태 + 메시지 처리 한 사이클.

REPORT zr_user_detail_demo.

PARAMETERS p_uname TYPE bapibname-bapibname OBLIGATORY DEFAULT sy-uname.

DATA: ls_address  TYPE bapiaddr3,
      ls_admin    TYPE bapiuseradmin,
      ls_company  TYPE bapiuscomp,
      ls_default  TYPE bapidefaul,
      ls_locked   TYPE bapislockd,
      lt_smtp     TYPE TABLE OF bapiadsmtp,
      lt_roles    TYPE TABLE OF bapiagr,
      lt_return   TYPE bapirettab,
      ls_return   TYPE bapiret2.

" === BAPI 호출 ===
CALL FUNCTION 'BAPI_USER_GET_DETAIL'
  EXPORTING
    username        = p_uname
  IMPORTING
    address         = ls_address
    admindata       = ls_admin
    company         = ls_company
    defaults        = ls_default
    islocked        = ls_locked
  TABLES
    addsmtp         = lt_smtp
    activitygroups  = lt_roles
    return          = lt_return.

" === 에러 체크 ===
READ TABLE lt_return INTO ls_return WITH KEY type = 'E'.
IF sy-subrc = 0.
  WRITE: / |❌ 조회 실패: { ls_return-message }|.
  RETURN.
ENDIF.

" === 기본 정보 ===
WRITE: / '=== 사용자 정보 ===',
       / |ID         : { p_uname }|,
       / |이름        : { ls_address-lastname }{ ls_address-firstname }|,
       / |대표 이메일 : { ls_address-e_mail }|,
       / |전화        : { ls_address-tel1_numbr } { ls_address-tel1_ext }|,
       / |부서        : { ls_address-department }|,
       / |직책        : { ls_address-function }|,
       / |회사        : { ls_company-company }|,
       / |언어        : { ls_default-langu }|,
       / |시간대       : { ls_default-tzone }|,
       / |코스트센터   : { ls_default-kostl }|.

" === 생성자 정보 ===
WRITE: /, / '=== 관리 정보 ===',
       / |생성자       : { ls_admin-aname }|,
       / |생성일       : { ls_admin-erdat }|,
       / |마지막 로그온 : { ls_admin-trdat }|.

" === 락 상태 ===
WRITE: /, / '=== 락 상태 ===',
       / |로컬 락(관리자)  : { ls_locked-local_lock }|,
       / |글로벌 락(CUA)   : { ls_locked-glob_lock }|,
       / |실패 로그온 락   : { ls_locked-wrng_logon }|,
       / |비밀번호 비활성   : { ls_locked-no_user_pw }|.

IF ls_locked-local_lock = 'L'
OR ls_locked-glob_lock  = 'L'
OR ls_locked-wrng_logon = 'L'
OR ls_locked-no_user_pw = 'L'.
  WRITE: / |⚠️ 이 사용자는 락 상태입니다 — 자동 처리 시 제외 검토|.
ENDIF.

" === 등록된 모든 이메일 ===
WRITE: /, / '=== 등록된 이메일 목록 ==='.
LOOP AT lt_smtp INTO DATA(ls_smtp).
  WRITE: / |  { COND #(
    WHEN ls_smtp-r_3_user = '1' THEN '★'
    ELSE '·'
  ) } { ls_smtp-e_mail }|.
ENDLOOP.

" === 할당된 역할 ===
WRITE: /, / '=== 할당된 역할 ==='.
LOOP AT lt_roles INTO DATA(ls_role)
  WHERE from_dat <= sy-datum
    AND to_dat   >= sy-datum.       " 현재 유효한 역할만
  WRITE: / |  { ls_role-agr_name } - { ls_role-agr_text }|.
ENDLOOP.

" === 경고 메시지 ===
LOOP AT lt_return INTO ls_return WHERE type = 'W'.
  WRITE: / |⚠️ { ls_return-message }|.
ENDLOOP.

이 미니 리포트를 SE38 에 그대로 붙이고 실행하면 사용자 ID 만 입력해서 풀 정보를 한 번에 받을 수 있습니다. 결재 시스템 / 알림 발송 / 사용자 분석 같은 자동화에 그대로 응용 가능.


요약

단계 파라미터 핵심
1 ADDRESS 이름·이메일·전화·부서·직책 (가장 자주 쓰는 한 구조체)
2 ADMINDATA 생성자·생성일·마지막 로그온일
3 COMPANY + DEFAULTS 소속 회사 · 언어 · 시간대 · 코스트센터
4 ADDSMTP 모든 이메일 (R_3_USER='1' 이 표준)
5 ACTIVITYGROUPS + PROFILES 할당된 역할·프로파일 (유효기간 확인)
6 ISLOCKED 4종 락 상태 ('L' / 'U') — 자동 발송 분기에 활용
7 RETURN TYPE = 'E' 체크 필수 / 'W' 는 부분 누락 경고

BAPI_USER_GET_DETAIL 은 SAP 사용자 정보를 한 번에 가져오는 가장 깔끔한 방법입니다. USR02/USR21/ADRP/ADR6 같은 테이블을 직접 조인하는 코드는 SAP 버전·필드 변경에 약하지만, 이 BAPI 는 SAP 가 호환성을 보장합니다. ADDRESS · ADMINDATA · COMPANY · DEFAULTS 네 EXPORTING 만 익숙해지면 결재 자동화 / 메일 발송 / 권한 분석 같은 시나리오에 그대로 재사용 가능. IMPORTING 으로 받은 파라미터만 BAPI 가 채워주는 동작 원리를 이해하면, 필요한 정보만 받아 호출 비용도 줄일 수 있습니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.

BAPI_USER_GET_DETAIL 은 SAP NetWeaver 표준 BAPI(Function Group SU_USER, Package SUSR) 로 ECC 6.0 / S/4HANA on-premise 환경에서 동일하게 동작합니다. 호출 사용자에게 S_USER_GRP 권한 객체(Activity 03 = Display) 가 부여되어 있어야 사용자 정보 조회가 가능하며, 권한이 없으면 RETURN 테이블에 에러 메시지가 채워집니다.

 

ADDRESS 구조(BAPIADDR3) 의 FULLNAME 필드는 한국어 환경에서 비어 있는 경우가 흔하므로 LASTNAME + FIRSTNAME 조합으로 직접 구성하는 것이 안전합니다. 호출 시 IMPORTING 으로 받지 않은 EXPORTING 구조체는 BAPI 내부에서 채우지 않으므로(IS SUPPLIED 분기) 필요한 정보만 받는 것이 성능 면에서 권장됩니다. 본문의 사용자 ID(TESTUSER01) 는 일반화한 예시이며, 사내 환경에서는 실제 사용자 ID 로 교체하여 사용하시기 바랍니다.