본문 바로가기

ABAP 프로그래밍 개념/ABAP Dynamic Programming(동적 프로그래밍)

2.ABAP 동적 프로그래밍 : 필드 심볼(Field Symbol) 2

먼저 이 글을 읽기 앞서서 필드 심볼 1편을 안읽으신 분은 먼저 읽기를 추천드립니다.

2023.03.08 - [ABAP 프로그래밍 개념/ABAP Dynamic Programming(동적 프로그래밍)] - 2.ABAP 동적 프로그래밍 : 필드 심볼(Field Symbol) 1

 

2.ABAP 동적 프로그래밍 : 필드 심볼(Field Symbol) 1

Field Symbol( 이하 필드심볼) 은 Pointer(존재하는 Data Object를 가르키는)와 비슷한 개념입니다, 필드 심볼은 data object는 아니기 때문에, 그 자신이 소유한 어떠한 메모리도 잡고 있지 않습니다. 대신에

abapta0903.tistory.com


필드 심볼 정의


필드심볼은 FIELD-SYMBOLS라는 구문을 사용하여 선언됩니다. 필드 심볼의 이름은 < > 사이의 네이밍으로 정의됩니다. 필드 심볼의 타입(유형)은 TYPE 참조와 LIKE 참조를 사용하는 Data Object와 같습니다.

또한 ANY라는 유형을 써서 Generic Field Symbol을 정의할 수 있습니다. Fully Types Field Symbol을 사용할 때, 오직 같은 Type의 Data Object만이 필드 심볼에 할당될 수 있습니다. 이것은 Structure의 구성요소에 정적으로 접근할 계획이 있을 때 유용합니다.

예를 들어, 아래 예시와 같이 Structure의 각각의 구성요소와 작업을 하는 경우에는, 필드 심볼은 Fulley Type 입니다. 

DATA st_mara TYPE mara.

FIELD-SYMBOLS: <fs_mara> TYPE mara,
               <fs_matnr> TYPE matnr.
               
ASSIGN st_mara TO <fs_mara>.
<fs_mara>-matnr = '100'.


ASSIGN st_mara-matnr TO <fs_matnr>.

 

만약 필드 심볼을 동적으로 어떠한 필드나 구조체를 동적으로 바라보게 하고 싶다면, 필드 심볼을 Generic Type으로 TYPE ANY라는 addition을 사용하여 정의할 수 있습니다. 그러나 , Generic Type을 쓰면, 구성요소들에 대해서는 Runtime 시에만 알 수 있기 때문에, 정적으로 구문을 통해 접근하는 것은 불가능합니다.

DATA st_mara TYPE mara.
FIELD-SYMBOLS: <fs_any> TYPE ANY.
ASSIGN st_mara TO <fs_any>.
* <fs_any>-matnr = '100'. "ERROR"
ASSIGN st_mara-matnr TO <fs_any>.

또한, 인터널 테이블을 필드 심볼로 할당할 수 있습니다. 인터널 테이블을 할당하기  위해서는, 필드 심볼이 table로 정의되어야 합니다. 

FIELD-SYMBOLS <fs_mara> TYPE STANDARD TABLE OF mara.

 

필드 심볼은 데이터 객체처럼 어떤 종류의 내부 테이블이든 정의할 수 있습니다. 또한, 내부 테이블에 적용 가능한 모든 동작과 문장을 수행할 수도 있습니다. 예를 들어, 필드 심볼과 함께 LOOP 문을 사용하더라도 Syntax Checker는 오류를 발생시키지 않습니다.

만약, 개발과정에서 인터널 테이블들을 동적으로 필드심볼에 할당한다면, 필드심볼은 Generic Table로 선언하기  위하여 ANY TABLE이라는 문법을 사용해야 됩니다.

FIELD-SYMBOLS <fs_table> TYPE ANY TABLE.

Data Object 할당하기


1. Assign 구문은 Data Object를 필드심볼에 할당하기 위하여 사용합니다.

ASSIGN data_object TO <fs>.

Assignment 동작은 정적 & 동적 둘다 수행이 가능합니다.
이름을 알고 있는 Data Object를 필드심볼에 할당하는 경우에는, Data Object의 할당이 정적으로 진행됩니다.

DATA st_mara TYPE mara.
FIELD-SYMBOLS: <fs_mara> TYPE mara.
ASSIGN st_mara TO <fs_mara>.

2. 런타임시에 동적으로 Data Oject를 필드심볼에 할당하기 위해 사용

때로, 오직 런타임 시에만 동적으로 할당하고 싶은 Data Object가 있을 수 있습니다. 특정 필드 혹은 변수에 대한 Data Object를 프로그램 실행시에만 할당하고 싶은 경우에는 아래와 같은 구문을 사용 할 수 있습니다.

ASSING (name) TO <fs>.

여기서, name 변수는 data obejct의 이름을 지칭하고, 변수는 반드시 괄호( ) 안 에 들어 있어야 합니다.

DATA field_name TYPE string.
FIELD-SYMBOLS <fs_field> TYPE ANY.

