[MySQL] SpringBoot์—์„œ Point, Polygon ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋ฐ” ๊ฐ์ฒด์— ๋‹ด๊ธฐ (with MyBatis)

2025. 2. 16. 19:10ใ†Trouble Shootings/Web

 

์ƒํ™ฉ ์„ค๋ช…

๐Ÿ› ๏ธํ™˜๊ฒฝ
- SpringBoot 3.4.2
- MySQL 8.0.41
- MyBatis 3.0.4

- Liberica JDK 17 LTS

 

 

๋ชจ๋ฐ”์ผ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋˜ ์ค‘, ์ขŒํ‘œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ผ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ง€๋„์—์„œ ์›ํ•˜๋Š” ์œ„์น˜์— ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ฆฌ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ํฐ์„ ๋“ค๊ณ  ํ•ด๋‹น ์˜์—ญ์— ๋“ค์–ด๊ฐ€๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ์ด์—ˆ์ฃ . (+์ง€๋„์—์„œ ์‹œ๊ฐ์ ์œผ๋กœ ํ‘œ์‹œ)

์ง€๋„์— ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ฆฌ๋Š” ์˜ˆ์‹œ (์ถœ์ฒ˜: https://apis.map.kakao.com/web/sample/drawShape)

 

์ €๋Š” RDBMS ๊ธฐ์ˆ  ์Šคํƒ์œผ๋กœ MySQL์„ ์„ ํƒํ•œ ์ƒํ™ฉ์ด์—ˆ๊ณ , MySQL์—๋Š” ์ด๋Ÿฌํ•œ ๊ณต๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…(ex. Point, Polygon)์„ ์ง€์›ํ•˜๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

์š”๊ตฌ์‚ฌํ•ญ์— ๊ณต๊ฐ„์— ๋Œ€ํ•œ ๋ณต์žกํ•œ ์—ฐ์‚ฐ์ด ํ•„์š” ์—†์–ด์„œ ๊ทธ๋ƒฅ ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ์œผ๋กœ ๊ฐ๊ฐ ์œ„๋„ ๊ฒฝ๋„ ์ขŒํ‘œ๋ฅผ ์ €์žฅํ• ๊นŒ๋„ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์ค‘์•™์  ์ขŒํ‘œ๊นŒ์ง€ ์ด 10๊ฐœ์˜ ์ปฌ๋Ÿผ์ด ํ•„์š”ํ•ด์„œ ๊ทธ๋ƒฅ Polygon ํƒ€์ž…์œผ๋กœ ์ €์žฅํ•˜๋Š” ๊ฒŒ ๋” ๊ด€๋ฆฌํ•˜๊ธฐ ์ข‹๊ฒ ๋‹ค๋Š” ํŒ๋‹จ์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

ํ”„๋ก ํŠธ์—์„œ ์ค‘์•™์ ๊ณผ ๊ผญ์ง“์  ์ขŒํ‘œ๋ฅผ ๋ถ„๋ฆฌํ•ด์„œ ๋‹ฌ๋ผ๊ณ  ํ•˜๋”๋ผ๊ตฌ์š”

 

 

โŒํ•˜์ง€๋งŒ ์ž๋ฐ”์—๋Š” ์ด์— ๋Œ€์‘๋˜๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด ์—†๋‹ค

Point์™€ Polygon ํƒ€์ž… ๋ฐ์ดํ„ฐ๋Š” MySQL์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.

-- (๊ฒฝ๋„, ์œ„๋„)
POINT(126.976997, 37.578562),

-- (๊ฒฝ๋„ ์œ„๋„),(๊ฒฝ๋„ ์œ„๋„), ...
-- ์‹œ๊ณ„๋ฐฉํ–ฅ ๋˜๋Š” ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ ์ˆœ์œผ๋กœ ์ขŒํ‘œ๋ฅผ ๋„ฃ์–ด์•ผ ํ•จ (์—ฌ๊ธฐ์„  ์‹œ๊ณ„๋ฐฉํ–ฅ์œผ๋กœ ๋„ฃ์Œ)
-- ๋งˆ์ง€๋ง‰ ์ขŒํ‘œ๋Š” ์ฒซ ์ขŒํ‘œ์™€ ๋™์ผํ•˜๊ฒŒ(๊ทธ๋ž˜์•ผ ๋‹ซํžŒ ๋‹ค๊ฐํ˜•์ด ๋˜๋ฏ€๋กœ)
ST_GeomFromText('POLYGON((126.976712 37.578773,
                          126.977304 37.578748,
                          126.977276 37.578246,
                          126.976673 37.578266,
                          126.976712 37.578773))')

 

ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์žˆ๋˜ ๊ฒŒ, ์ €๋Š” ์ €์žฅํ•œ ๋ฐ์ดํ„ฐ ๊ฐ’๋“ค๋งŒ ์ž˜ ๊ฐ€์ ธ์™€์„œ DTO์— ๋‹ด์•„ ํ”„๋ก ํŠธ๋กœ ๋ณด๋‚ด์ฃผ๊ธธ ์›ํ–ˆ๋Š”๋ฐ, ๊ทธ๋Ÿฌํ•œ ๊ธฐ๋Šฅ์€ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™๋”๋ผ๊ตฌ์š”. ๊ทธ๋ž˜์„œ Point, Polygon ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ฝ์–ด์™€์„œ ํŒŒ์‹ฑ(parsing)ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

