IDL(Interface Definition Language) 문법 기초

IDL(Interface Definition Language) 문법 기초

DDS(Data Distribution Service) 시스템 구축의 여정은 데이터 그 자체를 정의하는 것에서부터 시작된다. 분산 시스템에서 데이터는 단순한 정보의 파편이 아니라, 시스템의 각 구성 요소가 서로 소통하고 협력하게 만드는 언어이자 계약(Contract)이다. 이 계약이 명확하지 않다면, 제아무리 고성능의 네트워크와 최신 하드웨어를 갖추었다 한들 시스템은 제대로 작동할 수 없다. 서로 다른 프로그래밍 언어, 상이한 운영체제, 그리고 엔디안(Endianness)이 다른 하드웨어 아키텍처 사이에서 데이터의 의미와 구조를 오해 없이 전달하기 위해 OMG(Object Management Group)는 IDL(Interface Definition Language)이라는 표준을 정립했다.1

본 장의 3.1절에서는 DDS 애플리케이션 개발의 초석이 되는 IDL의 문법 기초를 매우 상세하게 다룬다. 단순히 문법적 규칙을 나열하는 수준을 넘어, IDL이 탄생하게 된 배경, 컴파일러가 이를 해석하는 원리, 그리고 각 문법 요소가 실제 C++, Java, Python 등의 언어로 변환될 때 발생하는 매핑의 미학을 심층적으로 분석한다. 독자는 이 과정을 통해 단순한 데이터 구조체 작성을 넘어, 시스템의 상호 운용성(Interoperability)을 보장하는 견고한 데이터 모델링의 철학을 습득하게 될 것이다.

1. IDL의 개요와 철학: 시스템 간의 ‘에스페란토’

IDL은 본래 분산 객체 기술의 시초라 할 수 있는 CORBA(Common Object Request Broker Architecture) 스펙의 핵심 구성 요소로 등장했다.2 CORBA는 이기종 환경에서의 메서드 호출(RPC)을 목표로 했으나, 그 과정에서 정의된 IDL의 강력한 표현력과 언어 중립적인(Language Neutral) 특성은 데이터 중심(Data-Centric) 미들웨어인 DDS에서도 그 가치를 인정받았다.

1.1 정의 언어(Definition Language) vs 구현 언어(Implementation Language)

IDL을 접하는 개발자가 가장 먼저 명심해야 할 점은 IDL이 ’구현’을 위한 언어가 아니라 ’정의’를 위한 언어라는 사실이다.3 IDL 파일 내부에는 알고리즘, 제어 흐름(if, for, while), 메모리 할당, 혹은 변수의 초기화 로직이 존재하지 않는다. 오직 데이터의 형태(Type), 구조(Structure), 그리고 인터페이스(Interface)의 선언만이 존재한다. 이를 ’선언적 언어(Declarative Language)’라고 칭한다.

DDS 개발자가 .idl 확장자를 가진 파일을 작성하면, DDS 벤더(RTI, eProsima, OCI 등)가 제공하는 IDL 컴파일러(또는 코드 생성기, Code Generator)가 이 파일을 읽어 들인다. 그리고 개발자가 목표로 하는 대상 언어(Target Language)에 맞는 소스 코드를 자동으로 생성해낸다.4 예를 들어, IDL로 정의된 struct는 C++의 classstruct, Java의 class, Python의 class로 각각 변환된다.

이러한 접근 방식은 다음과 같은 강력한 이점을 제공한다:

  1. 언어 독립성: 시스템의 한 노드는 C++로, 다른 노드는 Java로, 또 다른 노드는 Python으로 작성되더라도 동일한 IDL 파일을 공유함으로써 완벽하게 호환되는 데이터 통신이 가능하다.6
  2. 유지보수성: 데이터 구조가 변경될 때 IDL 파일 하나만 수정하고 코드를 재생성하면, 모든 언어의 데이터 타입 정의가 일관성 있게 업데이트된다.
  3. 강타입(Strong Typing) 보장: XML이나 JSON과 같은 스키마리스(Schemaless) 또는 런타임 검증 방식과 달리, IDL은 컴파일 타임에 데이터 타입의 정합성을 엄격하게 검사한다. 이는 미션 크리티컬 시스템에서 런타임 오류를 획기적으로 줄여준다.6

