News

PA0002 vs PA0006 — 하나는 덮이고 하나는 쌓인다 #shorts #SAP #HR

▶ YouTube에서 보기

이 글이 답하는 질문

  • 왜 어떤 인포타입은 이력이 쌓이고, 어떤 것은 하나만 남나?
  • 시간 제약(time constraint)이라는 게 정확히 무엇을 통제하나?
  • HR 데이터를 조회할 때 왜 날짜 조건을 빼면 안 되나?
  • 같은 사번에 같은 인포타입이 여러 건 나오면 어느 것이 맞는 값인가?
  • 서브타입이 있으면 규칙이 어떻게 달라지나?

이 글을 보기 전에

인사 마스터 화면(PA20/PA30)을 열어 본 경험이면 충분합니다. 급여 계산이나 스키마를 몰라도 됩니다. ABAP 조회 예제가 나오므로 SELECT 문 정도만 읽을 수 있으면 됩니다.

인포타입은 언제나 기간을 가진다

HR 데이터의 출발점은 이겁니다. 인사 정보는 시점에 따라 값이 달라지므로, 모든 인포타입 레코드에 유효기간이 붙습니다.

모든 PA 인포타입 테이블의 공통 키

  PERNR   사번
  INFTY   인포타입 번호 (0002, 0006, ...)
  SUBTY   서브타입 (주소 종류 등)
  BEGDA   유효 시작일
  ENDDA   유효 종료일

즉 "홍길동의 주소"가 아니라
   "홍길동의 2026.03.01 ~ 9999.12.31 주소"
가 한 건이다

그래서 인사 데이터를 조회할 때 사번만 넣으면 과거 이력까지 전부 나옵니다. 지금 유효한 값을 원한다면 날짜 조건이 반드시 들어가야 합니다. 이걸 빼먹는 바람에 값이 여러 건 나오는 상황이 HR 조회에서 제일 자주 벌어집니다.

시간 제약이 이력 여부를 정한다

여기가 핵심입니다. 인포타입마다 시간 제약(time constraint) 값이 정해져 있고, 이것이 "같은 기간에 몇 건까지 존재할 수 있나"를 통제합니다.

시간 제약 1
  전체 기간에 빈틈 없이, 항상 정확히 1건
  새 값을 넣으면 기존 레코드가 끊긴다
  예: 개인정보, 조직배정, 기본급

시간 제약 2
  같은 기간에 최대 1건. 없어도 된다
  예: 장애 정보처럼 해당자만 있는 항목

시간 제약 3
  같은 기간에 여러 건 공존 가능
  예: 주소(자택·긴급연락), 자격증

제약 1이 "덮어써지는 것처럼 보이는" 이유입니다. 실제로는 덮어쓰는 게 아니라 기존 레코드의 종료일을 하루 전으로 끊고 새 레코드를 잇는 방식입니다. 그래서 이력은 남지만, 특정 시점으로 보면 항상 한 건입니다.

제약 1 — 조직배정 변경 (2026.07.01 부서 이동)

  변경 전
    2024.01.01 ~ 9999.12.31   영업1팀

  변경 후
    2024.01.01 ~ 2026.06.30   영업1팀   ← 종료일이 끊김
    2026.07.01 ~ 9999.12.31   영업2팀   ← 새로 이어짐

제약 3 — 주소 추가

  2024.01.01 ~ 9999.12.31   자택 주소
  2026.05.01 ~ 9999.12.31   긴급연락 주소   ← 공존

테스트 환경

  • S/4HANA 2023 온프레미스, SAP HCM(PA) 기준
  • 확인에 쓰는 표준 트랜잭션 — PA20, PA30, SE11, SM30(V_T582A)
  • 조회 예제는 ADT(Eclipse)에서 작성

이 글의 예제는 제조업 인사 운영을 가정해 구성했습니다. 사번 00104471을 기준으로 설명합니다.

직접 해보기

1. 인포타입의 시간 제약을 확인한다

추측하지 말고 설정값을 직접 봅니다. 인포타입 속성 테이블에 들어 있습니다.

* 인포타입별 시간 제약 조회
SELECT infty,        " 인포타입
       zeitb,        " 시간 제약 (1/2/3)
       subty_flag    " 서브타입 사용 여부
  FROM t582a
  WHERE infty IN ( '0002', '0006', '0001', '0008' )
  INTO TABLE @DATA(lt_attr).

