๊ธ์ ์ฝ๊ธฐ ์
ํ์ฌ ์ฐ์ํํ
ํฌ์ฝ์ค์์ ์งํํ๊ณ ์๋ '๋ฐ์ธ๊ถ' ํ๋ก์ ํธ์์ ์์ฑ ๋ก์ง์ ์ด๋ป๊ฒ ๊ฐ์ ํ ์ง ๊ณ ๋ฏผํ๋ ๊ณผ์ ์ ๋ด์ ๊ธ์ด๋ค.
๊ธ์ ์ฝ๊ธฐ ์ ์ ์ดํด๋ฅผ ๋๊ธฐ์ํด ํ๋ก์ ํธ์ ๋ํด ๊ฐ๋ตํ๊ฒ ์๊ฐํ์๋ฉด, ํ์ฌ ๋ฐ์ธ๊ถ์ ์ฃผ๋ณ ๋ฌ๋ ์ฝ์ค๋ฅผ ์ฝ๊ฒ ์ฐพ์ ์ ์๋๋ก ๋์์ฃผ๋ ์๋๋ก์ด๋ ์ฑ์ด๋ฉฐ ์ด๋ฌํ ๋ฌ๋ ์ฝ์ค๋ฅผ ๊ตฌ์ฑํ๋ ๋๋ฉ์ธ ๊ฐ์ฒด๋ ๋ค์๊ณผ ๊ฐ์ด Course, Segment, GeoLine, Coordinate๊ฐ ์๋ค.
`Course`๋ ๋ฌ๋ ์ฝ์ค๋ฅผ ์๋ฏธํ๊ณ , `List<Segment>`๋ฅผ ๊ฐ์ง๋ค. ๊ทธ๋ฆฌ๊ณ `Segment`๋ ๊ฒฝ์ฌ๋์ ๊ด๋ จํ ์ ๋ณด๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ค์ด๊ณ , ์ด๋ค์ ๋ค์ `List<GeoLine>`์ ๊ฐ๋๋ค. `GeoLine`์ ์งํ๋ฉด์ ์ด๋ ํ ์ ์ ๊ฐ๋
์ ์ผ๋ก ํํํ ๊ฒ์ด๋ฉฐ, 2๊ฐ์ `Coordinate`๋ฅผ ๊ฐ์ง๋ค.
์์ฑ ๊ด๋ จ ์ฑ
์์ ์ด๋ป๊ฒ ํ ๊น?
public Course(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
this.id = null;
this.name = new CourseName(name);
this.roadType = roadType;
List<Coordinate> coordinates = CoordinateBuilder.fromRawCoordinates(rawCoordinates)
.removeSimilar()
.smooth()
.build();
List<GeoLine> geoLines = GeoLineBuilder.fromCoordinates(coordinates)
.build();
this.segments = SegmentBuilder.fromGeoLines(geoLines)
.mergeSameElevationDirection()
.mergeSameInclineType()
.build();
this.length = calculateLength(segments);
this.inclineSummary = InclineSummary.of(segments);
this.difficulty = Difficulty.fromLengthAndRoadType(length(), roadType);
}
Builder ํจํด์ผ๋ก ์์ฑํ๊ฒ ๋ ๊ณ๊ธฐ
์ฒ์์๋ ๊ฐ ๋๋ฉ์ธ ๊ฐ์ฒด์ ์์ฑ ๊ด๋ จ ์ฑ
์์ ์ฃผ๊ณ ์ด๋ฅผ ๊ฐ์ ์์ฑํ๋๋ก ํ๋ค. ๊ทผ๋ฐ, ์์ฑ ๋ก์ง์ด ๋๋ฌด ๋ณต์กํด์ง ๋งํผ ๊ทธ๋๋ก ๋๊ธฐ์๋ ๋ค๋ฅธ ์ค์ํ ๋๋ฉ์ธ ๋ก์ง๋ค์ด ์ ๋ณด์ด์ง ์์๋ค. ๊ทธ๋์ ์ด๋ฌํ ์์ฑ ๋ก์ง์ ์ข ๋ถ๋ฆฌํ๊ณ ์ ํ๊ณ ๊ทธ ๋์์ผ๋ก Builder ํจํด์ ํ์ฉํ๋ ๊ฒ์ด๋ค.
ํ์ง๋ง, ํ์ฌ ์์ฑ ์ฑ
์์ด ๋๋ฌด ํผ์ฌํด ์๋ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ฆ.
๊ทธ๋ฆฌ๊ณ Course์์๋ ์ฌ์ค Segment์ ์กด์ฌ๋ง ์๋ฉด ๋๋๋ฐ Coordinate, GeoLine์ ์กด์ฌ๋ ์์์ผํ๋ค. ์ฌ์ง์ด ์ด๋ค์ ์์ฑํ๋๊ฒ CoordinateBuilder, GeoLineBuilder์์ ์๊ณ ์์ด์ผ ํ๋ค. SegmentBuilder, CoordinateBiuilder์ ๊ฒฝ์ฐ์๋ ๋ฉ์๋์ ํธ์ถ ์์๋ ์๊ณ ์์ด์ผ ํ๋ค.
Course ์์ฑ์์์ ๊ฐ๋ ์ฑ
์์ด ๋๋ฌด ๊ฑฐ๋ํ ๊ฒ ๊ฐ๋ค.
Builder ํจํด์ ๋ํ ์๊ฐ
Builder ํจํด์ ๋ชฉ์ ์์ฒด๋ ๊ฐ์ฒด์ ๋ณต์กํ ์์ฑ ๊ณผ์ ๋ฐ ๋ง์ ํ๋ผ๋ฏธํฐ๋ค์ ๋งคํํ๋ ๊ณผ์ ๋ค์ ๋จ์ํ ํ๊ธฐ ์ํ ํจํด์์ ์๋ค.
์ฐ๋ฆฌ ๋๋ฉ์ธ ๋ก์ง์ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ด ๋ณต์กํ๋ค. โ
์ด๊ฑด ์ธ์
๊ทผ๋ฐ Builder ํจํด์ ๊ถ๊ทน์ ์ธ ๋ชฉํ๋ ‘์ ํ์ ์ธ’ ์์ฑ(์ ์ฐํ ์กฐํฉ)์ด ๊ฐ๋ฅํ๋๋ก ํ๋ ๊ฒ์ด๋ค. ์์๋ก ์์ฌ ์ผ์ ํ๋ฅผ ๋ง๋ ๋ค๊ณ ํ๋ฉด ๋๊ตฐ๊ฐ๋ ์ ์ฌ ์์ฌ, ์ ๋
์์ฌ๋ง ์ฃผ์
ํ์ฌ ์์ฑํ๊ณ ์ถ์ ์ ์๊ณ , ๋๊ตฐ๊ฐ๋ ์์นจ, ์ ์ฌ, ์ ๋
์์ฌ ๋ชจ๋ ๋ฃ์ด ์์ฑํ๊ณ ์ถ์ ์ ์๋ค.
๊ทธ๋ฐ ๊ด์ ์์ ์ฐ๋ฆฌ ๋๋ฉ์ธ์ Builder ํจํด์ ‘์ ํ์ ์ธ’ ์์ฑ์ด ํ์ํ๊ฐ? ์ด ๋ถ๋ถ์ โ
ํญ์ ๊ฐ์ ์์์ ํ์์ผ๋ก ์์ฑํ๊ณ ์์. ๊ทธ๋ผ Builder ํจํด์ ๋ค์ด๋ฐ์ ๋ฐ๋ผ๊ฐ ํ์๊ฐ ์๋?
๊ธฐ์กด ์์ฑ์ ๋ก์ง์ ๋จ์ํ ํ๊ณ ์ด์ ๋ํ ์์ฑ ์ฑ
์์ Factory, Creator ๋ฑ.. (๋ค์ด๋ฐ์ ์์ )๋ก ๋๊ฒจ ๋ ๋ช
ํํ๊ฒ ํ์!
๊ทธ๋ผ Factory ํจํด์ ๋ญ๋ฐ
Factory ํจํด์ ์์ฑ ์ฑ
์์ ์ถ์ํ ํ๊ณ ์ ๋ง๋ค์ด์ง ํจํด์ด๋ค. ๊ทผ๋ฐ ์ฌ์ค GoF ์ ์์ ์ํ๋ฉด ์ฌ๊ธฐ์ ํด๊ฒฐํ๊ณ ์ ํ๋ ๊ฐ์ฒด์ ๋ณต์กํ ์์ฑ ๊ณผ์ ์ ์ถ์ํ ํ๋ค๊ธฐ๋ณด๋ค ํด๋ผ์ด์ธํธ ์
์ฅ์์ ์ฌ๋ฌ ๊ตฌํ์ฒด๋ค์ ์ ํํด์ผ ํ๋ ์ฝ๋๋ฅผ ์ถ์ํ ํ ๊ฒ ์ฆ, ๊ฐ์ฒด ์์ฑ์ ์ฑ
์์ ์ถ์ํ ํ ๊ฒ์ด๋ค.
ํจํด์ ๋๋ฌด ๋งค๋ชฐ๋์ง ๋ง์
๊ฒฐ๊ตญ ๋ด๊ฐ ํ๊ณ ์ถ์๊ฑด ์์ฑ์ ๋ก์ง ๋จ์ํ + ์์ฑ ์ฑ
์ ๋ช
ํํ๊ฒ ๋ถ๋ฆฌ
๊ฐ์ ํ๊ฒ ๋ ๊ฒ
public Course(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
this.id = null;
this.name = new CourseName(name);
this.roadType = roadType;
List<Coordinate> coordinates = CoordinateBuilder.fromRawCoordinates(rawCoordinates)
.removeSimilar()
.smooth()
.build();
List<GeoLine> geoLines = GeoLineBuilder.fromCoordinates(coordinates)
.build();
this.segments = SegmentBuilder.fromGeoLines(geoLines)
.mergeSameElevationDirection()
.mergeSameInclineType()
.build();
this.length = calculateLength(segments);
this.inclineSummary = InclineSummary.of(segments);
this.difficulty = Difficulty.fromLengthAndRoadType(length(), roadType);
}
๊ธฐ์กด์๋ Course๊ฐ segments๋ฅผ ๋ง๋ค๊ธฐ ์ํด์ coordinates๋ ๋ง๋ค๊ณ , geoLines๋ ๋ง๋ค๊ณ ์์์. ๊ทธ๋ฆฌ๊ณ ํด๋น ๊ฐ์ฒด๋ค์ ๋ง๋ค๊ธฐ ์ํด์ ์์ฑ ์์๊น์ง ๊ธฐ์ตํ๊ณ ์์๋ค. ํ์ง๋ง, Course๋ ์ด๋ฌํ ์ฌ์ค์ ์๊ณ ์์ ํ์๊ฐ ์๋ค. ๊ทธ๋ฌ๋ฉด ์ด๋ฌํ ์์ฑ ๋ก์ง๋ค์ ๋ ์ถ์ํ ํ๋๊ฒ ๋ง์ง ์์๊น?
public Course(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
this.id = null;
this.name = new CourseName(name);
this.roadType = roadType;
**this.segments = SegmentFactory.create(rawCoordinates);**
this.length = calculateLength(segments);
this.inclineSummary = InclineSummary.of(segments);
this.difficulty = Difficulty.fromLengthAndRoadType(length(), roadType);
}
public class SegmentFactory {
public static List<Segment> create(List<Coordinate> rawCoordinates) {
List<Segment> rawSegments = GeoLineFactory.create(rawCoordinates).stream()
.map(GeoLine::toSegment)
.toList();
List<Segment> mergedSegments = mergeSameElevationDirection(rawSegments);
return mergeSameInclineType(mergedSegments);
}
private static List<Segment> mergeSameElevationDirection(List<Segment> segments) {
// ...
}
private static List<Segment> mergeSameInclineType(List<Segment> segments) {
// ...
}
}
public class GeoLineFactory {
public static List<GeoLine> create(List<Coordinate> rawCoordinates) {
List<Coordinate> coordinates = CoordinateFactory.create(rawCoordinates);
// ...
return lines;
}
}
public class CoordinateFactory {
public static List<Coordinate> create(List<Coordinate> rawCoordinates) {
List<Coordinate> nonSimilarCoordinates = removeSimilar(rawCoordinates);
List<Coordinate> coordinates = smooth(nonSimilarCoordinates);
validateValidCoordinateSize(coordinates);
return coordinates;
}
private static void validateValidCoordinateSize(List<Coordinate> rawCoordinates) {
if (rawCoordinates.size() < 2) {
throw INVALID_COORDINATE_COUNT.create(rawCoordinates.size());
}
}
private static List<Coordinate> removeSimilar(List<Coordinate> rawCoordinates) {
// ...
}
private static List<Coordinate> smooth(List<Coordinate> rawCoordinates) {
// ...
}
}
๊ทธ๋์ Builder ๋ค์ด๋ฐ์ ์ ๊ฑฐํ๊ณ Factory๋ก ๋ณ๊ฒฝํ์ผ๋ฉฐ ๊ฐ ์์ฑ ๋ก์ง๋ค์ ์ถ์ํ ํ๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก Course์์๋ ๋ ์ด์ Coordinate, GeoLine, Segment์ ์์ฑ ๋ฐฉ์์ ๊ถ๊ธํด ํ์ง ์๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ Factory ๊ฐ์ฒด๋ค์ด Course → Segment → GeoLine → Coordinate๋ก ๋ง๋ค์ด์ง ๋๋ฉ์ธ ๊ตฌ์กฐ์ ๋์ผํ๊ธฐ ๋๋ฌธ์ ์ดํดํ๊ธฐ๊ฐ ์ฌ์์ก๋ค.
์์ฌ์ด ์ ์ Factory๋ผ๋ ๋ค์ด๋ฐ์ธ๋ฐ, ์ด๋ฅผ ํ ๋ด์์ ํฉ์ํ๋ค๋ฉด ํด๋น ๋ค์ด๋ฐ์ ๊ทธ๋๋ก ์ฌ์ฉํ๊ณ ์๋๋ผ๋ฉด ๋ค๋ฅธ ๋ค์ด๋ฐ์ ๊ณ ๋ฏผํด๋ณด๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค.
์์ฑ ๋ก์ง์ ๋ํ ๊ณ ๋ฏผ