1.2 IDL의 진화: CORBA에서 DDS-XTypes까지

IDL은 멈춰있는 표준이 아니다. 초기 CORBA 시절의 IDL 2.x 버전은 객체 지향적 인터페이스 정의에 치중했으나, 컴포넌트 모델을 위한 IDL 3.x를 거쳐, 현재는 데이터 모델링의 유연성을 극대화한 IDL 4.x(IDL4) 시대로 진입했다.2

특히 DDS에서는 XTypes (Extensible and Dynamic Topic Types) 표준과 맞물려 IDL의 중요성이 더욱 부각되었다. IDL 4.2와 XTypes는 데이터 타입의 확장성(Extensibility)을 지원하기 위해 @appendable, @mutable과 같은 어노테이션(Annotation)을 도입했다. 이는 시스템 운영 중에 데이터 구조가 일부 변경되더라도 기존 시스템과의 호환성을 유지할 수 있게 해주는 혁신적인 기능이다.2 본 서적에서는 최신 트렌드를 반영하여 IDL 4.2 표준을 기준으로 설명하되, 현장에서 여전히 널리 쓰이는 IDL 3.5 스타일과의 차이점도 함께 언급한다.

2. 어휘 규칙 (Lexical Rules): 컴파일러가 문자를 읽는 법

IDL 파일을 작성할 때 가장 먼저 마주하는 것은 어휘 규칙이다. IDL의 어휘 분석(Lexical Analysis) 규칙은 C++의 그것과 매우 유사하게 설계되어 있어 C 계열 언어 개발자들에게 친숙함을 제공한다.3 하지만 분산 환경의 특수성을 반영한 몇 가지 결정적인 차이점과 제약 사항이 존재하며, 이를 간과할 경우 원인을 알 수 없는 컴파일 오류나 통신 불능 상태에 빠질 수 있다.

2.1 문자셋 (Character Set)과 토큰

IDL 명세는 기본적으로 ISO Latin-1 (8859-1) 문자셋을 사용한다.1 IDL 파일은 일련의 토큰(Token)으로 구성되며, 토큰은 식별자, 키워드, 리터럴(상수값), 연산자, 구분자 등으로 분류된다.

  • 알파벳: a-z, A-Z
  • 숫자: 0-9
  • 특수문자: 그래픽 문자 및 공백 문자(Space, Tab, Newline)

최근 IDL 4.2 스펙 등에서는 다국어 지원을 위해 유니코드(UTF-8 등) 처리를 위한 wchar, wstring 타입 확장을 명시하고 있지만, **식별자(변수명, 모듈명, 타입명)**를 작성할 때는 여전히 영문자와 숫자, 밑줄(_)의 조합만을 사용하는 것이 안전하며 표준적이다. 한글이나 특수 문자가 포함된 식별자는 대부분의 IDL 컴파일러에서 오류를 발생시킨다.

2.2 주석 (Comments)

코드의 가독성을 높이고 메타 정보를 기록하기 위한 주석 처리는 C++ 및 Java와 완벽하게 동일하다.1 주석은 IDL 컴파일러의 전처리 단계에서 공백으로 치환되거나 무시되므로, 생성된 코드에 영향을 주지 않는다.

  • 한 줄 주석 (Line Comment): //로 시작하여 해당 라인의 끝(EOL)까지를 주석으로 처리한다.
  • 블록 주석 (Block Comment): /*로 시작하여 */로 끝나는 영역을 주석으로 처리한다. 여러 줄에 걸쳐 작성할 수 있다.
/*
* ==========================================
* 모듈명: Robotics
* 작성자: System Architect
* 설  명: 로봇 제어 시스템을 위한 공통 데이터 정의
* ==========================================
*/
module Robotics {
// 로봇 팔의 관절 각도 (단위: 라디안)
struct JointState {
long id;      /* 관절 ID */
double angle; /* 현재 각도 */
};
};

