지난 포스팅에서 OpenLayers 라이브러리를 사용하여 Map 객체를 생성해 보았다.
이제 React + Next 환경에서 적용하는 방법을 알아보겠다.
먼저, 우리는 생성된 Map 객체를 프로젝트 어디서든 사용할 수 있게 하기 위하여 Context API를 사용해 Map을 전역 상태로 관리할 것이다.
따라서 아래와 같은 폴더 구조가 생성된다.
pages
├──_app.js
├──index.js
│
context/map
├──index.js
├──map.js
└──mapContext.js
// ./map/mapContext.js
import React from "react";
const MapContext = new React.createContext({});
export default MapContext;
지난 포스팅에서 생성한 Map객체를 Context에 저장
// ./map/map.js
import React, { useState, useEffect } from 'react';
import MapContext from './mapContext';
import 'ol/ol.css';
import { Map, View } from 'ol';
import { defaults } from 'ol/control';
import { fromLonLat, get } from 'ol/proj';
import { Tile } from 'ol/layer';
import { OSM, XYZ } from 'ol/source';
const Map = ({ children }) => {
const [mapObj, setMapObj] = useState({});
useEffect(() => {
const map = new Map({
controls: defaults({ zoom: false, rotate: false }).extend([]),
layers: [
new Tile({
source: new OSM()
}),
new Tile({
name: 'Base',
visible: true,
source: new XYZ({
url: `http://api.vworld.kr/req/wmts/1.0.0/${process.env.VWORLD_API_KEY}/Base/{z}/{y}/{x}.png`
})
})
],
target: 'map',
view: new View({
projection: get('EPSG:3857'),
center: fromLonLat([126.30574134206182, 33.35570244202401], get('EPSG:3857')),
zoom: 14
})
})
setMapObj({ map });
return () => map.setTarget(undefined);
}, []);
// ✨ MapContext.Provider에 객체 저장
return <MapContext.Provider value={{ mapObj }}>{children}</MapContext.Provider>;
};
export default Map;
// ./map/index.js
export { default } from './map';
Provider에 저장한 객체를 사용하기 위해서는 Context.Provider로 감싸져 있는 자식 요소에서 사용 가능하다. 따라서 우리는 React+Next의 최상위 루트인 _app.js
에 적용할 것이다.
import dynamic from 'next/dynamic';
const Map = dynamic(() => import('context/maps'), { ssr: false });
function MyApp({ Component, pageProps }) {
return (
<>
<Map>
<Component {...pageProps} />
</Map>
</>
);
}
export default MyApp;
✨ 중요 POINT!
위 예제를 보면dynamic import
로 모듈을 불러오는 것을 볼 수 있다.
Next.js는 기본적으로 SSR로 동작한다. 하지만 OpenLayers는 브라우저에서만 동작하는 라이브러리이기 때문에 SSR 동작이 불가능하다. 따라서 Next.js에서 제공해주는dynamic import
를 사용하면 모듈을 빌드 타임이 아닌 런타임에 불러오도록 한다.
Next.js 공식문서 - next/dynamic
import Head from 'next/head';
import { useContext, useState } from 'react';
import MapContext from 'context/maps/mapContext';
export default function Home() {
const { mapObj } = useContext(MapContext);
const { map } = mapObj;
return (
<div>
<Head>
<title>OpenLayers Practice</title>
</Head>
<div id='map'></div>
</div>
);
}
오늘은 OpenLayers 객체를 React + Next 환경에 적용해 보았다.
위에서 보면 전역 상태로 만든 Map 객체를 어디에 쓰인다는 것인가? 싶지만,
후에 지도를 컨트롤하는 layer add/remove, zoom in/out, map scale 등에서 유용하게 쓰인다!
지도 컨트롤은 다음 포스팅으로 또 찾아오겠다ㅏㅏㅏ!
(오늘의 tmi, 지도 초깃값을 제주도 금오름으로 해놓았더니, 떠나고 싶다...🍊)