1. 들어가는 글: 거리가 깡패다
통신 엔지니어에게 우주는 너무나 넓고 가혹한 곳입니다.
지구 저궤도(500km)에서는 스마트폰 수준의 전력으로도 콸콸 데이터를 쏟아낼 수 있지만, 화성(약 2억 2천만 km)에서는 신호가 $10^{16}$배(160dB)나 약해집니다.
이 엄청난 손실(Path Loss)을 극복하고, "데이터를 살려서 지구까지 배달할 수 있는지" 계산하는 것이 링크 버짓의 핵심입니다.
오늘은 X-Band(8.4GHz) 주파수를 사용하는 화성 탐사선을 가정하고, 지구와의 거리에 따라 통신이 가능한지 판단하는 시뮬레이터를 만들어 봅니다.
2. 계산 로직: dB의 마법 (더하기와 빼기)
링크 버짓 계산은 곱하기/나누기 대신, 로그 스케일인 데시벨(dB)로 변환하여 더하기/빼기로 계산합니다.
- $P_{tx}$: 송신 전력 (dBm)
- $G_{tx}, G_{rx}$: 안테나 이득 (dBi) $\rightarrow$ 클수록 좋음
- $L_{path}$: 경로 손실 (dB) $\rightarrow$ 거리가 멀수록 커짐 (나쁜 것)
- $L_{misc}$: 기타 손실 (케이블, 대기, 강우 감쇄 등)
최종적으로 수신 에너지($E_b/N_0$)가 목표치(Threshold)보다 높으면 통신 성공입니다.
3. 파이썬 코드: 링크 버짓 계산기
이 코드는 거리, 주파수, 안테나 크기, 데이터 속도를 입력받아 링크 마진(여유분)을 계산합니다.
import numpy as np
import matplotlib.pyplot as plt
# --- 1. 유틸리티 함수 (dB 변환) ---
def to_db(value):
return 10 * np.log10(value)
def from_db(db):
return 10 ** (db / 10)
# --- 2. 핵심 물리량 계산 함수 ---
def calc_antenna_gain(diameter_m, freq_hz, efficiency=0.6):
"""
안테나 이득(Gain) 계산 (dBi)
G = efficiency * (pi * D / lambda)^2
"""
c = 3e8 # 빛의 속도 (m/s)
wavelength = c / freq_hz
gain_linear = efficiency * (np.pi * diameter_m / wavelength)**2
return to_db(gain_linear)
def calc_free_space_loss(distance_km, freq_hz):
"""
자유 공간 경로 손실(FSPL) 계산 (dB)
L = (4 * pi * d / lambda)^2
"""
c = 3e8
wavelength = c / freq_hz
distance_m = distance_km * 1000
loss_linear = (4 * np.pi * distance_m / wavelength)**2
return to_db(loss_linear)
def link_budget_calculator(distance_km, data_rate_bps):
"""
링크 버짓 계산 시뮬레이션
"""
# --- 시스템 파라미터 (화성 탐사선 가정) ---
freq = 8.4e9 # 8.4 GHz (X-Band Deep Space)
tx_power_w = 100.0 # 송신 전력 100W
tx_ant_diam = 2.0 # 위성 안테나 지름 2m (High Gain Antenna)
rx_ant_diam = 34.0 # 지상국 안테나 지름 34m (NASA DSN)
system_noise_temp = 135.0 # 시스템 잡음 온도 (Kelvin)
# 목표 성능 (QPSK + Coding 적용 시 요구사항)
required_EbN0 = 10.0 # 10 dB 이상이어야 통신 가능
# 1. 송신 (Tx)
tx_power_dbm = to_db(tx_power_w * 1000) # W -> mW -> dBm
tx_gain_dbi = calc_antenna_gain(tx_ant_diam, freq)
eirp = tx_power_dbm + tx_gain_dbi # 유효 복사 전력
# 2. 채널 (Channel)
path_loss = calc_free_space_loss(distance_km, freq)
atmos_loss = 1.0 # 대기 손실 등 기타 손실 (dB)
# 3. 수신 (Rx)
rx_gain_dbi = calc_antenna_gain(rx_ant_diam, freq)
rx_power_dbm = eirp - path_loss - atmos_loss + rx_gain_dbi
# 4. 잡음 (Noise)
k = 1.38e-23 # 볼츠만 상수
noise_power_density_dbm = to_db(k * system_noise_temp * 1000) # No (dBm/Hz)
# 5. Eb/N0 계산
# Eb/N0 = C/N0 - 10*log(DataRate)
# C/N0 = RxPower - NoiseDensity
c_n0 = rx_power_dbm - noise_power_density_dbm
actual_EbN0 = c_n0 - to_db(data_rate_bps)
# 6. 마진 (Margin)
margin = actual_EbN0 - required_EbN0
return margin, actual_EbN0, path_loss
# --- 3. 시뮬레이션: 거리에 따른 마진 변화 ---
# 화성 거리: 최소 0.5 AU ~ 최대 2.5 AU (1 AU = 1.5e8 km)
distances = np.linspace(0.5, 2.7, 100) * 1.5e8
target_bps = 2e6 # 2 Mbps (고화질 사진 전송 목표)
margins = []
for d in distances:
m, _, _ = link_budget_calculator(d, target_bps)
margins.append(m)
# --- 4. 시각화 ---
plt.figure(figsize=(10, 6))
plt.plot(distances / 1.5e8, margins, linewidth=3, color='blue')
# 기준선 (0dB Margin)
plt.axhline(0, color='red', linestyle='--', label='Communication Limit (0 dB)')
plt.fill_between(distances / 1.5e8, margins, 0, where=(np.array(margins)>=0), color='green', alpha=0.1, label='Success Region')
plt.fill_between(distances / 1.5e8, margins, 0, where=(np.array(margins)<0), color='red', alpha=0.1, label='Fail Region')
plt.title(f"Mars-Earth Link Budget Analysis (Data Rate: {target_bps/1e6} Mbps)")
plt.xlabel("Distance (AU, Astronomical Unit)")
plt.ylabel("Link Margin (dB)")
plt.grid(True)
plt.legend()
plt.show()
# 대표 케이스 출력 (1.5 AU - 평균 거리)
m, eb, loss = link_budget_calculator(1.5*1.5e8, target_bps)
print(f"=== [Link Budget Report @ 1.5 AU] ===")
print(f"Path Loss : {loss:.2f} dB")
print(f"Received Eb/N0 : {eb:.2f} dB")
print(f"Link Margin : {m:.2f} dB ({'PASS' if m>0 else 'FAIL'})")
4. 결과 분석: 화성이 멀어지면 인터넷이 끊긴다
코드를 실행하면 거리에 따라 통신 마진이 어떻게 변하는지 그래프로 확인할 수 있습니다.
[텍스트 결과 예시]