[심화] 주석은 원칙적으로 코드 생성 과정에서 사라지지만, 일부 현대적인 IDL 컴파일러(예: RTI Code Generator의 특정 옵션 사용 시)는 IDL의 주석을 생성된 C++ 헤더 파일이나 Java 파일의 Javadoc으로 옮겨주는 기능을 제공하기도 한다. 따라서 주석을 작성할 때도 명확하고 정제된 언어를 사용하는 것이 바람직하다.

2.3 식별자(Identifiers)와 대소문자 구분(Case Sensitivity)의 미묘한 관계

IDL 문법에서 개발자들이 가장 혼란스러워하고 실수하기 쉬운 부분이 바로 식별자의 대소문자 처리 규칙이다. IDL은 이기종 언어 간의 매핑을 위해 매우 독특하고 엄격한 ’이중적 잣대’를 적용한다.2

  1. 충돌 검사 시 대소문자 무시 (Case Insensitive for Collision):

IDL 컴파일러가 네임스페이스 내에서 이름 충돌(Name Collision)을 검사할 때는 대소문자를 구분하지 않는다. 즉, TargetPosition과 targetPosition, 심지어 TARGETPOSITION은 IDL 관점에서 모두 ‘동일한’ 이름으로 간주된다. 따라서 같은 스코프(Scope) 내에서 대소문자만 다른 두 개의 식별자를 동시에 정의하는 것은 불법이다.1

  • 잘못된 예:
struct Packet {
long data;
long DATA; // 컴파일 에러! 'data'와 'DATA'는 충돌함.
};

이러한 규칙이 존재하는 이유는 Pascal, Ada, SQL과 같이 대소문자를 구분하지 않는(Case Insensitive) 언어로의 매핑을 지원하기 위함이다. 만약 IDL이 대소문자 차이만으로 서로 다른 변수를 허용한다면, 대소문자를 구분하지 않는 언어로 코드를 생성할 때 심각한 이름 충돌이 발생할 것이다.9

  1. 참조 시 대소문자 보존 및 일치 (Case Preservation & Consistency):

하지만 식별자가 한 번 정의되면, 그 식별자를 참조(Reference)할 때는 반드시 정의된 것과 동일한 대소문자를 사용해야 한다.2 이는 C++, Java, Python과 같이 대소문자를 엄격하게 구분하는(Case Sensitive) 언어에서의 혼란을 방지하기 위함이다.

  • 올바른 예:

코드 스니펫

typedef long MyLong;
struct Test {
MyLong value; // OK
};
  • 잘못된 예 (일부 컴파일러에서 경고 또는 에러):

코드 스니펫

typedef long MyLong;
struct Test {
mylong value; // 에러! 정의된 'MyLong'과 대소문자가 다름.
};
  1. 언어 매핑 시의 대소문자:

생성된 코드(C++ 등)에서는 IDL에 적힌 대소문자가 그대로 유지된다. 따라서 C++ 코드에서는 MyLong과 mylong이 전혀 다른 심볼이 되므로, IDL 작성 시 일관성을 유지하는 것이 매우 중요하다.8 “정의는 유일하게, 참조는 정확하게” 라는 원칙을 고수해야 한다.

2.4 키워드(Keywords)와 이스케이프 메커니즘

IDL은 구문 분석을 위해 다수의 예약어(Keyword)를 선점하고 있다. module, struct, interface, enum, union, const 등 익숙한 단어부터 factory, native, value 등 특수한 용도에 쓰이는 단어까지 다양하다.10 이 예약어들은 원칙적으로 식별자로 사용할 수 없다. 예를 들어 변수 이름을 switch라고 짓거나 구조체 이름을 interface라고 지을 수 없다.

그러나 레거시 시스템과의 연동이나 도메인 특화 용어(Domain Specific Terms) 사용 시, 부득이하게 예약어를 식별자로 써야 할 상황이 발생한다. 예를 들어, 네트워크 장비의 상태를 나타내는 변수명을 contextin으로 짓고 싶을 수 있는데, 이는 IDL의 키워드다. 이를 해결하기 위해 IDL은 이스케이프(Escaping) 메커니즘을 제공한다.1

  • 이스케이프 규칙: 식별자 앞에 밑줄(_)을 붙이면, IDL 컴파일러는 해당 단어를 키워드 검사에서 제외하고 일반 식별자로 취급한다.
  • 매핑 규칙: 중요한 점은 언어 매핑 시(코드 생성 시) 앞의 밑줄이 제거된다는 것이다.

