AEGLOSLAB ROS 2 Jazzy 대전

제3부 미들웨어: DDS·RTPS·RMW

3.1 DDS 개념 — DCPS·도메인·엔티티

3.1.1 이 장에서 배우는 것 / 선수 지식

제1·2부는 한 프로세스 안의 이야기였다. 이제 프로세스 밖으로 나간다. publish()가 rmw를 지나면 그 아래에는 DDS가 있고, DDS는 ROS 2가 만든 것이 아니라 로봇공학과 무관하게 20년 넘게 발전해 온 산업 표준이다. 항공·방산·금융·발전소에서 쓰이던 미들웨어이며, ROS 2는 그것을 채택했다.

이 사실이 실무에서 의미하는 바가 크다. ROS 2 문서에 없는 답이 DDS 명세와 벤더 문서에 있다. "왜 이런 개념이 있지"라는 의문의 상당수는 "로봇 때문이 아니라 DDS의 원래 용도 때문"이 답이다. 이 장은 그 개념 체계를 세운다.

배우는 것:

  • DDS의 정체 — 무엇을 표준화하는가, 계층 구조(DCPS·RTPS·XTypes·Security).
  • DCPS 객체 모델 — DomainParticipant부터 DataWriter까지, 그리고 ROS 2 개념과의 대응.
  • 도메인과 파티션 — 격리의 두 축.
  • 도메인 ID의 실제 상한(3.1.13) — 232가 경계이며 그 이유.
  • 인스턴스와 키 — DDS의 핵심 개념인데 ROS 2가 노출하지 않는 것. 왜 중요한가.
  • DDS QoS의 전체 목록 — 1.5에서 본 것은 부분집합이다.
  • ROS 2가 DDS를 택한 이유와 그 대가 — 다시, 이번엔 미들웨어 쪽에서.

선수 지식: 1.5(QoS), 2.1(계층), 1.4(발행 경로). RTPS 와이어 프로토콜은 다음 장 3.2.

정직: DDS 개념은 OMG의 DDS·RTPS·XTypes·Security 명세에 근거한다. 벤더마다 명세 해석과 구현 범위가 다르며, ROS 2가 노출하지 않는 기능을 벤더 API로 쓰려면 이식성을 잃는다(1.5.3.7). 아래 서술은 명세와 공개 문서 기준이며 대부분 이 환경에서 검증하지 않았다(목차 3) — 예외는 도메인 ID 상한(3.1.13)으로, 실물에서 경계값을 실행 확인했다.

3.1.2 DDS는 무엇을 표준화하는가

DDS(Data Distribution Service)는 OMG(Object Management Group)의 표준군이며, 하나의 문서가 아니라 여러 명세의 묶음이다.

DDS-DCPS 객체 모델 · API · QoS DDS-RTPS 와이어 프로토콜 DDS-XTypes 타입 시스템 · 진화 DDS-Security 인증 · 암호 · 접근제어 DDS-RPC 요청·응답 UDP · TCP · 공유메모리
명세무엇을 정하나ROS 2에서
DCPS객체 모델·API·QoS 정책rmw가 이 위에 구축된다
RTPS바이트 수준 프로토콜상호운용의 근거(3.2)
XTypes타입 표현·CDR 인코딩·타입 진화직렬화·type hash(1.3)
Security인증·암호화·접근제어SROS2의 기반(13.3)
RPC요청·응답 패턴ROS 2는 쓰지 않는다 — 자체 구현(1.7.2)

"DDS-RPC를 안 쓴다"는 점이 흥미롭다. ROS 2의 서비스는 DDS-RPC 표준이 아니라 토픽 두 개로 직접 구현됐다. 이유는 역사적·실용적이며, 결과적으로 ROS 2 서비스는 비ROS DDS 애플리케이션과 자동으로 상호운용되지 않는다.

DDS의 핵심 철학: 데이터 중심(data-centric).

축메시지 중심(전통적 MOM)데이터 중심(DDS)
관심사"메시지를 전달한다""데이터의 상태를 공유한다"
모델큐·브로커분산 공유 데이터 공간
브로커필요없음(피어 투 피어)
중복애플리케이션이 처리인스턴스·키로 미들웨어가 처리

