티스토리 뷰

지난번에 이어 DB에 있는 데이터를 가져와 화면에 출력할 예정임.

 

1. 프로젝트 진행할 디렉토리 만들기

cd 또는 cd /d 사용하여 원하는 폴더로 이동
mkdir 디렉토리명
cd 디렉토리명

 

2. package.json 생성

npm init -y

 

3. 필요한 모듈 또는 플러그인 설치

npm install --save pg dotenv express axios cors ol
npm install --save-dev parcel-bundler

 

4. package.json 내용 수정 및 추가

{
    "name": "gis",
    "version": "0.0.1",
    "type": "module",
    "description": "get map data",
    "main": "main.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "parcel index.html",
        "build": "parcel build --public-url . index.html"
    },
    "keywords": [
        "openstreetmap"
    ],
    "author": "",
    "license": "ISC",
    "dependencies": {
        "axios": "^1.4.0",
        "cors": "^2.8.5",
        "dotenv": "^16.0.3",
        "express": "^4.18.2",
        "ol": "^7.3.0",
        "pg": "^8.11.0"
    },
    "devDependencies": {
        "parcel-bundler": "^1.12.5"
    }
}

 

5. index.js 생성 db 연결 되는지 확인

import pg from 'pg';

const { Pool } = pg;

const pool = new Pool({
  user: 'username',
  host: 'local 또는 127.0.0.1',
  database: 'db name',
  password: 'password',
  port: 5432,
});
async function conntectToPostfrsql() {
    try {
        await pool.connect();
        console.log("CONNETING SUCCESS");
    } catch (error) {
        console.error("CONNECTING FAIL");
    } finally {
        await pool.end();
    }
}

  conntectToPostfrsql();

터미널에서 실행해봄.

 

6. .env 파일 생성 작성

	DATABASE_NAME='DB_Name'
	DATABASE_USERNAME='User_Name'
	DATABASE_HOST='localhost 또는 127.0.0.1'
	DATABASE_PASSSWORD='password'
	DATABASE_PORT=5432

 

7. server.js 생성 코드 작성 및 연결 확인

연결 확인을 위한 코드임. 추후 server.js로 변경됨.

터미널에 node server.js 입력 출력값 또는 localhost:3000 링크 접속하여 확인

연결 확인 완료

 

8. 화면 출력을 위해 Index.html 작성

<html>
    <head>
    <meta charset="UTF-8">
    <title>Accessible Map</title>
    <link rel="stylesheet" type="text/css" href="./node_modules/ol/ol.css" />
    <style>
        #map {
            width: 100%;
            height: 400px;
        }
    </style>
</head>
<body>
    <script src="./main.js"></script>
</body>
</html>

 

9. 화면에 출력할 있게 가공하는 main.js 작성

import { Map, View, Feature } from 'ol';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import { GeoJSON } from 'ol/format.js';
import axios from 'axios';
import { transformExtent, fromLonLat } from 'ol/proj.js';

const app = axios.create({
    baseURL: 'http://localhost:3000'
});

// map 넣어줄 div 생성
const mapDiv = document.createElement("div");
mapDiv.id = "map";
mapDiv.style.width = '100%';
mapDiv.style.height = "400px";
document.body.appendChild(mapDiv);

// 서울의 Bounding Box 좌표 (예시)
const bboxCoords = [126.764088, 37.413294, 127.183971, 37.715133];

// BBox 좌표를 올바른 좌표 체계로 변환
const bboxExtent = transformExtent(bboxCoords, 'EPSG:4326', 'EPSG:3857');

// 서울 영역의 Vector Source 생성
const vectorSource = new VectorSource({
    format: new GeoJSON(),
    loader: async function (extent, resolution, projection) {
        await app.post('/',
            { sql: `SELECT 'Feature' AS type, ST_AsGeoJSON(ST_Transform(way, 4326))::jsonb AS geometry, row_to_json((SELECT p FROM (SELECT name) AS p)) AS properties FROM planet_osm_polygon WHERE ST_Within(ST_Transform(way, 4326), ST_MakeEnvelope(${bboxCoords.join(',')}, 4326))` },
            { headers: { 'Content-Type': 'application/json' } })
            .then((response) => {
                const data = response.data;
                const features = data.rows.map((row) => {
                    const geometry = new GeoJSON().readGeometry(row.geometry);
                    geometry.transform('EPSG:4326', 'EPSG:3857'); // 좌표 변환 추가
                    return new Feature({
                        geometry: geometry,
                        name: row.properties.name
                    });
            });
            this.clear(); // 기존에 추가된 Feature들을 삭제
            this.addFeatures(features);
        })
        .catch((error) => {
            console.log(error);
        });
    },
});

const vectorLayer = new VectorLayer({
    source: vectorSource,
});

const map = new Map({
    layers: [vectorLayer],
    target: mapDiv,
    view: new View({
        center: fromLonLat([127.0, 37.5]), // 초기 중심 좌표 설정
        zoom: 10, // 초기 줌 레벨 설정
        extent: bboxExtent, // 초기 뷰를 BBox 영역으로 설정
      }),
});

// OpenLayers 지도 생성
map.setTarget('map');

 

9. main.js 맞추어 server.js 내용 수정

import express from 'express';
import pg from 'pg';
import dotenv from 'dotenv';
import cors from 'cors';
import path from 'path';

const { Pool } = pg;
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
dotenv.config();

const __dirname = path.resolve();
const port = 3000;

const pool = new Pool({
    user: process.env.DATABASE_USERNAME,
    host: process.env.DATABASE_HOST,
    database: process.env.DATABASE_NAME,
    password: process.env.DATABASE_PASSSWORD,
    port: process.env.DATABASE_PORT,
});

app.get('/', async (req, res) => {
    res.sendFile(__dirname + "/index.html");
});

app.post('/', async (req, res) => {
    const sql = req.body.sql
    let result = null;
    const client = await pool.connect();
    try {
        result = await client.query(sql);
        res.send(result);
    } catch (error) {
        console.error("CONNECTING FAIL");
    } finally {
        await pool.end();
    }
})

app.listen(port, () => {
    console.log(`Server listening at http://localhost:${port}`);
});

 

10. 정상 작동 되는지 확인

back에 해당되는 server 실행
node server.js

front에 해당되는 server 실행
npm start

 

화면에 출력하기 끝!

 

근데, 이걸론 미완성이므로 추가 되는대로 수정할 예정임.

반응형
LIST
댓글
링크
공지사항
최근에 올라온 글