# 서론
초기 angular로 개발하다가 React로 변경하게 되면서 redux를 많이 들었었다.
짧은기간에 환경세팅부터 통합테스트까지 진행해야 한다는 핑계로 react도 튜토리얼을 건너뛰고 진행했었고, 때문에 redux는 아예 배제하고 개발을 진행했었다. 다행히(?)도 openlayers를 이용한 지도기반 사이트 구축을 중심으로 했기 때문에, 전역상태관리 패키지가 없어도 진행할 수 있었다. ( 전역변수로 사용될 map 컴포넌트안에서 모든 위젯 컴포넌트 호출.. )
React가 점차 성장하면서 redux, contextAPI, recoil 그리고 jotai 등 다양한 상태관리 패키지들이 나타나고있다.
그 중 jotai 를 이용하여 웹지도를 다시 구현해보려고 한다.
openlayers와 vworld api 를 이용한 프로젝트를 생성할 예정
#0. 실행환경
- next.js 프로젝트 생성
- typescript
- styled-components
create-next-app --ts -e with-styled-components ${PROJECT_NAME}
# 1. 프로젝트 디렉토리 구조
...
∨ src/
> components/ : React Components
> hooks/ : React Custom Hooks
> interfaces/ : model or interface
> pages/ : Next Pages
> store/ : Jotai Store
> utils/ : custom utils ( common functions, settings ...)
#2. jotai 및 openlayers 설치
- [jotai] 문서 보기
# jotai 설치
yarn add jotai
# 또는
npm install jotai
- [openlayers] 문서 보기
# "@types/ol" 은 typescript 용이므로 javascript는 설치 할 필요 없음
yarn add ol @types/ol
# 또는
npm install ol @types/ol
#3. jotai 기본 문법
- atom() 을 이용하여 변수 설정
- atom()의 초기값은 반드시 있어야하며, undefined, null 등으로 초기값 설정 시 set함수는 never 타입
import { atom, useAtom } from 'jotai';
/*
* 변수 선언
*/
// 옳은 선언
const correctAtom1 = atom('');
const correctAtom2 = atom(0);
const correctAtom3 = atom({});
const correctAtom4 = atom([]);
// 잘못된 선언
const incorrectAtom1 = atom(null);
const incorrectAtom2 = atom(undefined);
const incorrectAtom3 = atom(unknown);
/*
* 변수 사용
*/
// 옳은 선언 변수 사용
const [str, setStr] = useAtom(correctAtom1);
const [num, setNum] = useAtom(correctAtom2);
const [obj, setObj] = useAtom(correctAtom3);
const [arr, setArr] = useAtom(correctAtom4);
// 잘못된 선언 변수 사용
const [null, setNull] = useAtom(incorrectAtom1); // setNull: never
const [undefined, setUndefined] = useAtom(incorrectAtom2); // setUndefined: never
const [unknown, setUnknown] = useAtom(incorrectAtom3); // setUnknown: never
- write 함수를 적용하고 싶다면 좀 더 세부적으로 설정할 수 있음
import { atom } from 'jotai';
/*
* 변수 선언
*/
// 1. primitive
const strAtom = atom('hello');
// 2. writeolny
const writeAtom = atom(null, (get, set, update) => {
set(strAtom, update);
});
// 3. readWrite
const readWriteAtom = atom(strAtom, (_get, set, update) => {
set(strAtom, update);
});
- 다양한 기술은 공식 문서 참고
#4. jotai 활용
- ./store/ 디렉토리에 mapAtom.tsx 생성
- 변수마다 스토어를 다르게 활용하고자하여 변수별로 파일을 생성함
- openlayers의 맵변수는 자체 get, set 함수를 가지고 있기 때문에 jotai의 set함수를 이용하지 않아도 됨
import { atom } from "jotai";
import { Map, View } from "ol";
import TileLayer from "ol/layer/Tile";
import { fromLonLat, transformExtent } from "ol/proj";
import XYZ from "ol/source/XYZ";
const url = `http://api.vworld.kr/req/wmts/1.0.0/${process.env.VW_KEY}/Base/{z}/{y}/{x}.png`;
export const mapAtom = atom<Map>(
new Map({
layers: [
new TileLayer({
source: new XYZ({
url,
}),
}),
],
view: new View({
center: fromLonLat([128, 37]),
zoom: 8,
extent: transformExtent([115, 30, 142, 45], "EPSG:4326", "EPSG:3857"),
minZoom: 6,
maxZoom: 22,
}),
})
);
- ./components/ 에 맵 컴포넌트 생성
import { useAtom } from "jotai";
import { useEffect, useRef } from "react";
import { MapLayout } from "components/cmmap/cmmap.styled";
import { mapAtom } from "store/mapAtom";
const Cmmap = () => {
const ref = useRef(null);
const [map] = useAtom(mapAtom);
useEffect(() => {
if (map && ref) {
map.setTarget(ref.current);
}
}, [map, ref]);
return <MapLayout ref={ref}></MapLayout>;
};
export default Cmmap;
후기
- 현업 때 상태관리 패키지를 활용했었으면 더 간결하고 독립적인 컴포넌트가 탄생했을 것 같다. (하지만 리덕스는 너무 복잡해보였음...)
- 다른 상태관리를 사용해보지 않았지만, jotai를 금방 적용해볼 수 있어서 쉽게 적용할 수 있어보인다.
- 백엔드없이 구현하게되어 reactQuery를 활용하지 않고 jotai 를 사용했으나, 백엔드가 있다면 reactQuery로 대체하여 사용해도 좋을 듯하여 추 후 백엔드를 구현하게 되면 reactQuery 로 바꿔서 적용해볼 예정이다.
'Dev-FE' 카테고리의 다른 글
[React-Native] #2. React Native - navigation 이용한 페이지 이동 (0) | 2022.10.30 |
---|---|
[React-Native] #1. React Native 프로젝트 첫 시작하기 (0) | 2022.10.19 |
[WEB] #3. tslint 로 코드 문법 설정하기 (1) | 2022.09.29 |
[WEB] #1. 무한스크롤 만들기 (1) | 2022.09.21 |
[CSS,JS] 동적 색상값(HEX) 얻기 (0) | 2022.08.29 |