[그래프 해석]

- 초록색 영역 (가까울 때): 거리가 0.5 AU ~ 1.0 AU(지구와 화성이 가까울 때)일 때는 마진이 0dB 이상입니다. 2Mbps 속도로 사진 전송이 가능합니다.
- 빨간색 영역 (멀어질 때): 거리가 1.2 AU를 넘어가자 마진이 마이너스로 떨어집니다.
- 의미: 2Mbps 속도로는 통신이 불가능합니다. 데이터가 다 깨져서 노이즈만 보입니다.
[엔지니어의 해결책]
화성이 멀어져서 마진이 마이너스가 되면 어떻게 해야 할까요?
- 전송 속도(bps)를 낮춘다: 2Mbps $\rightarrow$ 500kbps로 낮추면 $E_b$가 커져서 다시 통신이 됩니다. (사진 보내는 데 4배 오래 걸리겠지만요.)
- 안테나를 키운다: 지상국 안테나를 34m가 아니라 70m짜리(Deep Space Network)로 바꿉니다.

5. 심화: 비 님 오시지 마세요 (Rain Fade)
이 코드에서 atmos_loss = 1.0으로 단순화했지만, 실제 지구 대기는 통신의 방해꾼입니다.
특히 Ka-Band(26GHz) 같은 고주파를 쓰면, 비가 올 때 신호가 빗방울에 흡수되어 통신이 두절(Rain Fade)될 수 있습니다.
그래서 위성 통신 엔지니어는 전 세계 강우량 데이터를 분석해 "1년에 99.9% 시간 동안 통신 가능" 같은 목표를 세웁니다.

6. 마무리: 목소리까지 완성
이로써 위성은 눈(자세제어), 귀와 입(통신), 몸(구조/열), 다리(궤도)를 모두 갖췄습니다.
이제 마지막 퍼즐 조각이 남았습니다. 이 모든 장비를 움직이게 하는 '심장', 바로 전력 시스템(EPS)입니다.
다음 시간에는 심화 과정의 마지막 기술 파트인 [전력계 심화]로 넘어갑니다.
태양전지판(Solar Array) 효율 계산과, 식(Eclipse) 구간에서 배터리 용량을 산정하는 에너지 밸런스(Energy Balance)를 다뤄보겠습니다.
'우주공학 > Python' 카테고리의 다른 글
| [뉴스페이스 Python] 파이썬으로 띄우는 나만의 스타링크: 워커 델타(Walker Delta) 시각화와 관측 예측 (0) | 2026.01.29 |
|---|---|
| [Python 위성 심화] 태양을 향해 쏴라 (2): 파이썬으로 구현하는 궤도 에너지 밸런스 시뮬레이션 (0) | 2026.01.28 |
| [Python 위성 심화] 내 위성, 안 부서질까? 진동 시험 데이터(PSD) 분석과 Grms 계산 (0) | 2026.01.27 |
| [Python 위성 심화] 내 위성의 연료비 계산: 델타브이($\Delta V$) 계산기와 호만 전이 시각화 (0) | 2026.01.27 |
| [Python 위성 심화] 위성이 얼어 터지지 않으려면? 열 해석과 히터 설계 시뮬레이션 (1) | 2026.01.26 |