먼저 React 프로젝트를 생성하고 필요한 패키지를 설치함.
npx create-react-app my-map-app --template typescript
cd my-map-app
npm install ol
MapManager.ts
파일 생성OpenLayers를 사용하여 지도를 관리하는 MapManager
클래스를 생성함.
import Map from 'ol/Map';
import View from 'ol/View';
import { fromLonLat } from 'ol/proj';
import TileLayer from 'ol/layer/Tile';
import { Tile, Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource, XYZ } from 'ol/source';
import { defaults as defaultControls } from 'ol/control';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import { Style, Circle as CircleStyle, Fill, Stroke } from 'ol/style';
export interface LocationResult {
success: boolean;
error?: string;
}
export type LocationCallback = (result: LocationResult) => void;
class MapManager {
private map: Map | null = null;
private locationLayer: VectorLayer<VectorSource> | null = null;
initialize(target: string): Map {
const baseMap = new XYZ({
url: "http://api.vworld.kr/req/wmts/1.0.0/{apiKey}/Base/{z}/{y}/{x}.png",
crossOrigin: 'anonymous',
transition: 0,
});
this.map = new Map({
target,
layers: [
new Tile({
source: baseMap,
preload: 20,
}),
],
view: new View({
center: fromLonLat([127.550, 35.871]),
zoom: 7.5,
}),
controls: defaultControls({ zoom: false }),
});
return this.map;
}
findMyLocation(callback: LocationCallback): void {
if (!this.map) {
callback({ success: false, error: '지도가 초기화되지 않음' });
return;
}
if (!navigator.geolocation) {
callback({ success: false, error: '브라우저가 위치 정보를 지원하지 않음' });
return;
}
navigator.geolocation.getCurrentPosition(
(position) => {
const { longitude, latitude } = position.coords;
const location = fromLonLat([longitude, latitude]);
const locationFeature = new Feature({
geometry: new Point(location),
});
const vectorSource = new VectorSource({
features: [locationFeature],
});
const vectorLayer = new VectorLayer({
source: vectorSource,
style: new Style({
image: new CircleStyle({
radius: 8,
fill: new Fill({ color: '#3182f6' }),
stroke: new Stroke({ color: '#ffffff', width: 2 }),
}),
}),
});
this.map.addLayer(vectorLayer);
this.map.getView().animate({
center: location,
zoom: 15,
duration: 1000,
});
callback({ success: true });
},
(error) => {
let errorMessage = '알 수 없는 오류 발생';
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage = '위치 정보 접근 권한이 거부됨';
break;
case error.POSITION_UNAVAILABLE:
errorMessage = '위치 정보를 사용할 수 없음';
break;
case error.TIMEOUT:
errorMessage = '위치 정보 요청 시간이 초과됨';
break;
}
callback({ success: false, error: errorMessage });
},
{ enableHighAccuracy: true, timeout: 5000, maximumAge: 0 }
);
}
}
export default new MapManager();
MapComponent.tsx
파일 생성React 컴포넌트에서 MapManager
를 사용하여 지도 렌더링 및 내 위치 찾기 기능을 추가함.
import React, { useEffect, useState } from 'react';
import MapManager from '../utils/MapManager';
import '../assets/map.css';
const MapComponent = () => {
const [locationError, setLocationError] = useState<string | null>(null);
useEffect(() => {
MapManager.initialize('map');
return () => MapManager.cleanup();
}, []);
const findMyLocation = () => {
MapManager.findMyLocation((result) => {
if (!result.success && result.error) {
setLocationError(result.error);
} else {
setLocationError(null);
}
});
};
return (
<div className="map-container">
<div id="map" className="map" />
<button className="location-button" onClick={findMyLocation}>
내 위치 찾기
</button>
{locationError && <div className="location-error">{locationError}</div>}
</div>
);
};
export default MapComponent;
map.css
).map-container {
position: relative;
width: 100%;
height: 500px;
}
.map {
width: 100%;
height: 100%;
}
.location-button {
position: absolute;
top: 10px;
right: 10px;
padding: 10px;
background: blue;
color: white;
border: none;
cursor: pointer;
}
.location-error {
color: red;
margin-top: 10px;
}
그래서 님 위치는 어디심?