브로커가 없다는 것이 ROS 2에 결정적이었다. ROS 1의 roscore는 단일 장애점이었고, ROS 2는 그것을 없애고 싶었다(0.2). DDS는 이미 브로커 없이 동작하는 표준이었다.

3.1.3 DCPS 객체 모델

타입·이름 연결 DomainParticipant (도메인 참가 단위) Publisher Subscriber Topic (이름 + 타입) DataWriter DataReader
DDS 객체역할ROS 2 대응
DomainParticipant도메인 참가. 디스커버리 주체노드 또는 프로세스(벤더 의존 — 2.1.4)
PublisherDataWriter들의 컨테이너·정책 묶음직접 노출 안 됨
SubscriberDataReader들의 컨테이너직접 노출 안 됨
Topic이름 + 타입의 조합토픽(단, ROS는 rt/ 접두어 — 2.1.4)
DataWriter<T>특정 타입의 발행자rclcpp::Publisher<T>
DataReader<T>특정 타입의 구독자rclcpp::Subscription<T>

중요한 관찰 셋:

  1. Publisher·Subscriber가 ROS 2에서 사라졌다. DDS에서 이들은 여러 DataWriter를 묶어 공통 정책(파티션·일관성 그룹)을 적용하는 단위인데, ROS 2는 이 계층을 감췄다. 그래서 PARTITION 정책을 ROS 2 API로 못 쓴다(3.1.5).
  2. Topic은 이름만이 아니라 이름 + 타입이다. 같은 이름에 다른 타입을 등록하면 DDS 수준에서 불일치가 된다. ROS 2에서 "같은 토픽에 다른 타입" 문제가 조용히 나타나는 이유가 여기 있으며, type hash가 도입된 배경이기도 하다(1.3.5).
  3. DomainParticipant가 디스커버리 주체다. 참가자 하나가 디스커버리 트래픽의 단위이므로, 노드마다 참가자를 만드는 구현에서는 노드 수가 곧 디스커버리 비용이 된다(3.3).

3.1.4 도메인 — 격리의 첫 번째 축

도메인은 완전히 분리된 통신 공간이다. 다른 도메인의 참가자는 서로를 보지 못한다.

export ROS_DOMAIN_ID=42

동작 원리는 단순하다 — 포트 번호가 달라진다. RTPS 포트는 도메인 ID에서 계산되며(3.2.6), 다른 도메인은 다른 포트를 쓰므로 패킷이 섞이지 않는다.

성질설명
격리 수준완전 — 브리지 없이는 통신 불가
비용없음(포트만 다름)
보안아니다 — 같은 네트워크면 도메인을 바꿔 접근 가능(13.1)
권장 범위0~101(확인 필요: OS·설정에 따라 상한이 다르다)

함정: 도메인은 보안 경계가 아니다. "도메인을 나눴으니 격리됐다"는 안전 논증이 될 수 없다. 누구든 ROS_DOMAIN_ID를 바꿔 들어올 수 있다. 실제 격리는 네트워크 분리(VLAN·방화벽)나 SROS2(13.2)로 해야 한다.

함정: 도메인 ID 상한이 있는 이유는 포트 계산식 때문이다. 도메인 ID가 커지면 계산된 포트가 65535를 넘거나 다른 서비스와 충돌할 수 있다(3.2.6). 큰 값을 임의로 쓰지 말 것. 경계는 232다 — 233부터 초기화가 실패하며, 오류 메시지가 원인을 그대로 말해 준다(85차 실측, 3.1.13).

3.1.5 파티션 — ROS 2가 감춘 두 번째 축

DDS에는 도메인보다 경량 격리 수단이 하나 더 있다. PARTITION QoS다.

DomainParticipant (도메인 5) Publisher partition = robot1 Publisher partition = robot2 DataWriter /scan DataWriter /scan

같은 도메인·같은 토픽 이름이어도 파티션 문자열이 겹치지 않으면 연결되지 않는다. 와일드카드(robot*)도 지원한다.

축도메인파티션
격리 방식포트 분리매칭 문자열
디스커버리완전 분리같이 일어남(비용 절감 없음)
런타임 변경불가가능
ROS 2 노출✅ ROS_DOMAIN_ID❌ 없음

