0Pricing
R Academy · 강의

좌표 참조 체계와 투영

st_crs()와 st_transform()을 사용해 CRS 사이를 올바르게 변환합니다.

좌표 참조 체계와 투영은(는) CoddyKit의 무료 R Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 R Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

CRS가 중요한 이유

좌표 참조 시스템(CRS)은 도형 열의 숫자가 무엇을 의미하는지 R에 알려줍니다. 즉, 위도/경도의 도 단위인지, 투영 격자의 미터 단위인지, 아니면 다른 값인지를 나타냅니다. 서로 다른 CRS의 데이터를 재투영하지 않고 섞으면 공간 조인이 조용히 실패하고 거리 계산도 잘못됩니다.

library(sf)

# Two sf objects in the same CRS: operations work
nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))

# sf will error or warn when CRS do not match during operations
# This is the CRS metadata attached to the object
crs <- st_crs(nc)
cat('EPSG:', crs$epsg, '\n')
cat('Input is geographic (lon/lat)?', st_is_longlat(nc), '\n')
cat('Units:', crs$units_gdal, '\n')

st_crs: CRS 정보 읽기

st_crs(sf_obj)는 EPSG 코드, WKT 문자열, Proj4 문자열 및 단위 정보가 포함된 crs 객체를 반환합니다. 정수 EPSG 코드를 직접 전달하여 CRS 정의를 가져올 수도 있습니다.

library(sf)

nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))

# Inspect the CRS object
crs <- st_crs(nc)
cat('Class:', class(crs), '\n')
cat('EPSG:', crs$epsg, '\n')
cat('Proj4:', substr(crs$proj4string, 1, 60), '...\n')

# Lookup a CRS by EPSG code
wgs84 <- st_crs(4326)
web_mercator <- st_crs(3857)

cat('\nWGS84 name:', wgs84$Name, '\n')
cat('Web Mercator name:', web_mercator$Name, '\n')

EPSG:4326 — WGS84

EPSG:4326은 GPS 좌표의 표준인 세계 측지 시스템 1984입니다. 좌표는 십진 도 단위입니다. 경도(X)의 범위는 −180에서 180이고 위도(Y)의 범위는 −90에서 90입니다. 이는 투영 CRS가 아닌 지리적 CRS입니다.

library(sf)

# Create points in WGS84 (GPS coordinates)
cities <- data.frame(
  city = c('London', 'Tokyo', 'Sydney', 'New York'),
  lon  = c(-0.118, 139.692, 151.209, -74.006),
  lat  = c(51.509,  35.689, -33.869,  40.713)
)

cities_sf <- st_as_sf(cities,
  coords = c('lon', 'lat'),
  crs    = 4326
)

cat('CRS:', st_crs(cities_sf)$Name, '\n')
cat('Units:', st_crs(cities_sf)$units_gdal, '\n')

# Naive distance in degrees (not meaningful for real distances)
d <- st_distance(cities_sf[1, ], cities_sf[2, ])
cat('London-Tokyo distance (degrees):', round(as.numeric(d), 2), '\n')

EPSG:3857 — Web Mercator

EPSG:3857은 Google Maps, OpenStreetMap 및 Leaflet에서 사용하는 Web Mercator 투영입니다. 좌표는 미터 단위이며 본초 자오선과 적도를 중심으로 합니다. 극지방 근처에서는 면적이 왜곡되지만 웹 시각화에는 적합합니다.

library(sf)

cities <- data.frame(
  city = c('London', 'Tokyo'),
  lon  = c(-0.118, 139.692),
  lat  = c(51.509,  35.689)
)
cities_sf <- st_as_sf(cities, coords = c('lon', 'lat'), crs = 4326)

# Transform to Web Mercator
cities_merc <- st_transform(cities_sf, 3857)

cat('WGS84 coords (degrees):\n')
print(st_coordinates(cities_sf))

cat('\nWeb Mercator coords (metres):\n')
print(st_coordinates(cities_merc))

# Distance is now in metres
d <- st_distance(cities_merc[1, ], cities_merc[2, ])
cat('\nLondon-Tokyo distance (km):', round(as.numeric(d) / 1000, 0), '\n')

st_set_crs: CRS 지정

st_set_crs(sf_obj, crs)는 좌표를 변환하지 않고 CRS를 지정합니다. CRS 메타데이터가 없거나 잘못된 경우에만 사용하십시오. 좌표를 새 CRS로 재투영하려면 대신 st_transform()을 사용하십시오.

library(sf)

# Create geometry with NO CRS
pts <- st_sfc(
  st_point(c(-74.006, 40.713)),
  st_point(c(-87.629, 41.878))
)
cat('CRS before:', is.na(st_crs(pts)), '(NA = no CRS)\n')