코드 스니펫

struct SystemContext {
boolean _context;   // IDL: '_context'로 작성하여 키워드 'context' 회피.
// 생성된 C++ 코드: bool context; (밑줄 제거됨)

long _in;           // IDL: '_in' (매개변수 방향 키워드 'in' 회피)
// 생성된 Java 코드: int in; (밑줄 제거됨)
};

이 규칙은 매우 유용하지만 남용해서는 안 된다. 이스케이프된 식별자는 전송되는 데이터(Wire Protocol) 상에서는 밑줄이 없는 형태로 취급되지만, IDL 파일 내에서는 가독성을 해칠 수 있다. 또한, C++ 등 일부 언어에서는 시스템 라이브러리 내부 변수용으로 이중 밑줄(__)이나 밑줄로 시작하는 대문자(_Identify) 등을 예약해두고 있으므로, 생성된 코드가 타겟 언어의 예약어와 충돌하지 않는지도 신경 써야 한다.

3. 전처리(Preprocessing): 대규모 모델링을 위한 도구

IDL 컴파일러는 구문 분석(Parsing)에 앞서 전처리기(Preprocessor)를 수행한다. 이는 C/C++의 전처리기와 기능적으로 거의 동일하며, 대규모 시스템에서 IDL 파일을 모듈화하고 관리하는 데 필수적인 도구다.1

