Skip to content

Latest commit

 

History

History
247 lines (174 loc) · 13.7 KB

File metadata and controls

247 lines (174 loc) · 13.7 KB

Phase 4: 웹 Fleet Gateway와 분산 통신

오늘 꼭 기억해야 할 것

  1. ROS 2 discovery 성공과 실제 IP 경로의 안정성은 같은 문제가 아니다.
  2. 로봇의 생존 여부는 수신 측이 마지막 heartbeat 수신 시각으로 판정해야 한다.
  3. 브라우저는 상태 표현과 사용자 입력을 담당하고, 최종 모터 안전은 로봇이 집행한다.
  4. REST는 요청·응답 명령에, WebSocket은 실시간 상태 스트림에 적합하다.
  5. UI의 버튼 비활성화는 안전장치가 아니다. 서버도 오프라인 해제를 거부해야 한다.
  6. 토픽이 통과해도 서비스와 액션이 통과한다고 가정하면 안 된다.
  7. 분산 시스템의 시각 동기화와 미들웨어 구현 통일은 통합 테스트 항목이다.
  8. ROS_DISTRO는 단순 표시 문자열이 아니라 브리지의 ROS GID 해석에도 영향을 준다.
  9. systemctl active와 end-to-end 기능 복구는 같은 뜻이 아니다.
  10. 테스트 입력에 runner의 실제 CPU 같은 외부 상태를 섞지 않는다.

핵심 구조

sensor/OpenCR
     |
     v
TB1 ROS nodes --> RobotStatus --> robot Zenoh bridge
                                      |
                                      | TCP
                                      v