SELECT SINGLE ... FROM ... INTO field_name WHERE ....

ASSIGN (field_name) TO <fs_field>.

위 예시는 동적할당의 예시입니다. 여기서 FIELD_NAME이라는 변수에 담겨있는 data object는 필드 심볼로 할당될 것 입니다. 할당이 성공적으로 된다면, 시스템 필드 SY-SUBRC 는 0 값을 가질 것입니다.

동적 할당을 사용할 떄는, 필드 심볼에 접근하기 전에 필드 심볼이 할당되어 있는지 확인하는 것이 중요합니다. 할당되지 않은  필드심볼에 접근하는 것을 시도하는 것은 런타임 에러를 발생시킵니다.

3.동적 할당을 통해서 클래스의 속성(attribute)를 필드 심볼에 할당할 수도 있습니다.

ASSIGN class_reference_object->(attribute_name) TO <fs>.

이 할당에서는, 속성의 이름이 동적으로 이끌어집니다.

Static Attribute에 접근하는 것이라면, 클래스 이름을 동적으로 제시하여야합니다.

ASSIGN (class_name)=>(attribute_name) TO <fs>.
ASSIGN (class_name)=>attribute TO <fs>.

위 첫번째 예시는, 클래스 이름과 Attribute 이름을 둘 다 동적으로 제시했으나, 반면에 두번째 예시는 클래스이름을 동적으로 제시하고 Attribute 이름은 적적으로 제시하였습니다.

4. Strucutre(구조체)의 구성요소를 동적으로 필드 심볼에 할당할 수 있습니다.

ASSIGN component_name OF STRUCTURE struc TO <fs>.

위 구문을 통해선, Struc라는 Structure의 구성요소인 component_name을 <fs>로 할당합니다. 만약 component_name라는 Data Object가 'Charater' 혹은 'String' 타입이라면, component_name의 내용(데이터)가 component_name이라는 이름으로 해석 될 것입니다. 예를 들어 아래 예시를 보면, matnr 필드가 가지고 있는 값을 필드 심볼로 할당하는 것입니다.

DATA : st_mara TYPE mara,
       l_field TYPE string VALUE 'MATNR'.
       
FIELD-SYMBOLS: <fs_any> TYPE any.
ASSIGN l_field OF STRUCTURE st_mara TO <fs_any>.

 

그러나, 만약 Data Object인 component_name가 다른 형식이거나 숫자를 포함하고 있다면, 시스템은 이전 처럼 필드 이름으로 읽는 것이 아니라 구조체에서 필드의 위치로 해석하고 그 값을 필드 심볼에 할당합니다. 아래 예시를 보면, 구조체 st_mara의 3번째 필드인 mtart가 필드 심볼로 할당될 것인데 그 이유는 l_field라는 Data Object가 3이라는 값을 포함하고 있기 때문입니다.

TYPES: BEGIN OF ty_mara,
        matnr TYPE matnr,
        ersda TYPE ersda,
        mtart TYPE mtart,
      END OF ty_mara.
      
DATA : st_mara TYPE ty_mara,
	   l_field TYPE n VALUE 3.
       
FIELD-SYMBOLS: <fs_any> TYPE any.
ASSIGN l_field OF STRUCTURE st_mara TO <fs_any>.

 

5. 인터널 테이블에 대해 작업할 때 필드 심볼을 Work Area로 사용할 수 있습니다. 인터널 테이블 데이터는 READ와 LOOP 구문을 쓸 때 addition으로 ASSIGNING을 사용하여 필드 심볼에 할당할 수 있습니다.

READ TABLE itab ASSIGNING <fs>...

LOOP AT itab ASSIGNING <fs>..

ENDLOOP.

LOOP와 READ 문에 필드심볼을 사용하여 인터널 테이블 데이터를 할당하면, 필드 심볼은 할당된 테이블의 Row를 바로 가르키게 됩니다. 그렇기 때문에, 해당 Row의 어떠한 필드의 데이터를 바로 바꾸어도 바뀐 값이 적용됩니다.

TYPES: BEGIN OF ty_mara,
		matnr TYPE matnr,
		ersda TYPE ersda,
		mtart TYPE mtart,
       END OF ty_mara.
       
DATA : it_mara TYPE TABLE OF ty_mara.
FIELD-SYMBOLS: <fs_mara> LIKE LINE OF it_mara.

PARAMETERS p_matnr TYPE matnr.

SELECT matnr ersda mtart 
  FROM mara 
  INTO TABLE it_mara 
  WHERE matnr EQ p_matnr.
  
READ TABLE it_mara ASSIGNING <fs_mara> INDEX 1.

IF <fs_mara> IS ASSIGNED.
	<fs_mara>-mtart = 'ROH'.
ENDIF.

위 예시를 보면, IT_MARA의 첫 Row는 <fs_mara>에 할당되어 있습니다. <fs_mara>는 IT_MARA의 첫 번째줄을 바로 가르키게 되고, <fs_mara>-mtart = 'ROH' 구문은 IT_MARA의 첫 번째 줄의 해당 필드의 값을 바로 바꿀 것입니다. Work Area를 사용할 때와 달리, 필드심볼을 사용하면, MODIFY 구문을 사용하여 Work Area의 값을 인터널 테이블에 복사할 필요가 없습니다.