# Assign WGS84 (no coordinate transformation)
pts_wgs84 <- st_set_crs(pts, 4326)
cat('CRS after assignment:', st_crs(pts_wgs84)$epsg, '\n')

# Compare with st_transform (DOES transform coordinates)
pts_sf    <- st_sf(id = 1:2, geometry = pts_wgs84)
pts_merc  <- st_transform(pts_sf, 3857)
cat('Original lon:', st_coordinates(pts_sf)[1, 'X'], '\n')
cat('Mercator X:  ', st_coordinates(pts_merc)[1, 'X'], '\n')

st_transform: 재투영

st_transform(sf_obj, crs)는 모든 도형을 현재 CRS에서 대상 CRS로 재투영하며, 전체 측지 변환을 적용합니다. crs 인수에는 EPSG 정수, Proj4 문자열 또는 WKT 문자열을 사용할 수 있습니다.

library(sf)

nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))
cat('Original CRS:', st_crs(nc)$epsg, '\n')

# Re-project to WGS84
nc_wgs84 <- st_transform(nc, 4326)
cat('Transformed CRS:', st_crs(nc_wgs84)$epsg, '\n')

# Re-project to a local projected CRS (NC State Plane)
nc_stateplane <- st_transform(nc, 32119)  # NAD83 / North Carolina
cat('State Plane CRS:', st_crs(nc_stateplane)$Name, '\n')

# Area calculation is more accurate in a projected CRS
area_deg <- st_area(nc[1, ])
area_m2  <- st_area(nc_stateplane[1, ])
cat('Area (degrees^2):', format(area_deg, big.mark = ','), '\n')
cat('Area (m^2):      ', format(area_m2,  big.mark = ','), '\n')

올바른 투영 선택하기

투영마다 최적화하는 특성이 다릅니다. 예를 들어 면적 보존 투영(Mollweide), 정각 투영(Mercator), 등거리 투영이 있습니다. 지역 분석에는 미터 단위의 투영 CRS를 사용하고, 전 세계 개요에는 WGS84를 사용하며, 웹 지도에는 Web Mercator를 사용하십시오.

library(sf)

# Common EPSG codes cheat sheet
epsg_table <- data.frame(
  EPSG = c(4326, 3857, 4269, 32637, 27700),
  Name = c(
    'WGS84 (GPS, global)',
    'Web Mercator (web maps)',
    'NAD83 (North America geographic)',
    'UTM zone 37N (Middle East)',
    'British National Grid (UK)'
  ),
  Units = c('degrees', 'metres', 'degrees', 'metres', 'metres')
)

print(epsg_table, row.names = FALSE)

# Look up any EPSG online: https://epsg.io/<code>
cat('\nTip: use st_crs(epsg_code)$Name to verify a code\n')

Proj4 문자열

EPSG 코드가 표준이 되기 전에는 CRS를 Proj4 문자열로 정의했습니다. 이는 PROJ 라이브러리에 전달하는 간결한 매개변수 문자열입니다. 지금도 st_transform()과 함께 사용할 수 있지만, 명확성과 향후 호환성을 위해 EPSG 코드가 선호됩니다.

library(sf)

nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))

# WGS84 as Proj4 string
wgs84_proj4 <- '+proj=longlat +datum=WGS84 +no_defs'
nc_wgs84 <- st_transform(nc, crs = wgs84_proj4)

cat('Using Proj4 string:\n', wgs84_proj4, '\n')
cat('Result CRS EPSG:', st_crs(nc_wgs84)$epsg, '\n')

# Compare: equivalent to st_transform(nc, 4326)
cat('Same as EPSG 4326?',
    identical(st_crs(nc_wgs84), st_crs(st_transform(nc, 4326))), '\n')

CRS가 같은지 확인하기

공간 조인이나 중첩 작업을 수행하기 전에 st_crs(a) == st_crs(b)를 사용하여 두 객체가 같은 CRS를 공유하는지 확인하십시오. 다르면 작업을 진행하기 전에 한 객체를 다른 객체에 맞게 변환하십시오.

library(sf)

# Two objects in different CRS
nc_nad27  <- read_sf(system.file('shape/nc.shp', package = 'sf'))
nc_wgs84  <- st_transform(nc_nad27, 4326)

cat('Same CRS?', st_crs(nc_nad27) == st_crs(nc_wgs84), '\n')

# Always check before join/overlay
align_crs <- function(a, b) {
  if (st_crs(a) != st_crs(b)) {
    message('CRS mismatch! Transforming b to match a.')
    b <- st_transform(b, st_crs(a))
  }
  list(a = a, b = b)
}