" zeitb = '1' → 항상 1건
" zeitb = '2' → 최대 1건
" zeitb = '3' → 여러 건 가능

SM30에서 V_T582A를 열어도 같은 값을 화면으로 볼 수 있습니다. 커스텀 인포타입을 만들 때도 이 값을 정해야 하므로, 설계 단계에서 반드시 짚는 항목입니다.

자주 다루는 인포타입의 제약을 미리 알아 두면 조회 코드를 쓸 때 헷갈리지 않습니다.

제약 1 — 시점마다 정확히 1건
  0001  조직배정 (부서·직위)
  0002  개인정보 (이름·생년월일)
  0007  근무시간
  0008  기본급

제약 3 — 여러 건 공존
  0006  주소 (자택·긴급연락·우편물)
  0021  가족 (배우자·자녀 여러 명)
  0105  통신 (사번·메일·전화)

제약 2 — 있을 수도 없을 수도, 최대 1건
  0004  장애 정보

0021 가족 인포타입이 제약 3인 게 직관적입니다. 자녀가 둘이면 두 건이 있어야 하니까요. 반대로 0002 개인정보가 제약 1인 것도 당연합니다 — 한 시점에 생년월일이 두 개일 수는 없습니다.

0105 통신도 제약 3인데, 서브타입으로 종류가 갈립니다. 사번용, 메일용, 휴대폰용이 각각 한 건씩 공존합니다. 그래서 "이 사람 이메일" 하나만 필요한데도 서브타입 없이 조회하면 사번이 나올 수 있습니다.

2. 특정 시점의 값을 정확히 뽑는다

조회의 정석은 기준일을 기간에 넣는 것입니다.

* 기준일에 유효한 조직배정 (제약 1 → 1건)
DATA(lv_key) = sy-datum.

SELECT SINGLE pernr, orgeh, plans, begda, endda
  FROM pa0001
  WHERE pernr = @lv_pernr
    AND begda <= @lv_key
    AND endda >= @lv_key
  INTO @DATA(ls_org).

* 기준일에 유효한 주소 전부 (제약 3 → 여러 건)
SELECT pernr, subty, stras, ort01, begda, endda
  FROM pa0006
  WHERE pernr = @lv_pernr
    AND begda <= @lv_key
    AND endda >= @lv_key
  INTO TABLE @DATA(lt_addr).

제약 1이면 SELECT SINGLE이 안전하지만, 제약 3에서 SELECT SINGLE을 쓰면 여러 건 중 아무거나 하나가 잡힙니다. 서브타입까지 조건에 넣어야 원하는 종류를 특정할 수 있습니다.

* 자택 주소만 (서브타입 지정)
    AND subty = '1'

3. 이력을 시간순으로 본다

"언제 무엇이 바뀌었나"를 볼 때는 날짜 조건을 빼고 정렬합니다.

* 조직 이동 이력
SELECT pernr, begda, endda, orgeh, plans
  FROM pa0001
  WHERE pernr = @lv_pernr
  ORDER BY begda
  INTO TABLE @DATA(lt_hist).

" 제약 1이므로 기간이 빈틈없이 이어진다
" 앞 레코드의 endda + 1 = 다음 레코드의 begda

제약 1 인포타입은 기간이 연속이어야 정상입니다. 중간에 빈 구간이 있으면 데이터 정합성 문제이고, 그 기간을 기준일로 조회하면 아무 값도 안 나옵니다. 반대로 제약 3은 기간이 끊겨 있어도 정상입니다.

4. 왜 여러 건이 나왔는지 진단한다

조회 결과가 예상과 다르면 아래 순서로 좁힙니다. 원인이 셋 중 하나입니다.

* 사번의 해당 인포타입 전체를 기간과 함께 펼친다
SELECT pernr, subty, begda, endda
  FROM pa0006
  WHERE pernr = @lv_pernr
  ORDER BY subty, begda
  INTO TABLE @DATA(lt_all).

판단
  ① 기간이 서로 겹치지 않고 줄줄이 이어진다
     → 이력이다. 기준일 조건이 빠진 것

  ② 같은 기간에 subty 가 다른 건이 여럿이다
     → 제약 3이다. 서브타입을 지정해야 한다

  ③ 같은 기간에 subty 도 같은 건이 여럿이다
     → 데이터 오류. 제약 위반이므로 인사팀 확인 필요