ROS 2가 파티션을 노출하지 않는 이유: Publisher·Subscriber 계층을 감췄기 때문이다(3.1.3). 대신 ROS 2는 네임스페이스로 같은 목적을 달성한다(1.1.7의 ①) — 이름을 바꾸는 방식이라 개념적으로 더 단순하지만, 디스커버리 비용은 파티션과 마찬가지로 줄지 않는다.

견해: 다중 로봇에서 파티션이 아쉬운 경우가 있다 — 네임스페이스는 토픽 이름을 바꾸므로 도구·설정이 따라 바뀌어야 하지만, 파티션은 이름을 유지한 채 격리한다. 정말 필요하면 벤더 XML로 파티션을 설정할 수 있으나(확인 필요: RMW가 이를 존중하는지), 이식성을 잃고 ROS 2 도구가 이해하지 못하는 상태가 된다. 네임스페이스로 푸는 것이 표준적 방법이며, 디스커버리 규모 문제는 Discovery Server(3.4)나 zenoh(3.10)로 접근하는 편이 맞다.

3.1.6 인스턴스와 키 — ROS 2가 잃은 것

이것이 DDS에서 가장 중요한데 ROS 2에서 가장 안 보이는 개념이다.

DDS의 토픽은 단순한 메시지 스트림이 아니라 데이터베이스 테이블에 가깝다. 타입에 키(key) 필드를 지정하면, 같은 키를 가진 샘플들이 하나의 인스턴스로 묶인다.

Topic: RobotState  (key: robot_id)

  robot_id=1 → 인스턴스 1: [상태 이력…]  ← 이 인스턴스의 최신 상태
  robot_id=2 → 인스턴스 2: [상태 이력…]
  robot_id=3 → 인스턴스 3: [상태 이력…]

인스턴스가 주는 것:

기능설명
인스턴스별 히스토리KEEP_LAST(1)이 인스턴스마다 적용된다 — 로봇 100대의 최신 상태를 각각 보관
인스턴스 생명주기ALIVE·NOT_ALIVE_DISPOSED·NOT_ALIVE_NO_WRITERS — "이 로봇이 사라졌다"를 미들웨어가 알려준다
인스턴스별 QoS 적용deadline·liveliness가 인스턴스 단위로 감시된다
OWNERSHIP과 결합인스턴스마다 다른 발행자가 소유권을 가질 수 있다

ROS 2는 키를 노출하지 않는다. .msg에 키를 지정하는 문법이 없고, 따라서 모든 ROS 2 토픽은 단일 인스턴스로 취급된다(확인 필요: 벤더·버전에 따라 내부 처리가 다를 수 있음).

이것이 실무에 미치는 영향:

DDS 방식:  토픽 하나 /robot_states, 키 robot_id
           → 로봇 100대여도 토픽 1개, 인스턴스 100개
           → 각 로봇의 최신 상태가 KEEP_LAST(1)로 보관됨
           → 로봇이 정지하면 인스턴스 상태로 즉시 감지

ROS 2 방식: 로봇마다 토픽 /robot1/state, /robot2/state …
           → 토픽 100개, 엔티티 100쌍
           → 디스커버리 비용이 100배(3.3)
           → "로봇이 멈췄다"는 liveliness나 애플리케이션이 처리

견해: 다중 로봇·다중 개체 시스템에서 키의 부재는 실질적인 아키텍처 제약이다. ROS 2는 "개체마다 네임스페이스"로 풀도록 유도하는데, 이는 개체 수에 비례해 그래프가 커진다는 뜻이다. 개체가 수십~수백 개인 시스템(플릿·센서 어레이)에서는 이 비용이 실제로 문제가 되며, 그때 선택지는 ① 개체를 배열 필드로 묶은 메시지(원자성 대신 유연성 상실 — 1.2.9), ② 도메인 분리(1.1.7), ③ ROS 2 밖 프로토콜, ④ zenoh 같은 대안 미들웨어(3.10)다. 키를 못 쓴다는 사실을 알고 설계하는 것과 모르고 부딪히는 것은 다르다.

비ROS DDS 애플리케이션과 연동할 때도 중요하다. 상대가 키 있는 타입을 쓰면 ROS 2 쪽에서는 인스턴스 구분 없이 모든 샘플이 뒤섞여 보인다(확인 필요: 실제 동작은 벤더 의존).

3.1.7 DDS QoS 전체 목록 — 1.5는 부분집합이었다

1.5에서 다룬 여섯 정책은 DDS QoS의 일부다. 전체 목록:

정책하는 일ROS 2 노출
HISTORY보관 개수✅
RELIABILITY재전송✅
DURABILITY늦은 구독자✅
DEADLINE주기 계약✅
LIFESPAN데이터 만료✅
LIVELINESS생존 감시✅
RESOURCE_LIMITS샘플·인스턴스 상한❌ XML
OWNERSHIP / OWNERSHIP_STRENGTH다중 발행자 중 채택❌ XML
PARTITION논리 격리❌ XML
TIME_BASED_FILTER수신 측 다운샘플링❌ XML
DESTINATION_ORDER순서 기준(발행 시각 vs 수신 시각)❌
LATENCY_BUDGET배치 허용 지연❌
TRANSPORT_PRIORITY전송 우선순위(DSCP 등)❌
DURABILITY_SERVICETRANSIENT·PERSISTENT 저장 정책❌
PRESENTATION그룹 일관성·순서❌
ENTITY_FACTORY자동 활성화❌
WRITER_DATA_LIFECYCLE / READER_DATA_LIFECYCLE인스턴스 정리❌
USER_DATA / TOPIC_DATA / GROUP_DATA사용자 메타데이터❌(내부적으로 사용될 수 있음)

실무에서 아쉬운 것 넷:

① RESOURCE_LIMITS — KEEP_ALL의 실제 상한을 정하지 못한다(1.5.3.1). 메모리 폭주 방어를 벤더 기본값에 맡기게 된다.

② OWNERSHIP — 센서 이중화의 표준 관용구를 못 쓴다(1.5.3.7). 같은 토픽에 주·예비 센서를 발행하고 OWNERSHIP_STRENGTH로 자동 페일오버하는 구성이 DDS에서는 기본 기능인데, ROS 2에서는 애플리케이션이 직접 선택 로직을 만들어야 한다(14.9).

③ TIME_BASED_FILTER — 구독자가 "나는 초당 5개만 받겠다"고 선언하는 기능. 이것이 있으면 고빈도 토픽을 저빈도로 구독하는 노드가 대역을 안 쓴다. ROS 2에서는 다 받아서 버리거나, 중간에 다운샘플링 노드를 두어야 한다(7.8).

④ TRANSPORT_PRIORITY — 제어 명령을 대용량 영상보다 우선 전송하는 QoS 기반 통제. 없으므로 네트워크 계층(DSCP·트래픽 셰이핑)에서 따로 해야 한다(3.9).

견해: 이 목록은 "ROS 2가 부족하다"는 비판이 아니라 "대안이 어디 있는지 아는 지도" 로 읽는 편이 좋다. ROS 2는 이식성을 위해 공통 분모를 노출했고, 나머지는 벤더 XML로 열어 두었다(3.7·3.8). 필요하면 내려갈 수 있되, 내려가는 순간 그 설정은 벤더 전용이 된다는 트레이드오프를 의식적으로 선택하면 된다.

3.1.8 리스너·조건·wait set — 두 가지 수신 방식

DDS는 데이터 도착을 알리는 두 가지 방식을 제공한다. 2.2에서 본 executor 구조의 근원이 여기 있다.

방식동작특징
리스너(Listener)미들웨어 스레드가 콜백을 직접 호출즉시성 높음. 미들웨어 스레드에서 실행되므로 오래 걸리면 안 됨
조건 + WaitSet조건을 등록하고 애플리케이션 스레드가 대기실행 문맥을 애플리케이션이 통제

ROS 2의 기본 executor는 후자(WaitSet)를 쓴다(2.2.4). 그래서 콜백이 executor 스레드에서 실행되고, 그 결과가 1.7의 데드락이며 2.3의 executor 선택 문제다.

EventsExecutor는 전자(리스너)에 가깝다(2.3.6) — 미들웨어 리스너로 이벤트를 받아 큐에 넣는다. 즉 ROS 2 executor 논쟁은 DDS의 두 수신 방식 중 무엇을 쓸 것인가의 문제이기도 하다.

함정: 벤더 XML로 리스너 스레드 설정을 조정할 때, 그 스레드에서 사용자 콜백이 실행되는 것이 아님을 기억해야 한다. ROS 2 사용자 콜백은 executor 스레드에서 실행된다. 두 스레드 풀을 혼동하면 튜닝 방향이 어긋난다.