control Zenoh bridge --> Fleet Gateway --> REST/WebSocket --> browser
                               |
                               `--> e-stop service --> TB1 watchdog

네트워크가 끊어져도 TB1 watchdog은 입력 timeout을 감지해 0 속도를 출력한다. 관제 Gateway는 안전 명령을 전달하지만 최종 안전 집행자는 아니다.

반드시 설명할 수 있어야 하는 개념

1. 왜 온라인 상태를 로봇이 보내지 않는가

로봇이 죽거나 네트워크가 끊기면 online=false 메시지 자체를 보낼 수 없다. 따라서 Gateway가 마지막 heartbeat를 받은 로컬 monotonic 시각을 저장하고, 현재 시각과의 차이가 timeout을 넘으면 오프라인으로 판정한다.

monotonic clock을 쓰는 이유는 NTP 보정이나 사용자의 시계 변경 때문에 wall clock이 앞뒤로 움직여도 경과 시간 계산이 깨지지 않게 하기 위해서다.

2. REST와 WebSocket을 왜 함께 쓰는가

REST는 한 번의 요청에 한 번의 결과가 필요한 조회와 명령에 적합하다. 비상정지처럼 성공·실패와 HTTP 상태 코드가 필요한 작업에 사용한다. WebSocket은 연결을 유지하며 서버가 상태 변화를 계속 밀어줄 수 있어 실시간 대시보드에 적합하다.

3. 왜 WSL과 로봇 사이에 Zenoh를 넣었는가

DDS는 discovery와 데이터 전달에 UDP multicast와 동적 포트를 사용한다. WSL은 Windows와 Hyper-V 네트워크 경계 안에 있어 물리 LAN과의 양방향 DDS가 환경에 따라 불안정할 수 있다. 각 호스트 내부에서는 DDS를 사용하고, 호스트 사이는 고정된 Zenoh TCP 연결로 라우팅해 방화벽 범위와 장애 지점을 단순화했다.

4. 왜 DDS를 loopback에 격리하는가

같은 두 호스트가 직접 DDS로도 통신하고 Zenoh 브리지로도 통신하면 같은 메시지가 두 경로로 전달되거나 루프가 생길 수 있다. 관제 호스트의 DDS를 loopback에 묶으면 Gateway와 로컬 브리지만 서로 발견하고, 원격 통신은 Zenoh 한 경로로 제한된다.

5. 왜 토픽은 되고 서비스는 실패할 수 있는가

토픽은 연속 publish/subscribe 데이터고, 서비스는 request ID와 response ID를 정확히 연결해야 하는 요청·응답 통신이다. DDS 구현 간 표준 토픽 상호 운용이 성공해도 ROS 2 서비스의 식별자나 구현별 확장 기능이 완전히 호환된다는 뜻은 아니다. 그래서 토픽, 서비스, 액션을 각각 통합 테스트해야 한다.

6. 왜 브라우저 확인창만으로 부족한가

사용자는 개발자 도구나 직접 HTTP 요청으로 UI 검사를 우회할 수 있고, 오래된 화면은 실제 온라인 상태와 다를 수 있다. 따라서 서버가 현재 registry 상태를 다시 검사해 오프라인 로봇의 비상정지 해제를 HTTP 409로 거부해야 한다.

면접 모범 답변

질문 1. 이 Phase에서 무엇을 만들었습니까?

모범 답변:

TB1의 RobotStatus를 WSL 관제 서버에서 수신해 FastAPI REST와 WebSocket으로 제공하는 Fleet Gateway를 만들었습니다. 웹에서는 배터리, 위치, LiDAR 최소 거리, 시스템 자원과 fault를 실시간으로 표시합니다. 비상정지 명령은 Gateway가 로봇의 safety watchdog 서비스에 전달하지만, 네트워크 단절 시 최종 정지는 로봇 내부 watchdog이 담당하도록 책임을 분리했습니다.

질문 2. 로봇 online/offline은 어떻게 판정했습니까?

모범 답변:

로봇이 보내는 online 플래그를 신뢰하지 않고 Gateway가 heartbeat의 마지막 로컬 수신 시각을 monotonic clock으로 기록했습니다. 기본 1Hz heartbeat에서 3초 이상 새 메시지가 없으면 offline으로 판정했습니다. 실제로 Zenoh 브리지를 중단했을 때 약 5초 후 offline이 표시되고, 복구 후 다시 online으로 전환되는 것을 검증했습니다.

질문 3. 왜 FastAPI와 WebSocket을 선택했습니까?

모범 답변:

상태 목록과 명령 결과는 REST의 명확한 HTTP 의미를 활용하고, 지속적인 상태 갱신은 WebSocket으로 서버가 push하도록 분리했습니다. 한 기술로 억지로 통합하는 것보다 요청·응답과 스트리밍의 통신 성격에 맞춘 선택입니다.

질문 4. WSL 네트워크 문제를 어떻게 해결했습니까?

모범 답변:

Hyper-V 방화벽과 mirrored networking을 확인했지만 물리 LAN에서 WSL로 들어오는 일반 UDP·TCP가 안정적으로 도달하지 않았습니다. 방화벽 범위를 계속 넓히는 대신 로봇에서 TCP 7447을 수신하고 WSL이 outbound로 연결하는 Zenoh 브리지 구조로 전환했습니다. WSL의 DDS는 loopback에 격리해 중복 경로도 차단했습니다.

질문 5. 가장 어려웠던 장애와 해결 과정은 무엇입니까?

모범 답변:

상태 토픽과 웹 화면은 정상인데 비상정지 서비스만 시간 초과됐습니다. 먼저 TB1에서 서비스를 직접 호출해 watchdog 자체는 정상임을 분리했습니다. Zenoh debug 로그에서 양쪽 endpoint 발견과 query 생성은 확인했지만 원격 reply가 5초 후 timeout 되는 것을 찾았습니다. 시계 드리프트를 먼저 제거한 뒤에도 재현됐고, 공식 권장 조합과 비교해 TB1 노드가 Fast DDS인 점을 확인했습니다. TB1을 CycloneDDS RMW로 통일하자 웹 서비스가 즉시 성공했습니다. 이 경험으로 토픽 성공을 서비스 성공으로 일반화하면 안 된다는 점을 검증했습니다.

질문 6. 웹 관제 시스템의 안전을 어떻게 설계했습니까?

모범 답변:

첫째, 속도 제한과 timeout, e-stop 상태는 네트워크와 독립적인 로봇 내부 watchdog이 집행합니다. 둘째, e-stop 해제 뒤 중립 명령이 오기 전까지 재무장하지 않습니다. 셋째, 브라우저 확인창뿐 아니라 Gateway도 offline 상태의 해제를 HTTP 409로 거부합니다. 넷째, 명령은 응답 timeout을 두고 성공한 경우만 UI에 성공으로 표시합니다.

질문 7. 현재 보안 한계는 무엇입니까?

모범 답변:

현재는 신뢰된 실습 LAN을 전제로 해 인증과 암호화가 없습니다. 외부 공개 전에는 TLS, 사용자 인증, 역할 기반 권한, CSRF 방어, rate limit, 비상정지 명령 감사 로그가 필요합니다. 특히 해제 권한은 적용 권한보다 더 엄격하게 분리하는 것이 좋습니다.

질문 8. systemd가 active이면 장애 복구가 끝났다고 볼 수 있습니까?

모범 답변:

아닙니다. 프로세스가 다시 실행돼도 ROS 2 discovery와 Zenoh endpoint 재등록이 끝나기 전에는 관제 기능이 오프라인일 수 있습니다. 따라서 새 PID, API의 online=true, 안전 출력까지 함께 확인합니다. 실차 시험에서는 Agent 종료 뒤 약 3.7초에 오프라인이 감지됐고 약 11.4초에 다시 온라인으로 복귀했습니다.

질문 9. 브라우저 탭을 닫으면 실행 중인 로봇도 정지합니까?

모범 답변:

아닙니다. 이 구조에서 안전 lease의 소유자는 브라우저가 아니라 Fleet Gateway입니다. 탭을 닫아도 Gateway와 Zenoh가 살아 있으면 lease와 활성 목표는 계속됩니다. 작업자가 감독을 끝낼 때는 탭 종료를 정지 동작으로 간주하지 말고 목표 취소 또는 비상정지를 명시적으로 사용해야 합니다.

질문 10. ROBOT_OFFLINE으로 전원 차단과 네트워크 단절을 구분할 수 있습니까?

모범 답변:

구분할 수 없습니다. Gateway가 확실히 아는 사실은 3초 넘게 새 heartbeat가 없다는 것뿐입니다. 따라서 감사 로그에는 ROBOT_OFFLINE과 가능한 원인을 기록하되, 실제 원인은 TB1 systemd 로그, 전원 상태와 네트워크 상태를 함께 조사합니다. heartbeat가 돌아오면 중복 없이 ROBOT_ONLINE을 한 번 기록합니다.

30초 설명

TB1 상태를 웹에서 실시간 관제하는 FastAPI Gateway를 만들었습니다. RobotStatus는 WebSocket으로 표시하고, heartbeat가 3초 끊기면 수신 측에서 offline을 판정합니다. WSL과 로봇 사이는 Zenoh TCP 브리지로 연결했으며, 비상정지는 ROS 2 서비스로 전달합니다. 네트워크가 끊겨도 로봇 내부 watchdog이 최종 0 속도를 보장하고, 서버는 offline 상태의 e-stop 해제를 거부합니다.

1분 설명

Phase 4에서는 TB1의 RobotStatus를 관제 PC WSL에서 받아 REST와 WebSocket으로 제공하는 Fleet Gateway와 웹 대시보드를 구현했습니다. 배터리, odom, LiDAR, CPU·메모리, Wi-Fi와 fault를 한 카드에서 확인할 수 있습니다. 로봇의 online 여부는 로봇 플래그가 아니라 Gateway가 monotonic clock으로 heartbeat age를 계산해 판정합니다. WSL의 DDS 직접 통신이 불안정해 각 호스트에 Zenoh ROS 2 DDS 브리지를 두고 TCP 7447로 연결했습니다. 통합 중 토픽은 정상인데 서비스만 timeout 되는 장애가 있었고, 로그와 직접 호출로 원인을 분리한 뒤 TB1 RMW를 공식 권장 CycloneDDS로 통일해 해결했습니다. 브리지 단절 시 offline 전환, 해제 HTTP 409 차단, 복구 뒤 online 전환과 0 속도까지 실차 검증했습니다.

복습 문제와 정답

1. 로봇이 online=false를 보내게 하면 충분하지 않은 이유는 무엇인가?

정답: 로봇 전원이나 네트워크가 끊기면 그 메시지를 보낼 수 없기 때문이다. 수신자가 마지막 heartbeat 이후 경과 시간을 계산해야 한다.

2. heartbeat 경과 시간에 wall clock 대신 monotonic clock을 쓰는 이유는?

정답: NTP 보정이나 사용자의 시계 변경으로 시간이 앞뒤로 이동해도 경과 시간은 항상 단조 증가해야 하기 때문이다.

3. 비상정지 해제를 offline 상태에서 막아야 하는 이유는?

정답: 명령 전달과 현재 안전 상태를 확인할 수 없는 로봇을 원격으로 재무장하면 오래된 비중립 입력이나 예측하지 못한 상태로 움직일 수 있기 때문이다.

4. 상태 토픽이 보이면 서비스도 정상이라고 말할 수 있는가?

정답: 없다. 서비스는 request/reply 식별과 timeout 경로가 추가되므로 따로 호출하고 응답까지 검증해야 한다. 액션도 같은 방식으로 별도 검증한다.

5. Zenoh 브리지 양쪽의 DDS 직접 통신을 막는 이유는?

정답: 직접 DDS와 Zenoh라는 두 경로가 동시에 생기면 중복 전달이나 루프가 발생할 수 있기 때문이다.

6. UI에서 해제 버튼을 비활성화하면 서버 검사가 필요 없는가?

정답: 필요하다. UI는 우회할 수 있고 화면 상태가 오래됐을 수 있으므로 서버가 명령 시점의 authoritative 상태를 다시 검사해야 한다.

7. ROS_DISTRO=humble을 브리지에도 명시한 이유는?

정답: 브리지가 ROS 배포판별 GID 형식을 올바르게 해석하게 하기 위해서다. 설정이 없으면 다른 배포판을 가정해 graph와 서비스가 비정상 동작할 수 있다.

8. 로컬에서는 통과하고 CI에서만 HIGH_CPU가 발생한 테스트를 어떻게 고치는가?

정답: 실제 runner 자원 사용률을 기능 테스트 입력으로 사용한 것이 원인이다. 운영 임계값을 올려 숨기지 않고, 시스템 메트릭 수집 함수를 정상 값의 테스트 대역으로 바꿔 검증 대상인 ROS 메시지 흐름만 남긴다.

스스로 확인할 체크리스트

  • 종이를 보지 않고 데이터 흐름을 그릴 수 있다.
  • heartbeat와 monotonic clock의 관계를 설명할 수 있다.
  • REST와 WebSocket의 역할 차이를 예로 설명할 수 있다.
  • 로컬 watchdog이 필요한 이유를 네트워크 단절 시나리오로 설명할 수 있다.
  • 토픽·서비스·액션을 각각 검증해야 하는 이유를 말할 수 있다.
  • RMW 혼용 장애를 증거와 해결 순서로 설명할 수 있다.
  • 현재 보안 한계와 운영 전 추가 항목을 말할 수 있다.
  • 프로세스 복구와 기능 복구의 차이를 설명할 수 있다.
  • flaky test에서 외부 상태를 제거하는 이유와 방법을 설명할 수 있다.
  • 브라우저 연결과 Gateway lease가 다른 수명주기인 이유를 설명할 수 있다.
  • heartbeat 침묵만으로 장애 원인을 확정하면 안 되는 이유를 설명할 수 있다.