좌표계 변환을 처음 다뤄보면 EPSG 코드만 봐도 어디서 시작해야 할지 막막한 순간이 옵니다. 잘못 설정하면 지도에서 좌표가 km 단위로 어긋나거나 한반도가 아예 다른 위치에 찍힙니다.
이 글은 PROJ.4 / PROJ 라이브러리의 한국 환경 활용을 공식 문서와 EPSG 데이터베이스 기준으로 정리합니다. 다 읽으면 환경에 맞는 EPSG 코드·언어별 라이브러리·실전 변환 코드까지 정리됩니다.

PROJ.4 / PROJ 한 줄 정리 — 같은 라이브러리, 다른 이름
PROJ.4는 좌표계 변환 라이브러리의 옛 이름입니다. 현재 공식 명칭은 PROJ(proj.org)이며, 2018년 PROJ 5.0부터 ".4"를 떼었습니다. 검색에서는 여전히 "proj4"로 많이 쓰이지만, 실제 라이브러리는 PROJ 9.x(2024~2025년 안정 버전)가 표준입니다.
| 항목 | 내용 |
|---|---|
| 공식 이름 | PROJ (구: PROJ.4) |
| 현재 안정 버전 | 9.5 (2024-09 기준) |
| 최초 개발 | 1980년대, USGS Gerald Evenden |
| 현재 관리 | OSGeo 재단, MIT 라이선스 |
| 사용처 | QGIS·GeoServer·PostGIS·GDAL·OpenLayers·mapbox 내부 엔진 |
| 핵심 기능 | 좌표계 정의·변환·투영 |
PROJ는 EPSG(European Petroleum Survey Group) 데이터베이스를 내장해 약 8,000개의 좌표계를 지원합니다. 한국 환경에서 자주 쓰는 좌표계도 EPSG 코드 한 줄로 변환할 수 있습니다.
한국에서 자주 쓰는 좌표계 7가지 — EPSG 코드 매트릭스
| EPSG | 이름 | 단위 | 주 용도 |
|---|---|---|---|
| 4326 | WGS 84 (위경도) | 도(°) | GPS 표준, 글로벌 |
| 3857 | Web Mercator | 미터 | 구글 지도·OpenStreetMap·카카오맵 |
| 5179 | Korea 2000 / Unified CS (UTM-K) | 미터 | 네이버 지도·다음 지도 한국 통합 |
| 5181 | Korea 2000 / Central Belt | 미터 | 구 중부원점 (서울·경기) |
| 5186 | Korea 2000 / Central Belt 2010 | 미터 | 지적도 중부 (2010년 표준) |
| 5187 | Korea 2000 / East Belt 2010 | 미터 | 지적도 동부 (영남·강원 일부) |
| 32652 | WGS 84 / UTM zone 52N | 미터 | 한국 동부 (126°E ~ 132°E) |