aligned <- align_crs(nc_nad27, nc_wgs84)
cat('After alignment - same CRS?',
    st_crs(aligned$a) == st_crs(aligned$b), '\n')

CRS를 사용한 거리 계산

지리적 CRS(도 단위)에서 계산한 거리는 의미가 없습니다. 먼저 등거리 또는 면적 보존 투영 CRS로 재투영하거나, PROJ 라이브러리를 통해 WGS84를 올바르게 처리하는 sf의 내장 측지 거리 계산을 사용하십시오.

library(sf)

# City points in WGS84
cities <- data.frame(
  city = c('Paris', 'Berlin', 'Madrid', 'Rome'),
  lon  = c(2.350, 13.404, -3.702, 12.496),
  lat  = c(48.865, 52.520,  40.417, 41.902)
)
cities_sf <- st_as_sf(cities, coords = c('lon', 'lat'), crs = 4326)

# sf computes geodesic distances on WGS84 automatically
dist_matrix <- st_distance(cities_sf)
rownames(dist_matrix) <- cities$city
colnames(dist_matrix) <- cities$city

# Convert to km
dist_km <- round(as.numeric(dist_matrix) / 1000)
mat_km <- matrix(dist_km, 4, 4, dimnames = list(cities$city, cities$city))
print(mat_km)

완전한 CRS 작업 흐름

완전한 작업 흐름은 다음과 같습니다. 원시 GPS 데이터를 불러오고, WGS84를 지정한 다음, 정확한 면적 및 거리 계산을 위해 지역 미터 단위 CRS로 재투영하고, 분석을 수행한 뒤, 웹 지도 출력에 사용하도록 WGS84로 다시 재투영합니다.

library(sf)

# Load and assign CRS
nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))
nc_wgs84 <- st_transform(nc, 4326)

# Re-project to NC State Plane (metres) for accurate areas
nc_proj <- st_transform(nc, 32119)

# Compute area per county in km2
nc_proj$area_km2 <- as.numeric(st_area(nc_proj)) / 1e6

# Top 5 largest counties
top5 <- nc_proj[order(-nc_proj$area_km2), c('NAME', 'area_km2')]
cat('5 Largest NC Counties (km2):\n')
print(head(as.data.frame(top5)[, c('NAME', 'area_km2')], 5))

# Back to WGS84 for output
nc_output <- st_transform(nc_proj, 4326)
cat('\nOutput CRS:', st_crs(nc_output)$epsg, '\n')

빠른 확인

현재 WGS84(EPSG:4326)에 있는 폴리곤 피처의 정확한 면적(제곱미터)을 계산해야 합니다. 어떻게 해야 하나요?

복습: CRS와 투영

핵심 내용:

  • st_crs(sf_obj)는 CRS 메타데이터를 읽습니다. CRS를 지정할 때는 EPSG 코드가 선호됩니다
  • EPSG:4326 = WGS84(GPS용 도 단위), EPSG:3857 = Web Mercator(웹 지도용 미터 단위)
  • st_set_crs()는 변환 없이 CRS를 지정하고, st_transform()은 좌표를 재투영합니다
  • 공간 작업 전에 항상 st_crs(a) == st_crs(b)로 CRS가 같은지 확인하십시오
  • 정확한 거리와 면적을 위해 먼저 미터 단위의 투영 CRS로 재투영하십시오
  • Proj4 문자열도 여전히 작동하지만 EPSG 코드가 더 간결하고 읽기 쉽습니다
library(sf)
nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))

# CRS pipeline
cat('Original:', st_crs(nc)$epsg, '\n')
nc_wgs84 <- st_transform(nc, 4326)
nc_proj  <- st_transform(nc_wgs84, 32119)
cat('WGS84:', st_crs(nc_wgs84)$epsg, '\n')
cat('Projected:', st_crs(nc_proj)$epsg, '\n')

자주 묻는 질문

“좌표 참조 체계와 투영” 강의는 무료인가요?

네 — “좌표 참조 체계와 투영” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 R Academy 강의 전체를 잠금 해제할 수 있습니다. R Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“좌표 참조 체계와 투영”에서 뭘 배우나요?

st_crs()와 st_transform()을 사용해 CRS 사이를 올바르게 변환합니다. 브라우저에서 직접 실행하는 실습 코드로 R Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

R Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 R Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“좌표 참조 체계와 투영” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 R Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 R Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. sf 패키지로 단순 피처 다루기
  2. 좌표 참조 체계와 투영
  3. 공간 조인과 연산
  4. leaflet으로 인터랙티브 지도 만들기
← R Academy(으)로 돌아가기