3.1 파일 포함 (#include)과 헤더 가드

복잡한 로봇 시스템이나 자율주행 차량의 데이터 모델을 하나의 거대한 .idl 파일에 모두 정의하는 것은 불가능에 가깝다. 공통으로 사용되는 데이터 타입(예: 좌표계, 헤더 정보, 상태 코드)을 별도의 파일로 분리하고, 이를 #include 지시어를 통해 재사용해야 한다.1

// CommonTypes.idl
#ifndef COMMON_TYPES_IDL
#define COMMON_TYPES_IDL

module Common {
enum StatusCode { OK, WARN, ERROR };
};

#endif
// CameraSensor.idl
#include "CommonTypes.idl"

module Sensor {
struct CameraData {
Common::StatusCode status; // 포함된 파일의 타입 사용
sequence<octet> image_frame;
};
};

전처리기는 #include 문을 만나면 해당 파일의 내용을 그 위치에 그대로 복사해 넣는다. 이때 상호 참조나 중복 포함으로 인한 재정의 오류를 방지하기 위해, C++ 헤더 파일 작성 시와 마찬가지로 헤더 가드(Header Guard) (#ifndef, #define, #endif) 관용구를 사용하는 것이 IDL 작성의 표준 패턴이다.

3.2 매크로 정의 (#define)와 주의점

상수 값을 정의하거나 조건부 컴파일을 제어하기 위해 #define을 사용할 수 있다.

코드 스니펫

#define MAX_BUFFER 1024
#define USE_EXTENDED_TYPES

struct Buffer {
sequence<octet, MAX_BUFFER> data;
};

#ifdef USE_EXTENDED_TYPES
struct ExtendedInfo {... };
#endif

하지만, 단순한 상수를 정의할 때는 #define보다 IDL 문법인 const 키워드를 사용하는 것이 훨씬 바람직하다. #define은 단순 텍스트 치환이므로 타입 정보가 없어 생성된 코드에서 타입 안전성을 보장받기 어렵다. 반면 const는 명확한 타입을 가지며, 범위(Scope) 규칙을 따른다.14

3.3 프라그마 (#pragma)와 벤더 확장

#pragma 지시어는 컴파일러에게 특정 명령을 전달하기 위해 사용된다. 표준 문법으로 커버되지 않는 벤더별 확장 기능이나 코드 생성 옵션을 제어할 때 주로 등장한다. DDS에서는 역사적으로 토픽의 키(Key) 설정이나 ID 부여 등에 이 프라그마가 자주 활용되었다.3

코드 스니펫

struct UserProfile {
long user_id;
string name;
};

// (구형 방식) RTI Connext DDS 등에서 user_id를 키로 지정
#pragma keylist UserProfile user_id

최신 IDL 4.2 및 DDS-XTypes 스펙에서는 #pragma 대신 @key, @id, @optional과 같은 표준 어노테이션(Annotation) 문법을 사용하는 추세로 변화하고 있다. 하지만 여전히 많은 레거시 IDL 파일들이 #pragma를 사용하고 있으므로, 이를 해석할 수 있어야 한다.

4. 기본 데이터 타입 (Primitive Types): 데이터의 원자(Atom)

IDL의 가장 강력한 기능 중 하나는 플랫폼 독립적인 기본 데이터 타입(Primitive Types)을 제공한다는 점이다. C++의 int는 16비트일 수도, 32비트일 수도, 64비트일 수도 있다(Implementation Dependent). 하지만 IDL의 long은 32비트임이 보장된다. 이는 네트워크를 통해 데이터를 주고받을 때 데이터의 크기(Size)와 메모리 정렬(Alignment)을 예측 가능하게 만든다.2

아래 표는 IDL의 기본 데이터 타입과 그 특성, 그리고 주요 언어 매핑을 정리한 것이다.4

IDL 타입비트 크기부호 여부설명 및 용도C++ (Modern) 매핑Java 매핑Python 매핑
boolean8N/A논리값 (TRUE/FALSE).boolbooleanbool
octet8No가공되지 않은 8비트 바이너리 데이터.uint8_tbytebytes (byte string)
char8N/AISO Latin-1 문자 1개.charcharstr (len=1)
wchar가변(16/32)N/A다국어 문자. 구현에 따라 크기 다름.wchar_tcharstr (len=1)
short16Yes16비트 부호 있는 정수.int16_tshortint
unsigned short16No16비트 부호 없는 정수.uint16_tshort (주의)int
long32Yes32비트 부호 있는 정수.int32_tintint
unsigned long32No32비트 부호 없는 정수.uint32_tint (주의)int
long long64Yes64비트 대용량 정수.int64_tlongint
unsigned long long64No64비트 부호 없는 대용량 정수.uint64_tlong (주의)int
float32YesIEEE 754 단정밀도 부동소수점.floatfloatfloat
double64YesIEEE 754 배정밀도 부동소수점.doubledoublefloat
long double128 (표준)Yes확장 정밀도. 플랫폼 지원에 의존적.long doubledouble (매핑됨)float

4.1 정수형(Integer Types)과 언어 매핑의 함정

IDL의 정수형은 short(16bit), long(32bit), long long(64bit) 세 가지 크기를 기본으로 하며, 각각 unsigned 키워드를 붙여 부호 없는 형식을 만들 수 있다.2

  • 용어의 혼란 주의: C++ 표준에서 long은 “적어도 32비트“이지만, IDL의 long은 **“정확히 32비트”**다. 64비트 리눅스 환경에서 C++의 long은 64비트인 경우가 많지만, IDL의 long은 C++의 int32_t 또는 int로 매핑된다. 이 차이를 명확히 인지하지 못하면 오버플로우나 바이너리 호환성 문제가 발생한다.17
  • Java의 Unsigned 문제: Java는 byte, short, int, long이 모두 부호 있는(Signed) 정수다. 원시 타입(Primitive Type) 수준에서 Unsigned를 지원하지 않는다. 따라서 IDL의 unsigned long (0 ~ 42억)은 Java의 int (-21억 ~ 21억)로 매핑된다. 이때 21억을 넘는 값은 Java에서 음수로 표현된다. Java 개발자는 이를 올바르게 사용하기 위해 Integer.toUnsignedLong()과 같은 헬퍼 메서드를 사용하거나, 더 큰 타입(long)으로 캐스팅하여 처리해야 하는 번거로움이 있다.4 Python은 정수 크기에 제한이 없으므로(Arbitrary Precision), 이러한 문제에서 자유롭다.20

4.2 부동소수점형(Floating-Point Types)과 정밀도

floatdouble은 IEEE 754 표준을 따르므로 대부분의 하드웨어와 언어에서 호환성이 좋다. 문제는 long double이다. IDL 표준은 long double을 최소 15비트 지수와 64비트 가수를 가진 확장형으로 정의하지만(보통 128비트), 모든 컴파일러가 128비트 부동소수점을 지원하는 것은 아니다. Visual Studio(MSVC)와 같은 일부 컴파일러는 long doubledouble(64비트)과 동일하게 취급한다.13 이 경우 IDL 상에서는 long double이라도 실제 전송되는 데이터는 64비트일 수 있으며, 서로 다른 플랫폼 간 통신 시 정밀도 손실이나 CDR 디코딩 오류가 발생할 수 있으므로 사용에 신중해야 한다.

4.3 문자형(Char)과 옥텟(Octet)의 결정적 차이

초보자가 가장 많이 혼동하는 것이 charoctet이다. 둘 다 8비트 크기를 갖지만, 그 **의미론(Semantics)**은 하늘과 땅 차이다.16

  • char (Text): 문자를 의미한다. 시스템의 로케일(Locale)이나 인코딩 설정에 따라 변환이 일어날 가능성을 내포한다. 주로 텍스트 데이터를 표현할 때 사용된다.
  • octet (Binary): “가공되지 않은 바이트(Raw Byte)“를 의미한다. 이미지 파일의 픽셀 데이터, 암호화된 블록, 하드웨어 레지스터 덤프 등을 전송할 때는 반드시 octet을 사용해야 한다. octet은 어떠한 경우에도 데이터의 내용이 미들웨어에 의해 변조되거나 해석되지 않음이 보장된다(Opaque Data). C++에서는 uint8_t 또는 unsigned char로 매핑된다.

4.4 불리언(Boolean)과 와이어 프로토콜

boolean 타입은 TRUE 또는 FALSE 값만 가질 수 있다. C++에서는 0이 아닌 모든 값을 참으로 간주하지만, IDL은 명확한 논리 타입이다. RTPS(Real-Time Publish Subscribe) 와이어 프로토콜 상에서 boolean은 1바이트로 전송되며, 일반적으로 0은 FALSE, 1은 TRUE로 인코딩된다.16

5. 모듈(Module)과 스코핑(Scoping): 네임스페이스 관리 전략

수백, 수천 개의 데이터 타입이 정의되는 대규모 시스템에서 이름 충돌을 피하는 것은 매우 중요하다. IDL은 module 키워드를 통해 네임스페이스(Namespace)를 구성한다.23

5.1 모듈의 정의와 중첩

모듈은 중첩(Nested)될 수 있으며, 이를 통해 계층적인 데이터 구조를 설계할 수 있다.

module AutoDriving {
module Perception {
struct ObjectList {... };
};

module Planning {
struct Trajectory {... };
};
};

이 구조는 C++의 namespace AutoDriving { namespace Perception {... } }, Java의 package AutoDriving.Perception;으로 직관적으로 매핑된다.25

5.2 스코프 해결 연산자(::)

모듈 내부에서 다른 모듈의 타입을 참조하거나, 모듈 외부에서 특정 타입을 지칭할 때는 C++와 동일하게 더블 콜론(::) 연산자를 사용한다.26

코드 스니펫

module Control {
struct Command {
// 절대 경로 참조 (Absolute Scope)
AutoDriving::Planning::Trajectory target_path;

// 같은 모듈 내 참조는 이름만으로 가능하지만, 명확성을 위해 상대 경로 사용 가능
long timestamp;
};
};

IDL 컴파일러는 식별자를 찾을 때 현재 스코프에서 시작하여 상위 스코프로 이동하며 이름을 검색한다. 만약 여러 모듈에 같은 이름의 구조체가 있다면, ::를 사용하여 모호함을 없애야 한다.

6. 상수(Constants) 정의와 표현식

데이터 모델링 시 ’매직 넘버(Magic Number)’의 사용을 피하기 위해 상수를 정의하는 것은 좋은 습관이다. IDL은 const 키워드를 통해 기본 데이터 타입에 대한 상수를 정의할 수 있다.23

const long MAX_SENSORS = 100;
const float PI = 3.14159;
const string VENDOR_NAME = "MyCompany";

6.1 상수 표현식 (Constant Expressions)

IDL은 상수 정의 시 간단한 산술 및 비트 연산을 지원한다. 이를 통해 관련된 상수들을 유기적으로 정의할 수 있다. 지원되는 연산자는 +, -, *, /, % 등 산술 연산자와 <<, >>, &, |, ^ 등의 비트 연산자다.23

const short BASE_ID = 0x1000;
const short SENSOR_A_ID = BASE_ID + 1;
const short FLAG_ENABLED = 0x01 << 2; // 비트 시프트 연산

이때 중요한 제약 사항은, 상수 표현식의 피연산자는 반드시 리터럴(Literal)이거나 다른 상수여야 한다는 점이다. 런타임에 값이 변하는 변수나 함수 호출의 결과는 상수로 사용할 수 없다. 또한, 부동소수점 상수의 경우 정밀도 손실 없이 표현 가능한지 확인해야 한다.

7. IDL 구조체(Struct) vs 인터페이스(Interface)의 구분

DDS 입문자가 흔히 겪는 혼란 중 하나는 structinterface 키워드의 구분이다. 이 둘은 IDL 문법상 모두 존재하지만, DDS 환경에서의 용도는 명확히 구분된다.

  • Struct (구조체): DDS의 핵심인 데이터 중심(Data-Centric) 통신에서 주고받는 메시지의 본체다. 토픽(Topic) 타입을 정의할 때 사용되며, 멤버 변수(상태)만을 가진다. 우리가 작성하는 대부분의 DDS IDL은 struct 정의다.28
  • Interface (인터페이스): 객체가 제공하는 오퍼레이션(메서드)의 집합을 정의한다. 이는 CORBA나 RPC over DDS와 같은 요청-응답(Request-Reply) 패턴에서 사용된다. 일반적인 Pub/Sub 통신에서는 사용되지 않는다.29

따라서, “DDS로 센서 데이터를 보낸다“라고 할 때는 struct를 정의하는 것이 맞고, “원격 노드의 함수를 호출하여 결과를 받는다“라고 할 때(RPC over DDS 사용 시) 비로소 interface를 정의하게 된다. 일부 최신 DDS 구현체는 IDL의 interface 구문을 사용하여 RPC 서비스를 자동으로 생성해주는 기능을 제공하지만 30, 본질적인 데이터 분산 모델링의 중심은 여전히 구조체에 있다.

7.1 맺음말

지금까지 IDL의 기초 문법을 살펴보았다. IDL은 단순한 텍스트 파일이 아니라, 분산 시스템 전체를 관통하는 데이터의 청사진이다. 대소문자 규칙 하나, 데이터 타입의 비트 수 하나가 전체 시스템의 안정성과 상호 운용성을 좌우할 수 있다. 특히 현대적인 DDS 시스템은 다양한 언어와 플랫폼이 혼재된 환경에서 운용되므로, IDL이 제공하는 엄격한 타입 정의와 언어 중립적 특성을 십분 활용해야 한다.

이어지는 “3.2 기본 타입과 구조체(Struct), 시퀀스(Sequence)” 절에서는 이러한 기초 문법을 바탕으로, 실제 데이터를 담는 그릇인 구조체와 가변 길이 데이터를 처리하는 시퀀스, 그리고 메모리 효율적인 공용체(Union) 등의 복합 데이터 타입(Constructed Types)을 설계하는 방법을 구체적으로 다룰 것이다. 데이터의 뼈대를 세우는 작업이 끝났으니, 이제 그 뼈대에 살을 붙이고 혈관을 연결하는 본격적인 모델링의 세계로 진입할 차례다.

8. 참고 자료

  1. Interface Definition Language - Object Management Group (OMG), https://www.omg.org/spec/IDL/3.5/PDF
  2. Interface Definition Language - Object Management Group (OMG), https://www.omg.org/spec/IDL/4.2/PDF
  3. OMG IDL Syntax and the C++ IDL Compiler, https://docs.oracle.com/cd/E13203_01/tuxedo/tux81/CORBA_ref/idlchap.htm
  4. 20.3.4 Translations for IDL Types - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/users_manual/users_manual/Translations_for_IDL_Types.htm
  5. Fast-DDS-docs/docs/fastdds/dds_layer/topic/fastddsgen/fastddsgen.rst at master - GitHub, https://github.com/eProsima/Fast-RTPS-docs/blob/master/docs/fastdds/dds_layer/topic/fastddsgen/fastddsgen.rst
  6. OMG® IDL | Object Management Group, https://www.omg.org/corba/omg_idl.htm
  7. OMG IDL Syntax and Semantics 3.1 About This Chapter, https://ptolemy.berkeley.edu/projects/sec/studygroup/1999Fall/study-sept7-1999/chapt3.PDF
  8. Lexical Rules - Ice - ZeroC Documentation, https://doc.zeroc.com/ice/3.7/the-slice-language/lexical-rules
  9. Is IDL case un-sensitive ? - xmlBlaster, http://www.xmlblaster.org/mhonarc-xmlBlaster-devel/msg00045.html
  10. Reserved Words - NV5 Geospatial Solutions, Inc., https://www.nv5geospatialsoftware.com/docs/reswords.html
  11. Reserved Words - IRyA, UNAM, https://www.irya.unam.mx/computo/sites/manuales/IDL/Content/Creating%20IDL%20Programs/Appendices/reswords.html
  12. 20.3 Creating User Data Types with IDL - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/users_manual/users_manual/Creating_User_Data_Types_with_IDL.htm
    1. Defining a data type via IDL - 3.4.1 - eProsima Fast DDS, https://fast-dds.docs.eprosima.com/en/3.4.x/fastddsgen/dataTypes/dataTypes.html
  13. How to specify enum field values in CORBA - Stack Overflow, https://stackoverflow.com/questions/15969152/how-to-specify-enum-field-values-in-corba
  14. Interface Description Language (IDL) explanation — DDS-Demonstrators | TechPush, https://dds-demonstrators.readthedocs.io/en/latest/Teams/2.Demonstra-Tors/idl_explanation.html
  15. Primitive Data Types - Java™ Tutorials - Oracle Documentation, https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
  16. Basic Data Types - Oracle Help Center, https://docs.oracle.com/en/database/oracle/tuxedo/22/cobrg/basic-data-types.html
  17. IDL Data Types - NV5 Geospatial Software, https://www.nv5geospatialsoftware.com/docs/IDL_Data_Types.html
  18. IDL4 to Java Language Mapping - Object Management Group (OMG), https://www.omg.org/spec/IDL4-Java/1.0/Beta2/PDF
  19. Working with idl — Eclipse Cyclone DDS Python documentation, https://cyclonedds.io/docs/cyclonedds-python/0.9.1/idl.html
  20. IDL data types - IBM, https://www.ibm.com/docs/en/integration-bus/10.0.0?topic=corba-idl-data-types
  21. IDL - Interface Definition and Language Mapping - ROS2 Design, https://design.ros2.org/articles/idl_interface_definition.html
  22. Unoidl syntax description - Apache OpenOffice, https://www.openoffice.org/udk/common/man/idl.html
  23. 10 Introduction to OMG IDL, https://mhanckow.students.wmi.amu.edu.pl/corba/IDL.html
  24. Typedefs - Oracle Help Center, https://docs.oracle.com/en/database/oracle/tuxedo/22/cobrg/typedefs.html
  25. Enums - Oracle Help Center, https://docs.oracle.com/en/database/oracle/tuxedo/22/cobrg/enums.html
  26. Mapping of OMG IDL Statements to C++, https://docs.oracle.com/cd/E13161_01/tuxedo/docs10gr3/CORBA_ref/member.html
    1. Data Types — RTI Connext Getting Started documentation, https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/getting_started_guide/csharp/intro_datatypes.html
    1. IDL interfaces - 3.2.3 - eProsima Fast DDS, https://fast-dds.docs.eprosima.com/en/v3.2.3/fastddsgen/interfaces/introduction.html
  27. DDS IDL Compiler - java - Stack Overflow, https://stackoverflow.com/questions/66447744/dds-idl-compiler
  28. How to define a class and method in DDS idl file? - Stack Overflow, https://stackoverflow.com/questions/65787725/how-to-define-a-class-and-method-in-dds-idl-file