EPSG 코드를 모르고 좌표 데이터를 받으면 변환 자체가 불가능합니다. 공급자에게 좌표계가 무엇인지 명시적으로 확인하는 게 첫 단계입니다. 한국 공공 데이터(국토부·국세청·도로공사)는 보통 EPSG:5179(UTM-K) 또는 EPSG:5186(중부 2010) 중 하나입니다.
PROJ 설치 — Linux·Windows·macOS
운영체제별 설치 방법입니다. PROJ 자체는 C 라이브러리라 시스템 설치 후 언어별 바인딩을 따로 깝니다.
Linux (Ubuntu/Debian)
sudo apt update
sudo apt install libproj-dev proj-bin
proj --version
macOS (Homebrew)
brew install proj
proj --version
Windows
OSGeo4W 인스톨러 또는 conda를 통한 설치가 가장 안정적입니다:
# conda 환경
conda install -c conda-forge proj
# 또는 OSGeo4W (https://trac.osgeo.org/osgeo4w)
설치 후 proj 명령으로 버전 확인이 가능하면 정상입니다. EPSG 데이터베이스(proj.db)는 PROJ가 자동으로 가져옵니다 — 별도 설정 불필요.
변환 예제 — WGS84 ↔ UTM-K (EPSG:5179) 실전
서울 시청 좌표(위도 37.5666, 경도 126.9784)를 UTM-K로 변환하는 예제입니다.
명령줄 (cs2cs)
echo "126.9784 37.5666" | cs2cs +init=EPSG:4326 +to +init=EPSG:5179
# 결과: 953967.46 1953306.59 (UTM-K x, y)
Python (pyproj)
from pyproj import Transformer
transformer = Transformer.from_crs("EPSG:4326", "EPSG:5179", always_xy=True)
x, y = transformer.transform(126.9784, 37.5666)
print(f"UTM-K: x={x:.2f}, y={y:.2f}")
⚠️ always_xy=True 옵션 중요 — 안 붙이면 PROJ 6 이상에서는 위도·경도 순서가 라이브러리 정의에 따라 바뀝니다. 이 옵션이 "X 먼저, Y 다음"으로 강제합니다.
언어별 라이브러리 — 작업 환경별 선택
| 언어 | 라이브러리 | 설치 | 특징 |
|---|---|---|---|
| Python | pyproj | pip install pyproj |
가장 활발, NumPy 친화 |
| JavaScript | proj4js | npm install proj4 |
브라우저·Node 양쪽 |
| Java | PROJ4J (locationtech) | Maven org.locationtech.proj4j |
순수 자바 구현 |
| C# / .NET | DotSpatial.Projections | NuGet DotSpatial.Projections |
.NET 호환, 일부 코드 변환 필요 |
| PostgreSQL | PostGIS | CREATE EXTENSION postgis |
ST_Transform() 함수로 SQL 안에서 변환 |
| C/C++ | libproj | 시스템 설치 | 가장 빠름, 원본 라이브러리 |
본업 스택이 Java/Spring + .NET 풀스택이라면 백엔드: PROJ4J(Java) + 데이터베이스: PostGIS 조합이 가장 안정적입니다.

