Google이 Maps Platform을 몇 년간 계속 바꿔왔는데, 2026년 5월의 deprecated 물결이 지금까지 중 가장 영향이 크네요. Maps JavaScript API에서 네 가지 널리 쓰이는 기능이 제거됩니다: Heatmap Layer, Drawing Library, DirectionsService, DistanceMatrixService. 이 중 하나라도 사용 중이라면, 코드가 멈추기 전에 마이그레이션할 시간이 몇 주밖에 없습니다.
이건 오래된 엔드포인트가 몇 년간 남아있는 부드러운 deprecated가 아닙니다. Google이 하드한 제거 날짜를 설정했고, 개발자 콘솔에는 이미 경고가 표시되고 있습니다. 이 가이드는 뭐가 바뀌는지, Google이 왜 이렇게 하는지, 그리고 작동하는 코드 예시와 함께 각 서비스를 어떻게 마이그레이션하는지 정확하게 다룹니다. 드롭인 대체가 필요하다면 MapAtlas API가 각 deprecated Google 서비스에 어떻게 대응하는지도 보여드릴게요.
뭐가 언제 deprecated되나
영향받는 서비스의 전체 타임라인:
| 서비스 | Deprecated | 제거 날짜 | 대체 (Google) |
|---|---|---|---|
| Heatmap Layer (Maps JS API) | 2025년 8월 | 2026년 5월 | Maps Datasets API + deck.gl |
| Drawing Library (Maps JS API) | 2025년 5월 | 2026년 5월 | Extended Component Library |
| DirectionsService (Maps JS API) | 2026년 2월 25일 | 2026년 5월 | Routes API (REST) |
| DistanceMatrixService (Maps JS API) | 2026년 2월 25일 | 2026년 5월 | Routes API (REST) |
중요한 점: Google이 라우팅과 거리 계산을 완전히 없애는 게 아닙니다. 개발자들이 10년 넘게 써온 클라이언트 사이드 JavaScript 클래스를 제거하고, 서버 사이드 REST 엔드포인트인 새로운 Routes API로 강제 마이그레이션하는 겁니다. 단순한 버전 업이 아니에요. 라우팅 로직을 브라우저에서 백엔드로 이동하는 아키텍처 변경입니다.
뭐가 깨지나
코드베이스에 다음 중 하나라도 있으면 제거 날짜 이후에 실패합니다:
// All of these will stop working in May 2026
const directionsService = new google.maps.DirectionsService();
const distanceMatrixService = new google.maps.DistanceMatrixService();
const heatmap = new google.maps.visualization.HeatmapLayer({ data: points });
const drawingManager = new google.maps.drawing.DrawingManager();
제거 후에는 이 생성자들이 에러를 던집니다. 폴백 동작도 없고 graceful degradation도 없습니다. 지도는 로드되지만, 이 클래스에 의존하는 기능은 완전히 망가집니다.
Google이 이 변경을 강제하는 이유
Google의 공식 이유는 성능과 현대화입니다. DirectionsService와 DistanceMatrixService의 대체인 Routes API는 레거시 JavaScript 클래스가 수용할 수 없는 에코 프렌들리 라우팅, 이륜차 라우팅, 통행료 비용 추정 같은 새로운 기능을 지원합니다.
실제 이유는 가격 통제입니다. 라우팅을 서버 사이드 REST API로 옮김으로써 Google은 더 세밀한 청구와 사용량 추적을 얻습니다. JavaScript DirectionsService는 Google이 정확하게 측정하기 어려운 클라이언트 사이드 배치 처리 패턴을 허용했어요. Routes API는 모든 요청이 측정된 엔드포인트를 통과하도록 보장합니다.
Heatmap Layer와 Drawing Library의 경우, Google은 개발자들을 Extended Component Library와 deck.gl 같은 서드파티 시각화 도구로 밀어붙이고 있습니다. 이건 더 큰 패턴의 일부입니다: Google은 핵심 지도 타일 렌더링을 인하우스로 유지하고 나머지는 에코시스템에 외주줍니다.
개발자에게 실질적인 영향: 더 많은 백엔드 인프라, 관리해야 할 API 키 증가, 그리고 대부분의 경우 새 가격 티어에서 요청당 더 높은 비용입니다.
마이그레이션 체크리스트
마이그레이션 코드를 작성하기 전에 이 체크리스트를 따라가세요:
1. 코드베이스 감사
deprecated 클래스에 대한 참조를 코드베이스에서 검색합니다:
# Find all files using deprecated Google Maps services
grep -rn "DirectionsService\|DistanceMatrixService\|HeatmapLayer\|visualization.HeatmapLayer\|drawing.DrawingManager\|DrawingManager" \
--include="*.js" --include="*.ts" --include="*.tsx" --include="*.jsx" src/
이 서비스를 사용하는 모든 파일과 컴포넌트를 문서화하세요. 호출이 클라이언트 사이드(브라우저)에서 발생하는지 서버 렌더링 컨텍스트(예: Next.js API 라우트)에서 발생하는지 기록하세요.
2. 사용 패턴 파악
각 사용에 대해 문서화하세요:
- 사용된 이동 모드 (driving, walking, cycling, transit)
- Waypoint 지원 (단순 A에서 B, 또는 멀티스톱 라우트)
- 소비되는 응답 필드 (거리, 시간, polyline, 스텝, 요금)
- 볼륨 (비용 추정을 위한 일/월 요청 수)
- 레이턴시 요구사항 (실시간 사용자 대면, 또는 배치 처리)
3. 마이그레이션 대상 선택
두 가지 옵션이 있습니다:
옵션 A: Google에 남기. deprecated JavaScript 클래스에서 새 Google Routes API(REST)로 마이그레이션합니다. 백엔드 변경, 새 API 키 권한, 청구 업데이트가 필요합니다.
옵션 B: 프로바이더 전환. 서드파티 라우팅 API로 마이그레이션합니다. 어차피 통합 코드를 다시 작성하는 거라 대안을 평가할 좋은 시기입니다.
4. 병렬 환경 설정
절대 인플레이스로 마이그레이션하지 마세요. 전환하기 전에 최소 2주간 오래된 구현과 새 구현을 나란히 실행하면서 정확도와 레이턴시를 비교하세요.
5. 에러 핸들링 업데이트
deprecated 서비스는 콜백 함수를 통해 에러를 반환했습니다. REST API 대체는 HTTP 상태 코드를 반환합니다. 에러 핸들링 로직을 그에 맞게 변경해야 합니다.
API별 교체 가이드
DirectionsService에서 MapAtlas Directions API로
이전 (Google, deprecated):
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: { lat: 52.52, lng: 13.405 },
destination: { lat: 48.8566, lng: 2.3522 },
travelMode: google.maps.TravelMode.DRIVING,
waypoints: [
{ location: { lat: 50.9375, lng: 6.9603 }, stopover: true }
],
},
(result, status) => {
if (status === "OK") {
const route = result.routes[0];
console.log("Distance:", route.legs[0].distance.text);
console.log("Duration:", route.legs[0].duration.text);
}
}
);
이후 (MapAtlas Directions API):
const response = await fetch(
"https://api.mapatlas.com/v1/directions?" +
new URLSearchParams({
origin: "52.52,13.405",
destination: "48.8566,2.3522",
waypoints: "50.9375,6.9603",
mode: "driving",
key: process.env.MAPATLAS_API_KEY!,
})
);
const data = await response.json();
if (data.status === "OK") {
const leg = data.routes[0].legs[0];
console.log("Distance:", leg.distance.text);
console.log("Duration:", leg.duration.text);
// Polyline for map rendering
const polyline = data.routes[0].overview_polyline;
}
주요 차이점:
- JavaScript 클래스 대신 REST 엔드포인트. 호출이 브라우저가 아닌 백엔드에서 이루어집니다.
- 더 단순한 인증. 쿼리 스트링이나 헤더에 API 키 하나.
- 동일한 응답 구조. Routes, legs, distance, duration, polyline이 모두 있습니다.
DistanceMatrixService에서 MapAtlas Matrix API로
이전 (Google, deprecated):
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [
{ lat: 52.52, lng: 13.405 },
{ lat: 48.1351, lng: 11.582 },
],
destinations: [
{ lat: 48.8566, lng: 2.3522 },
{ lat: 51.5074, lng: -0.1278 },
],
travelMode: google.maps.TravelMode.DRIVING,
},
(response, status) => {
if (status === "OK") {
response.rows.forEach((row, i) => {
row.elements.forEach((element, j) => {
console.log(`Origin ${i} -> Dest ${j}:`,
element.distance.text, element.duration.text);
});
});
}
}
);
이후 (MapAtlas Matrix API):
const response = await fetch("https://api.mapatlas.com/v1/matrix", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.MAPATLAS_API_KEY}`,
},
body: JSON.stringify({
origins: [
{ lat: 52.52, lng: 13.405 },
{ lat: 48.1351, lng: 11.582 },
],
destinations: [
{ lat: 48.8566, lng: 2.3522 },
{ lat: 51.5074, lng: -0.1278 },
],
mode: "driving",
}),
});
const data = await response.json();
data.rows.forEach((row: any, i: number) => {
row.elements.forEach((element: any, j: number) => {
console.log(`Origin ${i} -> Dest ${j}:`,
element.distance.text, element.duration.text);
});
});
응답 모양은 거의 동일합니다. 주요 변경은 콜백 기반 브라우저 API에서 Promise 기반 서버 API로 이동하는 겁니다.
Heatmap Layer 교체
히트맵 시각화의 마이그레이션 경로는 요구사항에 따라 다릅니다:
옵션 1: MapLibre GL JS와 히트맵 레이어 (오픈소스)
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: "https://api.mapatlas.com/v1/styles/streets?key=YOUR_KEY",
center: [13.405, 52.52],
zoom: 10,
});
map.on("load", () => {
map.addSource("heat-data", {
type: "geojson",
data: {
type: "FeatureCollection",
features: heatmapPoints.map((point) => ({
type: "Feature",
geometry: { type: "Point", coordinates: [point.lng, point.lat] },
properties: { weight: point.weight },
})),
},
});
map.addLayer({
id: "heatmap-layer",
type: "heatmap",
source: "heat-data",
paint: {
"heatmap-weight": ["get", "weight"],
"heatmap-intensity": 1,
"heatmap-radius": 20,
"heatmap-opacity": 0.7,
},
});
});
히트맵 렌더링을 완전히 제어할 수 있고 Google의 타일 서버에 의존하지 않습니다.
옵션 2: deck.gl HeatmapLayer (Google 자체 권장)
import { Deck } from "@deck.gl/core";
import { HeatmapLayer } from "@deck.gl/aggregation-layers";
const heatmapLayer = new HeatmapLayer({
data: heatmapPoints,
getPosition: (d) => [d.lng, d.lat],
getWeight: (d) => d.weight,
radiusPixels: 30,
});
둘 다 됩니다. MapLibre GL JS는 MapAtlas 타일 스타일과 깔끔하게 통합되고, deck.gl은 어떤 베이스 맵에도 오버레이할 수 있습니다.
비용 비교: Google Routes API vs. MapAtlas
Google의 Routes API로 마이그레이션하는 건 코드 변경만이 아닙니다. 새 가격도 따라옵니다:
| 서비스 | Google (레거시, 1,000건당) | Google Routes API (1,000건당) | MapAtlas (1,000건당) |
|---|---|---|---|
| Directions (기본) | $5.00 | $5.00 | $1.50 |
| Directions (고급, waypoints/교통) | $10.00 | $10.00 | $2.50 |
| Distance Matrix (요소당) | $5.00 | $5.00 | $1.00 |
| Distance Matrix (고급) | $10.00 | $10.00 | $2.00 |
| Geocoding | $5.00 | $5.00 | $1.50 |
월 10만 건의 라우팅 요청 기준:
- Google Routes API: 약 $500-$1,000 (사용하는 기능에 따라)
- MapAtlas Directions API: 약 $150-$250
라우팅에 지오코딩과 거리 계산을 결합하는 애플리케이션에서는 절약이 빠르게 쌓입니다. 월 50만 개의 매트릭스 요소를 처리하는 물류 플랫폼이라면 Google에서 약 $2,500, MapAtlas에서 $500를 낼 겁니다.
전체 가격 세부정보는 MapAtlas 가격 페이지에서 확인하세요.
코드 마이그레이션 예시: 완전한 전후 비교
지도에 운전 방향을 표시하는 React 컴포넌트의 완전한 마이그레이션 예시입니다.
이전: React에서 Google Maps DirectionsService
import { useEffect, useRef } from "react";
function DirectionsMap({ origin, destination }: {
origin: google.maps.LatLngLiteral;
destination: google.maps.LatLngLiteral;
}) {
const mapRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const map = new google.maps.Map(mapRef.current!, {
center: origin,
zoom: 7,
});
const directionsRenderer = new google.maps.DirectionsRenderer();
directionsRenderer.setMap(map);
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin,
destination,
travelMode: google.maps.TravelMode.DRIVING,
},
(result, status) => {
if (status === "OK" && result) {
directionsRenderer.setDirections(result);
}
}
);
}, [origin, destination]);
return <div ref={mapRef} style={{ width: "100%", height: "400px" }} />;
}
이후: MapLibre GL JS와 MapAtlas Directions API
import { useEffect, useRef } from "react";
import maplibregl from "maplibre-gl";
function DirectionsMap({ origin, destination }: {
origin: { lat: number; lng: number };
destination: { lat: number; lng: number };
}) {
const mapRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const map = new maplibregl.Map({
container: mapRef.current!,
style: "https://api.mapatlas.com/v1/styles/streets?key=YOUR_KEY",
center: [origin.lng, origin.lat],
zoom: 7,
});
map.on("load", async () => {
// Fetch directions from your backend (or directly if CORS allows)
const res = await fetch(
`/api/directions?` +
new URLSearchParams({
origin: `${origin.lat},${origin.lng}`,
destination: `${destination.lat},${destination.lng}`,
mode: "driving",
})
);
const data = await res.json();
if (data.routes?.[0]) {
const coordinates = data.routes[0].geometry.coordinates;
map.addSource("route", {
type: "geojson",
data: {
type: "Feature",
geometry: { type: "LineString", coordinates },
properties: {},
},
});
map.addLayer({
id: "route-line",
type: "line",
source: "route",
paint: {
"line-color": "#4A90D9",
"line-width": 5,
},
});
// Fit map to route bounds
const bounds = coordinates.reduce(
(b: maplibregl.LngLatBounds, coord: [number, number]) =>
b.extend(coord),
new maplibregl.LngLatBounds(coordinates[0], coordinates[0])
);
map.fitBounds(bounds, { padding: 50 });
}
});
return () => map.remove();
}, [origin, destination]);
return <div ref={mapRef} style={{ width: "100%", height: "400px" }} />;
}
백엔드 API 라우트 (Next.js)
// app/api/directions/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const origin = searchParams.get("origin");
const destination = searchParams.get("destination");
const mode = searchParams.get("mode") || "driving";
const response = await fetch(
`https://api.mapatlas.com/v1/directions?` +
new URLSearchParams({
origin: origin!,
destination: destination!,
mode,
key: process.env.MAPATLAS_API_KEY!,
})
);
const data = await response.json();
return NextResponse.json(data);
}
이 패턴은 API 키를 서버에 보관하고 라우트 지오메트리만 클라이언트에 노출합니다.
마감일 전에 마이그레이션 테스트하는 방법
1단계: 두 API를 병렬로 실행하기
전환 전 2주간, 모든 요청에 대해 오래된 Google 서비스와 새 대체 서비스를 모두 호출합니다. 두 응답을 로그하고 비교하세요:
async function getDirectionsWithComparison(
origin: string,
destination: string
) {
const [googleResult, mapatResult] = await Promise.all([
fetchGoogleDirections(origin, destination),
fetchMapAtlasDirections(origin, destination),
]);
// Compare key metrics
const distanceDelta = Math.abs(
googleResult.distance - mapatResult.distance
);
const durationDelta = Math.abs(
googleResult.duration - mapatResult.duration
);
console.log({
route: `${origin} -> ${destination}`,
googleDistance: googleResult.distance,
mapatDistance: mapatResult.distance,
distanceDeltaPercent: ((distanceDelta / googleResult.distance) * 100).toFixed(1),
googleDuration: googleResult.duration,
mapatDuration: mapatResult.duration,
durationDeltaPercent: ((durationDelta / googleResult.duration) * 100).toFixed(1),
});
// Use MapAtlas result in production, Google as validation
return mapatResult;
}
2단계: 피처 플래그 설정하기
피처 플래그를 사용해서 애플리케이션이 어떤 API를 호출할지 제어합니다. 문제가 생기면 즉시 롤백할 수 있습니다:
const useMapAtlasDirections = process.env.FEATURE_MAPATLAS_DIRECTIONS === "true";
const directions = useMapAtlasDirections
? await fetchMapAtlasDirections(origin, destination)
: await fetchGoogleDirections(origin, destination);
3단계: 에러율 모니터링하기
전환 후 다음을 모니터링하세요:
- 새 API의 HTTP 4xx/5xx 에러율
- 레이턴시 증가 (새 프로바이더는 응답 시간이 다를 수 있습니다)
- UI가 의존하는 응답의 누락된 필드
- 엣지 케이스의 라우트 정확도 (페리 루트, 유료 도로, 제한 구역)
4단계: 출시 전 로드 테스트하기
애플리케이션이 스파이크를 처리한다면, 예를 들어 아침 배송 디스패치 중의 물류 플랫폼이라면, 피크 볼륨의 2배로 새 API를 로드 테스트하세요. MapAtlas는 프로덕션 청구 없이 로드 테스트할 수 있는 샌드박스 환경을 제공합니다.
타임라인: 이번 주에 해야 할 것
아직 마이그레이션을 시작하지 않았다면, 우선순위 순서입니다:
- 이번 주: 코드베이스 감사. 네 가지 deprecated 서비스의 모든 사용처를 파악합니다.
- 2주차: MapAtlas 계정을 만들고 API 키를 받으세요. 무료 티어는 테스트용 10,000건을 커버합니다.
- 3주차: 가장 중요한 서비스(보통 DirectionsService)의 대체를 구현합니다.
- 4주차: 나머지 서비스를 마이그레이션하고 병렬 테스트를 실행합니다.
- 5월 마감 전: 전환하고, Google API 의존성을 제거하고, 청구를 업데이트합니다.
마이그레이션은 선택이 아닙니다. 2026년 5월 이후에는 deprecated 클래스가 Maps JavaScript API에서 제거되고, 이를 참조하는 모든 코드가 런타임 에러를 던집니다. 지금 시작하면 제대로 테스트할 시간이 있습니다. 마지막 주까지 기다리면 압박 속에 프로덕션을 패치하게 됩니다.
마이그레이션 지원을 위해 MapAtlas는 직접적인 개발자 지원을 제공합니다. 연락처 페이지를 통해 연락하거나 API 문서부터 시작해서 요구사항에 맞게 대체 API를 평가해보세요.
자주 묻는 질문
Google Maps API deprecated가 정확히 언제 적용되나요?
Heatmap Layer와 Drawing Library는 각각 2025년 8월과 5월에 deprecated되었고, 2026년 5월에 제거될 예정입니다. DirectionsService와 DistanceMatrixService는 2026년 2월 25일에 deprecated되었으며 마찬가지로 2026년 5월이 제거 목표입니다. 제거 후에는 이 서비스들에 대한 API 호출이 오류를 반환합니다.
2026년 5월 이후에도 기존 Google Maps JavaScript API 키가 작동하나요?
deprecated되지 않은 서비스에는 API 키가 계속 작동합니다. 하지만 Maps JavaScript API를 통해 DirectionsService, DistanceMatrixService, Heatmap Layer, Drawing Library를 호출하는 코드는 모두 작동을 멈춥니다. 마감일 전에 이 특정 호출들을 대체 API로 마이그레이션해야 합니다.
Google Maps Directions API에서 가장 저렴한 대안은 뭔가요?
MapAtlas는 Google 동등 제품보다 약 70% 저렴한 Directions API를 제공합니다. 무료 티어에는 월 10,000건의 요청이 포함되어 있어 마이그레이션 개발 및 테스트에 충분합니다. 다른 대안으로는 Mapbox, HERE, OpenRouteService가 있지만, MapAtlas는 Google과 가장 유사한 요청/응답 형식을 제공해서 마이그레이션 작업량을 줄여줍니다.
점진적으로 마이그레이션할 수 있나요, 아니면 한꺼번에 전환해야 하나요?
점진적으로 마이그레이션할 수 있습니다. 각 deprecated 서비스는 독립적이라서 DirectionsService부터, 그 다음 DistanceMatrixService, 이어서 시각화 라이브러리 순으로 교체할 수 있습니다. 각 교체를 개별적으로 테스트하고 다음으로 넘어갈 수 있어서 이 방식이 실제로 권장됩니다.
MapAtlas가 Google DirectionsService와 동일한 waypoint와 이동 모드를 지원하나요?
네. MapAtlas Directions API는 driving, walking, cycling 이동 모드와 중간 waypoint를 지원합니다. 요청 형식은 약간 다르지만(RESTful 엔드포인트 vs. JavaScript 클래스), 핵심 기능인 이동 모드 선택이 가능한 멀티스톱 라우팅은 동등합니다.