필드 심볼 할당(Assign) 체크


Data Object가 필드 심볼에 할당된다면, 시스템 변수인 SY-SUBRC는 0으로 떨어집니다. 만약 할당 이후 바로 할당 유무를 확인하고 싶다면, SY-SUBRC 필드를 확인하면 됩니다.

ASSIGN dobj TO <fs>.

IF sy-subrc IS INITIAL.
 <fs> = 123.
ENDIF.

그러나, 대부분 상황에서, 할당 이후에 바로 필드 심볼에 접근하기보다는, 코드 안에서 추후에 접근할 필요성이 많을 것입니다. 이러한 경우에는 SY-SUBRC 시스템 변수를 확인하는 것은 유용하지 않고, SY-SUBRC는 가장 마지막에 수행된 구문의 결과에 따라 값이 Update 됩니다.

필드 심볼을 사용하기 전에 할당되있는 것을 확인하기 위해서는, IS ASSIGNED 구문을 다음과 가이 사용하면 됩니다.

IF <fs> IS ASSIGNED.

ENDIF.

SAP에서는 필드 심볼에 접근(사용)하기 전에 항상 IS ASSIGNED를 사용하여 확인하는 것을 추천합니다. 할당되지 않는 필드 심볼에 접근하기를 시도하는 것은 개발자가 쉽게 다루지 못하는 예외처리가 발생하기 때문입니다.


Unassigning a Field Symbol(필드심볼 할당 풀기)


필드 심볼에 어떠한 Data Object 데 대한 할당을 제거하기 위해서는, UNASSIGN 구문을 사용합니다.

UNASSIGN <fs>.

필드 심볼의 할당이 풀리고 나면, 필드 심볼은 초기화(Initialized)되고, 어떠한 Data Object도 가르키지 않습니다. 이후에는 다른 Data Object가 필드 심볼에 할당되기 전까지는 할당이 풀리고나면(Unassigned) 필드 심볼에 접근할 수 없습니다.

다른 Data Object와 달리, CLEAR 구문을 통해서는 필드 심볼을 초기화 할수 없고 CLEAR는 해당 필드 심볼이 가르키고 있는 '값'만을 지울 뿐입니다. 그래서 필드 심볼 초기화를 위해서는 반드시 UNASSIGN을 사용해야 합니다.


Casting


Data Object가 필드 심볼에 할당될 때, 필드 심볼은 Data Object와 Type이 양립할 수 있어(compatible)야 합니다. 그러나, 양립할 수 있는 경우가 아니라고 하더라도 Data Object가 필드 심볼에 할당 될때 어떠한 데이터 Type에 대해서도 cast(형변환)을 수행할 수 있습니다.

Casting(형변환)은 특정 data type을 다른 data type으로 다룰 수 있게 해줍니다. 이 의미는, 메모리의 모든 영역이 주어지는 유형을 가정하여 볼 수 있음을 의미합니다. 

예를 들어, Data Object가 형변환을 수행함으로서 필드 심볼에 할당될 때, Character 필드의 값을 Date 필드의 값으로 해석할 수 있습니다.

CASTING 구문이 cast를 수행할 때 사용됩니다.

ASSIGN dobj TO <fs> CASTING.

CASTING을 사용할 때, 다른 type의 Data Object는 필드 심볼에 할당 될 수 있습니다. Casting은 Data Object와 필드 심볼의 type이 양립하지 않더라도, Data Object를 필드 심볼에 할당될 수 있게 해줍니다.

아래 코드는, TYPE c의 필드를 Type D의 필드 심볼로 할당하는 과정입니다. Data Object의 할당 후에는, Data Object의 내용(데이터)는 Type D로 해석될 것입니다.

DATA text(8) TYPE c VALUE '20111201'.

FIELD-SYMBOLS <fs> TYPE sy-datum.

ASSIGN text TO <fs> CASTING.
WRITE <fs>.

Casting은 함축적으로 혹은 명시적으로 수행될 수 있습니다. 필드 심볼이 Fully Type이거나 ABAP type( c, n, p , x 등)을 사용하는 경우라면, CASTING은 ASSIGN 구문을 사용하고, 함축적으로 형변환을 진행할 것입니다.

만약, 필드 심볼의 유형이 Generically 하다면, 명시적으로 Data Type을 구체화하여 형변환을 시켜야 합니다.

ASSIGN dobj TO <fs> CASTING [TYPE data_type|LIKE dobj].

CASTING이라는 addition 뒤에, 코드를 통해 data type이나 data obejct를 구체화 할 수 있습니다. Casting은 구체화한 유형에 따라 수행될 것 입니다. 구체화할 유형이 필드 심볼의 Generic Type과 양립할 수 있다면, 명시적으로 Casting을 할 필요는 없습니다. 

반응형