[OpenLayers] OpenLayers 시작하기! (2) - 근데 이제 React와 Next를 곁들인..

지혜의 Devlog 📚·2021년 11월 22일
3

지난 포스팅에서 OpenLayers 라이브러리를 사용하여 Map 객체를 생성해 보았다.
이제 React + Next 환경에서 적용하는 방법을 알아보겠다.


🗺️ 0. 폴더 구조

먼저, 우리는 생성된 Map 객체를 프로젝트 어디서든 사용할 수 있게 하기 위하여 Context API를 사용해 Map을 전역 상태로 관리할 것이다.
따라서 아래와 같은 폴더 구조가 생성된다.

pages
 ├──_app.js
 ├──index.js
 │ 
context/map
 ├──index.js
 ├──map.js
 └──mapContext.js

🗺️ 1. Context 생성

// ./map/mapContext.js
import React from "react";

const MapContext = new React.createContext({});

export default MapContext;

🗺️ 2. Provider에 Map객체 저장

지난 포스팅에서 생성한 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;

🗺️ 3. map/index.js 경로 설정

// ./map/index.js
export { default } from './map';

🗺️ 4. Context.Provider로 감싸기

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

🗺️ 5. pages/index.js에 Map객체 불러오기

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, 지도 초깃값을 제주도 금오름으로 해놓았더니, 떠나고 싶다...🍊)

0개의 댓글