← DEVLOG
천문2025.10.125 min read

Mars Rover — 화성의 눈으로 보는 진짜 사진

NASA 화성 로버가 실제로 촬영한 사진을 브라우저에서 탐색하는 갤러리 — RSS 피드 파싱, 세션 캐시, 카메라 필터

nasa-apirss-feedsession-cachegallerylightbox

시작 — 화성의 눈

Curiosity와 Perseverance는 매일 수백 장의 사진을 지구로 전송합니다. NASA는 이 사진들을 RSS 피드로 공개하고 있습니다.

이 페이지는 그 피드를 파싱해서, 원하는 Sol(화성일)과 카메라를 선택하면 로버가 실제로 촬영한 사진을 바로 볼 수 있게 합니다. 합성 이미지가 아닌, 진짜 화성의 표면입니다.


NASA RSS Feed API

NASA의 mars.nasa.gov는 JSON 기반 RSS 피드를 제공합니다. 로버명, Sol 번호, 페이지 수를 쿼리하면 해당 조건의 이미지 목록이 반환됩니다.

// URL 빌드 — 미션 코드로 로버를 구분
const MISSION_MAP: Record<RoverName, string> = {
  curiosity: 'msl',
  perseverance: 'mars2020',
};

function buildUrl(rover: RoverName, sol: number): string {
  const mission = MISSION_MAP[rover];
  return `${RSS_BASE}?feed=raw_images&category=${mission}&feedtype=json&num=100&page=0&sol=${sol}`;
}

개발 환경에서는 Next.js rewrite 프록시(/api/mars-rss)를 경유하고, 프로덕션에서는 NASA 서버에 직접 요청합니다. CORS 문제를 우회하기 위한 구조입니다.


데이터 정규화

NASA 피드의 이미지 객체는 camera.instrument, image_files.small/medium/large/full_res 등 중첩 구조입니다. UI에서 쓰기 편한 flat 구조로 변환합니다.

function mapPhoto(img: MarsRssImage, idx: number): MarsPhoto {
  return {
    id: img.imageid ?? `${img.sol}_${idx}`,
    sol: img.sol,
    cameraName: img.camera.instrument,
    cameraFullName: CAMERA_NAMES[img.camera.instrument] ?? img.camera.instrument,
    imgSrc: img.image_files.medium || img.image_files.small,
    fullResSrc: img.image_files.full_res || img.image_files.large,
    earthDate: img.date_taken_utc?.split('T')[0] ?? '',
    credit: img.credit,
  };
}

카메라 코드(FHAZ_RIGHT_A, MCZ_LEFT 등)는 사람이 읽을 수 있는 이름(Front Hazard Cam Right, Mastcam-Z Left)으로 매핑합니다. Curiosity와 Perseverance는 카메라 명칭 체계가 다르므로 두 세트를 모두 관리합니다.


세션 캐시

같은 Sol을 반복 조회할 때 매번 네트워크 요청을 보내지 않도록, sessionStorage에 결과를 캐싱합니다.

const CACHE_PREFIX = 'mars_cache_';

function cacheKey(rover: RoverName, sol: number, camera?: string): string {
  return camera ? `${rover}_${sol}_${camera}` : `${rover}_${sol}`;
}

sessionStorage는 탭을 닫으면 사라지므로 영속적 저장 부담이 없습니다. SSR 환경에서는 typeof sessionStorage === 'undefined' 가드를 걸어 서버 사이드 에러를 방지합니다.


카메라 필터

하나의 Sol에는 여러 카메라의 사진이 섞여 있습니다. uniqueCameras() 함수로 해당 Sol에 존재하는 카메라 목록을 추출하고, 칩 UI로 필터링할 수 있게 합니다.

사용자가 특정 카메라를 선택하면, 전체 목록에서 해당 카메라의 사진만 필터링해서 보여줍니다. 카메라별 시점 차이를 비교할 수 있어, 같은 위치의 다른 렌즈 사진을 나란히 보는 경험을 제공합니다.


라이트박스

사진 카드를 클릭하면 full-res 이미지를 오버레이로 표시합니다. backdrop-filter: blur(8px)로 배경을 흐리게 처리하고, 하단에 카메라명과 촬영 날짜를 표시합니다.

원본 이미지를 새 탭에서 열 수 있는 링크도 제공합니다. NASA 이미지는 퍼블릭 도메인이므로 자유롭게 사용할 수 있습니다.


마치며

화성은 이제 상상의 대상이 아닙니다. 매일 새로운 사진이 지구에 도착합니다. 이 페이지는 그 사진들을 가장 빠르게 접할 수 있는 창구를 목표로 했습니다.

Sol 번호를 바꿔가며 화성의 계절이 변하는 모습을 보는 것, 다른 카메라로 같은 장소를 보는 것 — 작은 조작만으로도 화성 탐사의 일부가 됩니다.

이 포스트와 연결된 콘텐츠

직접 체험하기