3.1.9 ROS 2가 DDS를 택한 이유와 그 대가

0.2에서 설계 결정으로 다뤘던 것을 미들웨어 관점에서 다시 본다.

택한 이유:

이유설명
브로커 없음roscore 단일 장애점 제거
성숙한 표준20년 이상, 안전 중요 분야 실적
QoS무선·실시간 상황에 맞출 수 있는 정책(1.5)
보안 표준DDS-Security가 이미 존재(13.3)
다중 벤더상용·오픈소스 선택지, 벤더 종속 회피
실시간 지향애초에 그 용도로 설계됨

대가:

대가설명관련 장
디스커버리 비용브로커가 없으니 모두가 모두를 찾아야 한다3.3
복잡도QoS 조합·XML 설정·벤더 차이1.5·3.7
네트워크 민감성멀티캐스트·MTU·방화벽에 취약3.9
최소 공통분모벤더 고급 기능을 표준 API로 못 씀3.1.7
디버깅 난이도문제가 ROS 밖에 있다2.1.8
개념 부담키·인스턴스 등 안 쓰는 개념까지3.1.6
WAN·무선 부적합LAN 전제 설계3.9·3.10

마지막 항목이 근래 가장 중요한 대가로 부각됐다. DDS는 신뢰할 수 있는 LAN을 전제로 설계됐다. 무선·이동체·클라우드 연결·지연 큰 링크에서는 디스커버리와 신뢰성 메커니즘이 잘 맞지 않는다. rmw_zenoh가 Jazzy에서 대안으로 제공되는 배경이 이것이다(3.10).

견해: DDS 채택은 옳은 결정이었고, 동시에 대가가 분명한 결정이었다. 두 진술은 모순이 아니다. 로봇이 공장 LAN 안에 있던 시절의 요구에는 잘 맞았고, 필드·플릿·클라우드로 나가면서 한계가 드러났다. ROS 2 생태계가 Discovery Server·zenoh 같은 대안을 만들어 온 것은 실패가 아니라 rmw 추상이 의도대로 작동한 증거다 — 미들웨어를 교체할 수 있게 설계했기에 교체가 가능하다(3.5).

3.1.10 DDS를 직접 관찰하기

ROS 2 도구로는 안 보이는 것을 벤더 도구로 볼 수 있다.

# Fast DDS
fastdds discovery --help        # Discovery Server (3.4)
fastdds shm clean               # 공유메모리 세그먼트 정리 (2.7)
# fastdds · fast-discovery-server · ros-discovery 셋 다 설치된다 (88차 실행 확인 — 3.4)

# Cyclone DDS
# CYCLONEDDS_URI에 Tracing 설정을 넣어 로그로 관찰 (3.8)

가장 범용적인 도구는 Wireshark다. RTPS 디섹터가 참가자·엔드포인트·QoS를 해석해 보여준다(3.2.8).

sudo tcpdump -i any -w rtps.pcap 'udp portrange 7400-7500'
# Wireshark에서 열고 필터: rtps

ROS 2 CLI로 보이는 것과의 대조가 유용하다:

질문ROS 2 도구DDS 수준 확인
노드가 보이나ros2 node list참가자 SPDP 패킷(3.3)
QoS가 맞나ros2 topic info -vSEDP의 QoS 정보
데이터가 흐르나ros2 topic hzRTPS DATA 서브메시지
재전송이 일어나나불가HEARTBEAT·ACKNACK(3.2)
디스커버리 부하불가패킷 캡처

아래 두 줄이 ROS 2 도구로는 답할 수 없다는 점이 중요하다. "왜 이렇게 느리지"의 답이 재전송 폭주나 디스커버리 트래픽일 때, ROS 2 CLI는 아무것도 알려주지 않는다. 그때 내려가야 할 곳이 이 장 이후의 내용이다.

3.1.13 도메인 ID 상한을 실제로 찾았다 — 실측

3.1.4는 "상한이 있는 이유는 포트 계산식 때문"이라고 원인을 적었지만 값을 적지 않았다. 0부터 늘려 가며 노드를 실행해 경계를 찾았다(실행 확인, Jazzy · rmw_fastrtps_cpp).

ROS_DOMAIN_ID결과
0 · 101 · 166 · 200 · 232정상 기동
233 · 255 · 256실패