โœ…"Point, Polygon" โ†’ "Double" Parser ๋งŒ๋“ค๊ธฐ

SpringBoot์—์„œ๋Š” Point, Polygon ๊ฐ’์„ ์šฐ์„  ๋ฌธ์ž์—ด(String)๋กœ ์ฝ์–ด์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ST_AsText(mp.center_point) as center_point,
ST_AsText(mp.edge_points) as edge_points,

ST_AsText()๋กœ ์ฝ์–ด์˜ค๋Š” ๊ฒฐ๊ณผ๊ฐ’๋“ค

 

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๋ฌธ์ž์—ด์—์„œ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์ขŒํ‘œ ๊ฐ’๋“ค๋งŒ ์™์™ ๋นผ๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Point ๋ฐ์ดํ„ฐ ํƒ€์ž…์˜ ๊ฒฝ์šฐ, "POINT(๊ฒฝ๋„ ์œ„๋„)" ํ˜•์‹์œผ๋กœ ๋ฌธ์ž์—ด์ด ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋งž์ถฐ์„œ ๊ฒฝ๋„์™€ ์œ„๋„ ์ขŒํ‘œ ๊ฐ’์„ ๋นผ๋ƒ…๋‹ˆ๋‹ค.

// ์ค‘์•™์ ("POINT(๊ฒฝ๋„ ์œ„๋„)") parsing
private Double[] paresPoint(String pointStr) {
    if (pointStr == null)  return null;
    
    // 1. ๋ถˆํ•„์š”ํ•œ ๋ฌธ์ž๋“ค์€ ์ „๋ถ€ ์—†์• ์ฃผ๊ณ ,
    String coords = pointStr.replace("POINT(", "").replace(")", "");
    // 2. ๊ณต๋ฐฑ์„ ๊ธฐ์ค€์œผ๋กœ ๊ฐ’๋“ค์„ ์ถ”์ถœ
    String[] coordinates = coords.split(" ");
    return new Double[] {Double.parseDouble(coordinates[1]), 
                         Double.parseDouble(coordinates[0])};
}

 

Polygon ํƒ€์ž…๋„ ์ด์™€ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

// ๊ฐ€์žฅ์ž๋ฆฌ ์ ๋“ค parsing
private List<Double[]> parsePolygon(String polygonStr) {
    if (polygonStr == null) return null;

    // "POLYGON((๊ฒฝ๋„1 ์œ„๋„1,๊ฒฝ๋„2 ์œ„๋„2,...))" ํ˜•์‹ ํŒŒ์‹ฑ
    String coords = polygonStr.replace("POLYGON((", "").replace("))", "");
    List<Double[]> points = Arrays.stream(coords.split(",")).map(String::trim)
                   .map(pointStr -> { String[] coordinates = pointStr.split(" ");
                   return new Double[] {Double.parseDouble(coordinates[1]), Double.parseDouble(coordinates[0])};
                 }).collect(Collectors.toList());

    // ๋งˆ์ง€๋ง‰ ์ขŒํ‘œ๋Š” ๋งจ ์ฒ˜์Œ๊ณผ ๊ฐ™์•„์„œ ์ œ์™ธ
    if (!points.isEmpty()) {
        points.remove(points.size() - 1);
    }

    return points;
}

 

 

728x90
๋ฐ˜์‘ํ˜•