③은 드물지만 데이터 이관 직후에 나옵니다. 표준 화면으로 입력하면 시스템이 막지만, 이관 프로그램이 테이블에 직접 넣으면 제약을 우회할 수 있기 때문입니다. 이관 검증 항목에 "제약 1·2 인포타입의 기간 중복 여부"를 넣어 두면 이런 사고를 미리 잡습니다.

참고로 ENDDA9999.12.31인 레코드가 두 건 이상 보이면 ②나 ③일 가능성이 큽니다. 제약 1이라면 그런 레코드는 하나뿐이어야 합니다.

왜 이 구조가 필요한가

번거로워 보이지만 이유가 분명합니다.

  • 소급 처리 — 3개월 전 부서 이동이 늦게 반영되면, 그 시점의 조직으로 급여를 다시 계산해야 합니다. 시점별 값이 남아 있어야 가능합니다.
  • 법적 보존 — 인사 기록은 변경 이력 자체가 보존 대상입니다. 덮어쓰면 남지 않습니다.
  • 미래 발령 — 다음 달 1일부 인사를 미리 입력해 둘 수 있습니다. 기준일 조회이므로 오늘 조회에는 영향이 없습니다.

세 번째가 실무에서 자주 혼란을 만듭니다. 미래 레코드가 이미 들어와 있는데 개발자가 날짜 조건 없이 조회하면, 아직 오지 않은 부서가 나옵니다.

실제로 이런 문의가 들어옵니다. "인사팀은 아직 영업1팀이라는데 우리 화면에는 영업2팀으로 뜬다"는 식입니다. 데이터가 틀린 게 아니라 다음 달 발령이 이미 등록돼 있고, 조회 쪽이 그걸 걸러내지 않은 것입니다.

미래 발령이 있는 상태

  2024.01.01 ~ 2026.08.31   영업1팀   ← 오늘 유효
  2026.09.01 ~ 9999.12.31   영업2팀   ← 미래

  날짜 조건 없이 ORDER BY begda DESCENDING
  → 영업2팀이 첫 행으로 잡힌다  ❌

  begda <= sy-datum AND endda >= sy-datum
  → 영업1팀  ✅

"최신 레코드를 가져온다"는 접근이 위험한 이유가 여기 있습니다. HR에서 최신은 가장 늦게 시작하는 것이 아니라 지금 시점을 덮는 것입니다. 정렬로 해결하려 들면 미래 데이터가 들어오는 순간 틀립니다.

기준일을 파라미터로 받아 두면 과거 조회도 같은 코드로 처리됩니다. 6월 기준 조직도를 뽑아 달라는 요청이 오면 lv_key만 바꿔 넣으면 됩니다.

자주 만나는 함정

  • 날짜 조건 없이 조회 — 과거·미래 레코드까지 전부 나옵니다. 건수가 여러 개면 대개 이 문제입니다.
  • 제약 3에 SELECT SINGLE — 자택 주소를 원했는데 긴급연락 주소가 잡힙니다. 서브타입을 함께 넣어야 합니다.
  • ENDDA를 오늘로 비교 — 유효 종료일은 보통 9999.12.31입니다. endda = sy-datum으로 찾으면 아무것도 안 나옵니다. 범위 비교여야 합니다.
  • 제약 1인데 기간이 끊긴 데이터 — 조회 결과가 비어 나오는 원인입니다. 값이 없는 게 아니라 그 시점을 덮는 레코드가 없는 상태입니다.
  • 테이블 직접 조회로 권한 우회 — PA 테이블을 직접 읽으면 인사 권한 체크가 걸리지 않습니다. 표준 조회 수단을 쓰거나 권한 검사를 직접 넣어야 합니다.

핵심 한 줄

인포타입 레코드는 값이 아니라 기간을 가진 값입니다. 시간 제약 1이면 특정 시점에 항상 1건이라 덮어써지는 것처럼 보이고, 제약 3이면 여러 건이 공존합니다. 그래서 조회에는 기준일이 반드시 들어가야 합니다.

더 파볼 주제

  • 서브타입별 시간 제약을 따로 두는 경우
  • 소급 회계와 급여 재계산이 트리거되는 조건
  • 커스텀 인포타입 생성 시 정해야 하는 속성들
  • 인사 권한 오브젝트와 구조적 권한의 차이

댓글 0

아직 댓글이 없습니다.