실패할 때의 메시지가 원인을 직접 말한다.

Calculated port number is too high.
Probably the domainId is over 232 or portBase is too high.

책의 인과 설명이 정확히 확인됐다. 도메인 ID는 포트로 환산되며(3.2.6), 232를 넘으면 계산된 포트가 16비트를 벗어난다.

ROS_DOMAIN_ID를 무작위로 정하는 스크립트에 주의하라. "0~255 중 하나"로 추출하는 코드가 흔한데 233~255가 나오면 노드가 전혀 기동되지 않는다. 0~232, 실무적으로는 0~101을 권한다 — 101을 넘으면 일부 시스템에서 사용자 포트 범위와 겹칠 수 있다(3.2.6)(확인 필요).

이 값은 rmw_fastrtps_cpp 기준이다. 포트 계산식은 RTPS 표준에 있지만 portBase·오프셋은 벤더가 조정할 수 있으므로, 다른 rmw에서 경계가 같다고 단정하지 않는다(확인 필요).

3.1.11 함정 카탈로그

#함정증상대처
1도메인을 보안 경계로 오해잘못된 안전 논증네트워크 분리·SROS2(13.1)
2큰 도메인 ID 임의 사용포트 충돌·동작 불가권장 범위 준수(3.2.6)
3키·인스턴스를 기대ROS 2에 없음설계 단계에서 인지(3.1.6)
4KEEP_ALL의 상한을 무제한으로 이해메모리 폭주벤더 RESOURCE_LIMITS
5OWNERSHIP으로 이중화 설계API 없음앱 레벨 또는 XML
6저빈도 구독을 QoS로 기대TIME_BASED_FILTER 없음다운샘플링 노드(7.8)
7DDS-RPC 상호운용 기대ROS 2 서비스는 별개 구현토픽 기반임을 인지(1.7.2)
8리스너 스레드와 executor 스레드 혼동튜닝 방향 오류두 풀을 구분(3.1.8)
9ROS 2 CLI로 재전송·디스커버리 진단 시도정보 없음패킷 캡처(3.2)
10벤더 XML 설정 후 이식성 가정벤더 교체 시 무효대가 인지(3.6)

3.1.12 체크포인트

  • DDS를 구성하는 명세 다섯 가지와 각각이 ROS 2의 어느 부분에 대응하는지 말할 수 있는가. ROS 2가 쓰지 않는 것은?
  • "데이터 중심"이 "메시지 중심"과 어떻게 다른가. 브로커 부재가 ROS 2에 왜 결정적이었나.
  • DCPS 객체 여섯 개와 ROS 2 대응을 말할 수 있는가. ROS 2가 감춘 계층은 무엇이며 그 결과 못 쓰게 된 정책은?
  • Topic이 "이름 + 타입"이라는 사실이 type hash 도입과 어떻게 연결되는가.
  • 도메인이 격리를 만드는 원리는 무엇인가. 도메인이 보안 경계가 아닌 이유는?
  • 파티션과 도메인의 차이 네 가지를 말할 수 있는가. ROS 2는 같은 목적을 무엇으로 달성하는가.
  • DDS의 키·인스턴스가 제공하는 기능 네 가지는 무엇인가. ROS 2에서 이것이 없어 로봇 100대 시스템이 어떻게 달라지는가.
  • ROS 2가 노출하지 않는 DDS QoS 중 실무에서 아쉬운 넷과 각각의 우회 방법을 말할 수 있는가.
  • DDS의 두 가지 수신 방식과, 그것이 ROS 2 executor 설계와 어떻게 연결되는지 설명할 수 있는가.
  • ROS 2가 DDS를 택한 이유 여섯 가지와 대가 일곱 가지를 들 수 있는가. 근래 가장 부각된 대가는 무엇이며 그에 대한 생태계의 답은?
  • ROS 2 CLI로는 답할 수 없는 진단 질문 두 가지는 무엇인가.
  • ROS_DOMAIN_ID를 0~255에서 무작위로 선택하는 스크립트에 어떤 문제가 있는가(3.1.13).

다음 장 3.2는 이 개념들이 실제 바이트가 되는 층 — RTPS 와이어 프로토콜로 내려간다. GUID·서브메시지·신뢰성 상태기계, 그리고 방화벽 설정에 필요한 포트 계산식.