PROJ.4 → PROJ 8/9 변경점 — 옛 코드 마이그레이션
옛 PROJ.4 코드가 PROJ 8 이상에서 깨지는 경우가 많습니다. 핵심 변경 3가지입니다.
| 영역 | PROJ.4 (옛) | PROJ 8/9 (현재) |
|---|---|---|
| 좌표 순서 | 항상 (X, Y) | 좌표계 정의 따름. always_xy=True 권장 |
| 초기화 방식 | +init=EPSG:5179 |
EPSG 코드 직접 "EPSG:5179" |
| API | pj_init_plus() |
proj_create_crs_to_crs() |
| Datum 변환 | 단순 매개변수 | 시간 의존 변환(Time-dependent) 지원 |
옛 코드를 그대로 두면 PROJ 8 이상에서 좌표가 도와 위경도 뒤바뀌어 한반도 좌표가 인도양에 찍히는 사고가 흔합니다. 마이그레이션 시 always_xy=True 또는 명시적 축 순서 지정이 필요합니다.
흔한 함정 3가지
1. EPSG 코드 잘못 추측
공급자가 좌표계를 안 알려준 데이터를 받으면 추측하지 말고 확인해야 합니다. 한국 공공 데이터는 5179·5181·5186·5187 중 하나일 가능성이 높지만, "추측해서 변환"하면 모든 좌표가 km 단위로 어긋납니다. 공급자 문서를 끝까지 찾거나 메타데이터를 확인하세요.
2. Web Mercator(3857)와 WGS84(4326) 혼동
둘 다 "글로벌 표준"이지만 단위가 다릅니다. 4326은 위경도(도°), 3857은 미터입니다. 카카오맵·구글맵 SDK가 내부적으로 3857을 쓰는데 위경도(4326)를 그대로 넣으면 지도가 적도 부근에 압축돼서 나옵니다.
3. PROJ 6 이상의 좌표 축 순서 변경
위 표에서 언급한 사고. PROJ 6부터 좌표 순서가 좌표계 정의를 따릅니다 — 위도·경도 좌표계(EPSG:4326)는 라이브러리에 따라 (위도, 경도) 또는 (경도, 위도)로 다르게 처리됩니다. always_xy=True(pyproj) 또는 명시적 축 순서 강제가 답입니다.
Q&A — 자주 보는 질문 5개
Q. EPSG:5174 (Korean Datum 1985)와 EPSG:5179 (UTM-K) 중 무엇을 써야 하나요?
A. 신규 프로젝트면 EPSG:5179(UTM-K) 권장입니다. 5174는 1985년 베셀 타원체 기반 옛 표준이라 GPS 측위와 60~200m 정도 차이가 납니다. 5179는 GRS80(WGS84 호환) 타원체로 GPS 좌표와 정합성이 높습니다.
Q. 카카오맵 API에서 좌표를 받으면 어떤 EPSG를 써야 하나요?
A. 카카오맵 API의 getPosition()은 EPSG:4326(WGS84 위경도) 반환이 기본입니다. 다만 카카오맵 내부 렌더링은 EPSG:5181(중부원점 TM) 기반이라 일부 옛 API는 TM 좌표를 반환하기도 합니다. 공식 문서에서 "응답 좌표계"를 확인하세요.
Q. 좌표 변환할 때 cs2cs 명령줄과 pyproj 결과가 다른데요?
A. PROJ 6 이상의 축 순서 변경 영향입니다. 명령줄 cs2cs는 보통 (경도, 위도) 입력 기대, pyproj는 always_xy 옵션에 따라 동작. 항상 같은 라이브러리·같은 옵션으로 일관 사용하세요.
Q. PostgreSQL에서 좌표계 변환할 때 PostGIS 없이 가능한가요?
A. 안 됩니다. PostgreSQL 기본 기능에는 좌표계 변환이 없습니다. PostGIS 확장을 깔고 ST_Transform(geom, 5179) 같은 함수를 써야 합니다. PostGIS 자체가 내부적으로 PROJ를 사용합니다.
Q. 위성 영상이나 카카오/네이버 지도 타일을 깔 때 어떤 좌표계가 표준인가요?
A. 타일 좌표는 EPSG:3857(Web Mercator)가 사실상 표준입니다. 구글·OSM·카카오·네이버 모두 내부 타일 렌더링은 3857입니다. 좌표 입력은 4326(위경도)로 받고, 타일 계산은 3857로 변환하는 게 표준 흐름입니다.
정리 — 한국 환경 좌표계 선택 매트릭스
| 작업 | 권장 EPSG | 비고 |
|---|---|---|
| GPS 좌표 저장 | 4326 (WGS84) | 위경도 표준 |
| 카카오·네이버 지도 타일 | 3857 (Web Mercator) | 구글·OSM과 호환 |
| 한국 공공 데이터 처리 | 5179 (UTM-K) | 미터 단위, 거리 계산 정확 |
| 지적도·등기 데이터 | 5186 또는 5187 | 중부·동부 벨트 |
| 옛 데이터 호환 | 5181 (Central Belt) | 구 중부원점, 마이그레이션 시 |

PROJ.4가 오래 살아남은 이유는 하나의 표준이 모든 좌표계를 통합했기 때문입니다. EPSG 코드 한 줄로 변환이 끝나는 게 진짜 가치입니다. 비슷한 환경이면 위 매트릭스만으로 충분합니다.
검증 환경: PROJ 9.5, pyproj 3.6, Ubuntu 24.04 / Windows 11 / macOS 14, EPSG Database v11
원본 발행: 2022-08-30 / 2026-06-05 전면 개정 (본문 ~1,000자 → 4,000자, EPSG 매트릭스 + 언어별 라이브러리 + 마이그레이션 가이드 + Q&A 추가)
'IT > Information' 카테고리의 다른 글
| 개발 시 도움이 될 도구들 (0) | 2022.10.02 |
|---|---|
| Chocolatey 설치 및 사용 방법 (0) | 2022.09.26 |
| [MATLAB] MinGW-W64 수동 설치 (1) | 2022.09.23 |
| com, net, co.kr의 차이는? (0) | 2022.08.29 |
| 도메인이란 (0) | 2022.08.25 |
IT 기술과 개발 내용을 포스팅하는 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!