ํ์ฌ ๋๋ฉ์ธ์ `Course` → `Segment` → `GeoLine` → `Coordinate`์ ๊ตฌ์กฐ๋ก ๋ง๋ค์ด์ ธ์๋ค.
`GeoLine`, `Coordinate`๋ค์ `Course`์ ์ฑ์ง์ด ๋ค๋ฅด๋ค. ์ขํ๋ ๋ถ๋๋ฌ์ธ ํ์๊ฐ ์๊ณ , ์ขํ๋ค ๊ฐ์ ๊ฑฐ๋ฆฌ๊ฐ ๋จผ ๊ฒ๋ ์๊ด์๋ค. ์ธ๊ทธ๋จผํธ๋ค์ ๊ฒฝํฅ์ฑ์ด ๊ฐ๋ค๊ณ ํฉ์ณ์ง ํ์๋ ์๋ค. ‘์ฝ์ค’๋ผ๋ ๋ฒ์ ์์์ ์ดํดํ ๋ ์๋ฏธ๋ฅผ ๊ฐ๋ ๊ฒ์ ๋ง๋ค. ๊ฒ๋ค๊ฐ ์ฝ์ค๋ฅผ ๊ตฌ์ฑํ๋ ์ขํ๋ค๋ง์ด ๋ถ๋๋ฌ์์ผ ํ๊ณ , ๊ฑฐ๋ฆฌ๊ฐ ์งง์์ผ ํ๊ณ , ๊ฒฝํฅ์ฑ์ ํฉ์ณ์ ธ์ผ ํ๋ค. ๋ง๋ ๋ง์ด๋ค.
ํ์ง๋ง, ์กฐ๊ธ ์์ํ ์ ์ `GeoLine`, `Coordinate` ๋ ๋ชจ๋ ‘์ฝ์ค’๋ผ๋ ๋ฒ์ ๋ด์์ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ค์ด๋ค. ๊ทธ๋ ๋ค๋ฉด ํ์๋ค ๊ฐ์ ๊ทธ๋ฌํ ์ ์ ๊ณต์ ํ๊ณ ์๋ ์ํฉ์์ ์์ฑ ์ ์ขํ๋ค์ด ๋ถ๋๋ฌ์์ง๊ณ , ๊ฑฐ๋ฆฌ๊ฐ ๋จผ ๊ฒ์ ๋ณด์ ํ๋ ๋ก์ง์ `GeoLine`, `Coordinate` ์ชฝ์ผ๋ก ์ฎ๊ฒจ๋ ๋ฌธ์ ์์ง ์์๊น? ์คํ๋ ค `Course` ์ ๋๋ฌด ๋ง์ ๋ก์ง๋ค์ ๋ด๊ณ ์๋๊ฑด ์๋๊น? `Course`์์๋ง ์๋ฏธ๋ฅผ ๊ฐ์ง๋ค๊ณค ํ์ง๋ง, ์ด ๋๋ฉ์ธ์ ๋ง๋ค๋ `Segment`, `GeoLine`, `Coordinate`๋ ๋ชจ๋ ๊ฐ์ ๋งฅ๋ฝ์์ ๋์จ ๊ฐ์ฒด๋ค์ด๋ค.
์ด๋ ๊ฒ ์๊ฐํ๋ฉด ํ๋์ ๊ฐ๋ฆผ๊ธธ์ด ๋์ค๋ ๊ฒ ๊ฐ๋ค.
- `Course` ์ธ์ ํ์ ๊ฐ์ฒด๋ค์ ์์ํ๊ฒ ‘์ง๋ฆฌ์ ์ ’, ‘์ง๋ฆฌ์ ์ ’์ ์ญํ ๋ก ๋ณผ ๊ฒ์ธ๊ฐ?
๋ง์ฝ ์์ํ ์ง๋ฆฌ์ ์ , ์ ์ ์ญํ ๋ก ๋ณธ๋ค๋ฉด ์์ฑ ๋ก์ง๋ค์ `Course`์ ๋ถ๋ฆฌ๋๋ ๊ฒ์ด ๋ง๋ค. ํ์ง๋ง, ๊ทธ๋ฐ๊ฒ ์๋๋ผ `GeoLine`, `Coordinate`, `Segment`๋ ์ด๋์ ๋ ๋๋ฉ์ธ ๋ก์ง์ ํฌํจํ ์ ์๋ ์กด์ฌ๋ค๋ก ๋ณธ๋ค๋ฉด ์์ฑ ๋ก์ง์ ๊ฐ์๊ฐ ๋ถ๋ดํ๋ ๊ฒ์ด ๋ง๋ ๊ฒ ๊ฐ๋ค.
์ด๋ฐ ๋งฅ๋ฝ์ ๊ณ ๋ คํ์ ๋ ๋๋ ๋ณดํต ํ๋์ ๊ธฐ์ค์ผ๋ก ๊ฒฐ์ ํ๋ ๊ฒ ๊ฐ๋ค. ๋ฐ๋ก `์ฌ์ฌ์ฉ์ฑ`์ด๋ค. ๋ค๋ฅธ ํ๋ก์ ํธ์ ์ฌ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๊ฑด๋๋ฐ๊ณ , ํ์ฌ ํ๋ก์ ํธ์์ `Course`๊ฐ ์๋ ๊ฐ์ฒด๋ค์ ์ฌ์ฌ์ฉํ๋ ์ผ์ด ์๋? ํน์ ์์๊น? ์ง๊ธ ๋น์ฅ์ด๋ผ๋ฉด ํ๋ก์ ํธ์์๋ ์๋ค. `Course` ์ธ์ ํ์ ๊ฐ์ฒด๋ค์ ์ฌ์ฉ๋๋ ์ผ์ด ์๋ค.
๊ทธ๋ ๋ค๋ฉด, ์ถํ์ ์ฌ์ฌ์ฉ๋ ์ผ์ด ์์๊น? ๊ฝค ์์ ๊ฒ์ด๋ค. ์๋ฅผ ํ๋ ๋ค๋ฉด ํ์ฌ๋ `Course` ๋จ์๋ก ๋ฌ๋ ์ฝ์ค๋ฅผ ์ธ์ํ๊ณ ์์ง๋ง ๋์ค์ `Segment` ๋จ์๋ก ๋ฌ๋ ์ฝ์ค๋ฅผ ์ธ์ํ๊ณ ๊ฐ `Segment`๋ง๋ค์ ์ฌ์ฉ์๋ณ ๊ธฐ๋ก์ ๊ธฐ๋กํ๋ ๊ฒฝ์ฐ๊ฐ ์์ ๊ฒ ๊ฐ๋ค. ์ค์ ๋ก Strava์์๋ ํด๋น ๋ฐฉ์์ผ๋ก ๋ฌ๋ ์ฝ์ค๋ฅผ ์ธ์ํ๊ณ ์๋ค. ํ์ง๋ง ๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ๊ฒฝํฅ์ฑ์ ํฉ์น๊ณ , ์ขํ๋ฅผ ๋ณด์ ํ๋ ์ด๋ฐ ๋ก์ง๋ค์ ๋ชจ๋ ์ดํ๋ฆฌ์ผ์ด์
์์ ํ์ํ๊ธฐ ๋๋ฌธ์ ๋ง๋ค์ด์ง ๋ก์ง๋ค์ด๋ค. ๊ทธ๋์ `Segment` ๋จ์๋ก ๋ฌ๋์ฝ์ค๋ฅผ ์ธ์ํด๋ ์ฌ์ ํ ์ฌ์ฉ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ๋ก์ง๋ค์ด๋ค.
๊ทธ๋ผ ๊ฒฐ๊ตญ ๊ฐ ๋๋ฉ์ธ ๊ฐ์ฒด๋ค์ด ๊ฐ์ ์์ฑ ๋ก์ง์ ๊ฐ๊ณ ์๋๊ฒ ๋ง๋? ์ฌ์ค ๊ทธ๊ฑด ์๋๋ผ๊ณ ์๊ฐํ๋ค. ๋๋ ‘์ฝ์ค’๋ผ๋ ๋ฒ์ ๋ด์์ ์๋ฏธ๋ฅผ ๊ฐ๊ฒ๋๋ ๋ก์ง์ด๋ผ๋ ํ์์ ์๊ฒฌ์ ๋์ํ๋ ๋ฐ์ด๋ค. ๊ทธ๋์ ์ข ๋ ์ฝ๋์ ์ผ๋ก ๋ฌธ์ ๋ฅผ ๋ฐ๋ผ๋ณผ ํ์๊ฐ ์์ ๊ฒ ๊ฐ๋ค.
public Course(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
// ...
List<Coordinate> coordinates = CoordinateBuilder.fromRawCoordinates(rawCoordinates)
.removeSimilar()
.smooth()
.build();
List<GeoLine> geoLines = GeoLineBuilder.fromCoordinates(coordinates)
.build();
this.segments = SegmentBuilder.fromGeoLines(geoLines)
.mergeSameElevationDirection()
.mergeSameInclineType()
.build();
// ...
}
ํ์ฌ ๋ฌธ์ ๊ฐ ๋๋ ์ง์ ์ด๋ค. ์ข ๋ ๋ช
ํํ๊ฒ ๋ฌธ์ ๋ฅผ ์ ์ํ์๋ฉด ‘์์ฑ ์ฑ
์ ์ค ์์ฑ ๋ฐฉ์์ Course์ ๋ ๊ฒ์ด๋ ์๋๋ฉด ์ถ์ํ ํ ๊ฒ์ด๋’์ด๋ค. ์ฝ๋๋ฅผ ๋ณด๋ฉฐ ์๋นํ ๋ง์ ๊ณ ๋ฏผ์ ํด๋ดค๋๋ฐ, ๊ฒฐ๋ก ์ Course์ ๋๋ ๊ฒ์ด ์ข๋ค. ์ด๋ ๊ฒ ์๊ฐํ๊ฒ ๋ ๊ฐ์ฅ ํฐ ์ด์ ๋ ์ฝ๋์ ํํธํ ๋๋ฌธ์ด๋ค.
์๋ก์ด ์ ์
๊ฐ๋ฐ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํ์. ์ฝ์ค๋ฅผ ์ด๋ป๊ฒ ์์ฑํ๋์ง ๊ถ๊ธํด์ ์์ฑ์๋ฅผ ๋ดค๋๋ฐ, ๊ฐ ์ขํ๋ค์ SegmentFactory์์ ์ฒ๋ฆฌํ๊ณ ์๋ ๊ฒ์ ๋ดค๋ค. ๊ทธ๋์ ํด๋น ํฉํ ๋ฆฌ์ ๋ค์ด๊ฐ๋๋ ๋ GeoLineFactory๋ฅผ ํธ์ถํ๊ณ ์๋ค. ๊ทธ๋ฌ๋ฉด ๋ ํ๋ฒ ๋ ๋ค์ด๊ฐ๋์์ผ๋ก ์ฝ์ค๊ฐ ์์ฑ๋๋ ๊ณผ์ ์ ์ซ์๊ฐ์ผ ํ๋ค. ์ด ๊ณผ์ ์์ ๋ง์ฝ ์ปจํ
์คํธ๋ฅผ ๋์น๋ค๋ฉด ์ด๋ฅผ ๋ค์ ํ์ธํ๋๋ฐ ์ด๋ ค์์ ๊ฒช์ ๊ฒ์ด๋ค. ํ์ง๋ง ์ง๊ธ์ ๊ตฌ์กฐ๋ ์ถฉ๋ถํ ๊ทธ ์ปจํ
์คํธ๋ฅผ ์์ง์๊ณ ์ ์งํ๋ฉฐ ์ฝ๋๋ฅผ ์ฝ์ ์ ์๋ค. ์ฝ์ค๊ฐ ์ขํ๋ฅผ Segment๋ก ๋ง๋๋ ๊ณผ์ ์ด ํ ๋์ ๋ณด์ด๋ ๋ง์ด๋ค. ์ฆ, ์ ์ง๋ณด์ํ๊ธฐ๊ฐ ํธํด์ง๋ค.
๋ ๋ฒ์งธ๋ก๋ ์ ๋ณด ์ ๋ฌธ๊ฐ์ ๊ด์ ์ด๋ค. Course๋ Segment, GeoLine, Coordinate๊ฐ ์์ฑ๋๊ธฐ ์ํด ํ์ํ ์ ๋ณด๋ฅผ ๋ชจ๋ ๊ฐ์ง๊ณ ์๋ค. ์ฆ, Course๋ ๊ฐ ํ์ ๊ฐ์ฒด๋ค์ ์ ๋ณด ์ ๋ฌธ๊ฐ์ด๋ค. ๊ทธ๋์ ๊ฐ ํ์ ๊ฐ์ฒด๋ค์ ์์ฑ ์ฑ
์์ ๊ฐ๋ ๊ฒ์ด ํ๋ฆ์ ์์ฐ์ค๋ฝ๋ค.
๊ทธ๋์ ์๊ฐ์ ๋ฐ๊ฟจ๋ค. ํ์ง๋ง ์ฌ์ ํ ์์ฑ์๊ฐ ๋น๋ํ ๊ฒ์ ๋ง๋ค๊ณ ์๊ฐํ๋ค. ์๋ฅผ ๋ค์ด ์์ฑ์๊ฐ ๊ถ๊ธํด์ ๋ค์ด์๋๋ฐ, ์์ง์ ๊ถ๊ธํ์ง ์์ ์ขํ ์ฒ๋ฆฌ ๊ณผ์ ์ ๋ด์ผํ๋ค๋ฉด ์กฐ๊ธ ํผ๊ณคํ ๊ฒ์ด๋ค. ๊ทธ๋์ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ํ ์ ์์ ๊ฒ ๊ฐ๋ค.
// 1๋ฒ
public Course(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
this.id = null;
this.name = new CourseName(name);
this.roadType = roadType;
this.segments = refineCoordinates(rawCoordinates);
this.length = calculateLength(segments);
this.inclineSummary = InclineSummary.of(segments);
this.difficulty = Difficulty.fromLengthAndRoadType(length(), roadType);
}
private List<Segment> refineCoordinates(List<Coordinate> rawCoordinates) {
List<Coordinate> coordinates = CoordinateBuilder.fromRawCoordinates(rawCoordinates)
.removeSimilar()
.smooth()
.build();
List<GeoLine> geoLines = GeoLineBuilder.fromCoordinates(coordinates)
.build();
reutrn SegmentBuilder.fromGeoLines(geoLines)
.mergeSameElevationDirection()
.mergeSameInclineType()
.build();
}
```
```java
// 2๋ฒ
public static create(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
List<Coordinate> coordinates = CoordinateBuilder.fromRawCoordinates(rawCoordinates)
.removeSimilar()
.smooth()
.build();
List<GeoLine> geoLines = GeoLineBuilder.fromCoordinates(coordinates)
.build();
List<Segment> segments = SegmentBuilder.fromGeoLines(geoLines)
.mergeSameElevationDirection()
.mergeSameInclineType()
.build();
return new Course(name, roadType, segments);
}
private Course(String name, RoadType roadType, List<Segment> segments) {
this.id = null;
this.name = new CourseName(name);
this.roadType = roadType;
this.segments = segments;
this.length = calculateLength(segments);
this.inclineSummary = InclineSummary.of(segments);
this.difficulty = Difficulty.fromLengthAndRoadType(length(), roadType);
}
ํนํ 1๋ฒ ์ฝ๋๊ฐ ํ์ฌ ๊ธฐ์ค์ผ๋ก ์ต์ ์ด๋ผ๊ณ ์๊ฐํ๋ค. ํ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ด ๋ชจ๋ ์์ฑ์๋ฅผ ํตํด ์์ฑํ๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ฒ ๋ฉ์๋๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์์ฑ์ ์์์ ๋งฅ๋ฝ์ ๋ณํ๋ฅผ ์ฃผ๊ธฐ๋ ํ๊ณ , ์ด๋ค ๋ฐฉ์์ผ๋ก Segment๊ฐ ์์ฑ๋๋์ง ๊ถ๊ธํ๋ค๋ฉด `refineCoordinates`๋ง ํ์ธํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๊ฒฐ๋ก
์ด๋ฒ ๊ธฐํ์ ํ๋ก์ ํธ ๋๋ฉ์ธ์ ๋ํด์ ๋ค์ ํ๋ฒ ๊น๊ฒ ๊ณ ๋ฏผํ๋ ๊ณ๊ธฐ๊ฐ ๋์๋ค.
๊ธฐ์กด์๋ Course์์ ์๋ฏธ๋ฅผ ๊ฐ๋๋ผ๋ ๊ฐ์ ๋งฅ๋ฝ์์ ๋์จ ๋๋ฉ์ธ ๊ฐ์ฒด๋ผ๋ฉด ํด๋น ๋งฅ๋ฝ์ ๊ฐ์ง์ฑ ๊ฐ์์ ์ฑ ์์ ๊ฐ์ง๋ ๊ฒ์ด ๋ ์ข์ ๋ฐฉํฅ์ด๋ผ๊ณ ์๊ฐํ์๋ค. ํ์ง๋ง, ์์นซ ๊ณผ๋ํ๊ฒ ์ฑ ์์ ๋๋๊ฒ ๋๋ฉด ์คํ๋ ค ์ ์ง๋ณด์ ํ๊ธฐ ํ๋ ์ฝ๋๊ฐ ๋ ์ ์๋ค๋ ๊ฒ์ ์๊ฒ๋์๋ค. ๋ญ๊ฐ ์ข ์ถ์์ ์ธ ๊ฑฐ ๊ฐ๋ค.
๊ทธ๋์ ๋ค์ ํ๋ฒ ์์ ์์ ๋ก ์ ๋ฆฌํ๋ฉด Course์์ Segment, Coordinate์ ๋ณ๊ฒฝ์ ํ๋ค๋ ์ ์ด ๋ด๊ฒ ๋ถํธํจ์ผ๋ก ๋ค๊ฐ์์๋ค. ๊ทธ๋์ Segment, Coordinate, GeoLine ์ด๋ค์ด ์๋ก Course์์ ์ด๋ค์ง๋ ์ฑ ์์ ๊ฐ๋ ๊ฒ์ด ๋ ์ข์ ๋ฐฉํฅ์ด๋ผ๊ณ ์๊ฐํ๋ค. ํ์ง๋ง ํ์์ ๋ง์ฒ๋ผ ํ์ฌ Course์์๋ง Segment, …์ ๋ณด์ ์ด ํ์ํ๋ค. ์ฆ, ์ด๊ฑด Course์ ๋๋ฉ์ธ ๋ก์ง์ด๋ค. ๊ทธ๋์ ๋ค์๊ณผ ๊ฐ์ด ๋ฆฌํฉํ ๋ง์ ์งํํ๋ค.
public Course(String name, RoadType roadType, List<Coordinate> rawCoordinates) {
this.id = null;
this.name = new CourseName(name);
this.roadType = roadType;
this.segments = refineCoordinates(rawCoordinates);
this.length = calculateLength(segments);
this.inclineSummary = InclineSummary.of(segments);
this.difficulty = Difficulty.fromLengthAndRoadType(length(), roadType);
}
private List<Segment> refineCoordinates(List<Coordinate> rawCoordinates) {
List<Coordinate> coordinates = CoordinateBuilder.fromRawCoordinates(rawCoordinates)
.removeSimilar()
.smooth()
.build();
List<GeoLine> geoLines = GeoLineBuilder.fromCoordinates(coordinates)
.build();
reutrn SegmentBuilder.fromGeoLines(geoLines)
.mergeSameElevationDirection()
.mergeSameInclineType()
.build();
}
Builder๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ํ๋ก์ ํธ ์ด๊ธฐ์ Segment, Coordinate, GeoLine๋ค์ด ๊ฐ์ ์ด๋ฌํ ์ฑ ์์ ๊ฐ๊ณ ์๋ ์ํ์๊ธฐ์ ๋ ํผ๋์ค๋ฌ์ ๋ ๊ฒ ๊ฐ๋ค. ํ์๋ค๊ฐ์ ์ข์ ํ ๋ก ์ ์งํํ๋ ๊ฒ ๊ฐ์ ์ข๋ค. ๊ทธ๋ฆฌ๊ณ , ํญ์ ์ ๋ต์ ์๋ค๋ ์ ์ ๋ ๊นจ๋ซ๋๋ค.
'๊ฐ๋ฐ > ๋ฐ์ธ๊ถ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| OSRM Match API๋ก ๋ฌ๋ ์ฝ์ค ๋ฐ์ดํฐ ์ขํ ๋ณด์ ํ๊ธฐ (0) | 2025.12.14 |
|---|---|
| ๊ธธ์ฐพ๊ธฐ, ๊ฒฝ๋ก ๋ณด์ ์ ํต์ฌ OSRM ํบ์๋ณด๊ธฐ (0) | 2025.12.08 |
| API ๋ฌธ์ ๊ฐ์ ๊ณผ ๋ฌธ์ํ ํด Stoplight๋ก ๋ณ๊ฒฝํ๊ธฐ (0) | 2025.12.07 |
| ํ๋ก์ ํธ์์ Batch Job ๋ก๊ทธ์ MDC๋ฅผ ์ ์ฉํ๋ค. (0) | 2025.10.26 |
| ์๋ฒ์์ ์ง์์ ์ธ OutOfMemory๊ฐ ๋ฐ์ํ๋ ๋ฌธ์ ํด๊ฒฐ (3) | 2025.09.29 |