์ง€๋„์˜ ๊ฒฝ๊ณ„ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ ๊ทผ์ฒ˜ ์ผ์ž๋ฆฌ ๊ณต๊ณ  ์กฐํšŒ ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ

1. ๊ฐœ์š”

์ง„ํ–‰์ค‘์ธ ํ”„๋กœ์ ํŠธ์—์„œ ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๊ณ  ์žˆ๋Š” ์ง€๋„ ํ™”๋ฉด์— ์ผ์ž๋ฆฌ๋ฅผ ๋„์›Œ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๊ฒŒ๋๋‹ค. 

 

์—์–ด๋น„์—”๋น„ ๊ฐ™์€ ์ˆ™๋ฐ• ์—…์†Œ, ๋„ค์ด๋ฒ„ ๋ถ€๋™์‚ฐ๊ฐ™์€ ๋ถ€๋™์‚ฐ ํ”Œ๋žซํผ์—์„œ๋„ ์‰ฝ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

 

 

์šฐ๋ฆฌ ์„œ๋น„์Šค์—๋„ ์ด์™€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์ด ์žˆ๊ณ , ์•„๋ž˜๋Š” ๊ฐœ๋ฐœ ์ค‘์ธ ์„œ๋น„์Šค์˜ ์ดˆ์•ˆ ๋””์ž์ธ์ด๋‹ค. 

 

๊ฐ ์ผ์ž๋ฆฌ ๋ชจ์ง‘ ๊ณต๊ณ ์—๋Š” ์ด๋ฏธ ์œ„๋„, ๊ฒฝ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ํ•จ๊ป˜ ๊ฐ–๊ณ  ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ˜„์žฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๊ณ  ์žˆ๋Š” ์ง€๋„์˜ ๋ถ๋™์ชฝ, ๋‚จ์„œ์ชฝ ์œ„๋„, ๊ฒฝ๋„๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ ํ›„ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค ์กฐํšŒํ•ด ์˜ฌ ์ƒ๊ฐ์ด๋‹ค. 

 

 

์‚ฌ์‹ค ํ•™์Šต์ด ๊ฝค๋‚˜ ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ์ •๋ฆฌํ•  ๊ฒŒ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ํฌ์Šคํ„ฐ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ํŽธ์ธ๋ฐ ์ด๋ฒˆ์—” ๊ตฌ๊ธ€๋ง ํ–ˆ์„ ๋•Œ ์ž๋ฃŒ๊ฐ€ ๋„ˆ๋ฌด ์—†์–ด์„œ ์ฒ˜์Œ ํ•˜์‹œ๋Š” ๋ถ„๋“ค์ด๊ฒŒ ์กฐ๊ธˆ์ด๋‚˜๋งˆ ๋„์›€์ด ๋˜๊ณ ์ž ์“ฐ๊ณ ์žˆ๋‹ค. 

 

 

 

 

 

2. ์นด์นด์˜ค Map Key ๋ฐœ๊ธ‰

์ง€๋„์˜ ๊ฒฝ๊ณ„ ๋ถ€๋ถ„ ์œ„๋„, ๊ฒฝ๋„๋Š” ํ”„๋ก ํŠธ ํŒ€์ด ์•Œ์•„์„œ ์ž˜ ๋„˜๊ฒจ์ฃผ๊ฒ ์ง€๋งŒ ๊ฐœ๋ฐœ ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์นด์นด์˜ค ๋งต API๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

https://developers.kakao.com/

 

Kakao Developers

์นด์นด์˜ค API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•ด๋ณด์„ธ์š”. ์นด์นด์˜ค ๋กœ๊ทธ์ธ, ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ, ์นœ๊ตฌ API, ์ธ๊ณต์ง€๋Šฅ API ๋“ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

developers.kakao.com

 

  • ์นด์นด์˜ค API ์ ‘์†
  • ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋™
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ถ”๊ฐ€
  • JavaScript ํ‚ค ๋ณต์‚ฌ
  • ํ”Œ๋žซํผ์— ์‚ฌ์šฉํ•  URL ๋“ฑ๋ก

 

 

์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•  ํ‚ค๋Š” JavaScript ํ‚ค ์ด๋‹ค. 

 

 

 

๋งˆ์ง€๋ง‰์œผ๋กœ ํ”Œ๋žซํผ ๋ฉ”๋‰ด์—์„œ URL์„ ๋“ฑ๋ก์‹œ์ผœ์ค˜์•ผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

 

 

 

 

 

 

์•„๋ž˜๋Š” ์นด์นด์˜ค Map์„ ์ƒ์„ฑ ํ›„ ์œ„๋„, ๊ฒฝ๋„๋ฅผ ์ž…๋ ฅํ•ด Center ์œ„์น˜๋ฅผ ์žก๊ณ , ๋ถ๋™์ชฝ ๊ฒฝ๊ณ„, ๋‚จ์„œ์ชฝ ๊ฒฝ๊ณ„์˜ ์œ„๋„, ๊ฒฝ๋„ ์ขŒํ‘œ๋ฅผ ๊ตฌํ•˜๋Š” ๊ฐ„๋‹จํ•œ HTML JS ์ฝ”๋“œ์ด๋‹ค.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script
      type="text/javascript"
      src="http://dapi.kakao.com/v2/maps/sdk.js?appkey=ab9e6700f2bc6a1dee2720143aade0cf"
    ></script>

    <div id="map" style="width: 100%; height: 350px"></div>

    <div id="mapInfo"></div>

    <script>
      var mapContainer = document.getElementById('map'), // ์ง€๋„๋ฅผ ํ‘œ์‹œํ•  div
        mapOption = {
          center: new kakao.maps.LatLng(33.450701, 126.570667), // ์ง€๋„์˜ ์ค‘์‹ฌ์ขŒํ‘œ
          level: 3, // ์ง€๋„์˜ ํ™•๋Œ€ ๋ ˆ๋ฒจ
        };

      var map = new kakao.maps.Map(mapContainer, mapOption); // ์ง€๋„๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค

      // ์ผ๋ฐ˜ ์ง€๋„์™€ ์Šค์นด์ด๋ทฐ๋กœ ์ง€๋„ ํƒ€์ž…์„ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ์ง€๋„ํƒ€์ž… ์ปจํŠธ๋กค์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค
      var mapTypeControl = new kakao.maps.MapTypeControl();

      // ์ง€๋„ ํƒ€์ž… ์ปจํŠธ๋กค์„ ์ง€๋„์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค
      map.addControl(mapTypeControl, kakao.maps.ControlPosition.TOPRIGHT);

      function getInfo() {
        // ์ง€๋„์˜ ํ˜„์žฌ ์ค‘์‹ฌ์ขŒํ‘œ๋ฅผ ์–ป์–ด์˜ต๋‹ˆ๋‹ค
        var center = map.getCenter();

        // ์ง€๋„์˜ ํ˜„์žฌ ๋ ˆ๋ฒจ์„ ์–ป์–ด์˜ต๋‹ˆ๋‹ค
        var level = map.getLevel();

        // ์ง€๋„ํƒ€์ž…์„ ์–ป์–ด์˜ต๋‹ˆ๋‹ค
        var mapTypeId = map.getMapTypeId();

        // ์ง€๋„์˜ ํ˜„์žฌ ์˜์—ญ์„ ์–ป์–ด์˜ต๋‹ˆ๋‹ค
        var bounds = map.getBounds();

        // ์˜์—ญ์˜ ๋‚จ์„œ์ชฝ ์ขŒํ‘œ๋ฅผ ์–ป์–ด์˜ต๋‹ˆ๋‹ค
        var swLatLng = bounds.getSouthWest();

        // ์˜์—ญ์˜ ๋ถ๋™์ชฝ ์ขŒํ‘œ๋ฅผ ์–ป์–ด์˜ต๋‹ˆ๋‹ค
        var neLatLng = bounds.getNorthEast();

        // ์˜์—ญ์ •๋ณด๋ฅผ ๋ฌธ์ž์—ด๋กœ ์–ป์–ด์˜ต๋‹ˆ๋‹ค. ((๋‚จ,์„œ), (๋ถ,๋™)) ํ˜•์‹์ž…๋‹ˆ๋‹ค
        var boundsStr = bounds.toString();

        var message = '์ง€๋„ ์ค‘์‹ฌ์ขŒํ‘œ๋Š” ์œ„๋„ ' + center.getLat() + ', <br>';
        message += '๊ฒฝ๋„ ' + center.getLng() + ' ์ด๊ณ  <br>';
        message += '์ง€๋„ ๋ ˆ๋ฒจ์€ ' + level + ' ์ž…๋‹ˆ๋‹ค <br> <br>';
        message += '์ง€๋„ ํƒ€์ž…์€ ' + mapTypeId + ' ์ด๊ณ  <br> ';
        message +=
          '์ง€๋„์˜ ๋‚จ์„œ์ชฝ ์ขŒํ‘œ๋Š” ' +
          swLatLng.getLat() +
          ', ' +
          swLatLng.getLng() +
          ' ์ด๊ณ  <br>';
        message +=
          '๋ถ๋™์ชฝ ์ขŒํ‘œ๋Š” ' +
          neLatLng.getLat() +
          ', ' +
          neLatLng.getLng() +
          ' ์ž…๋‹ˆ๋‹ค';

        document.getElementById('mapInfo').innerHTML = message;
      }
      getInfo();
    </script>
  </body>
</html>

 

 

์นด์นด์˜ค ๋ณธ์‚ฌ๋ฅผ ์ค‘์‹ฌ ์ขŒํ‘œ๋กœ ์ฐ๊ณ , ์ง€๋„์˜ ํ™•๋Œ€ ๋ ˆ๋ฒจ์„ 3์œผ๋กœ ํ–ˆ์„ ๋•Œ ๋ถ๋™์ชฝ ์ขŒํ‘œ์™€ ๋‚จ์„œ์ชฝ ์ขŒํ‘œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

๋™์•„๋Œ€ํ•™๊ต ์œ„๋„, ๊ฒฝ๋„๋ฅผ ์ฐพ์•„ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋‚˜์˜จ๋‹ค. ๋‚จ์„œ์ชฝ ์ขŒํ‘œ์—” ์„์ˆ™๋„ ์ดˆ๋“ฑํ•™๊ต๊ฐ€ ์œ„์น˜ํ•˜๋Š”๋ฐ, ํ•ด๋‹น ์ขŒํ‘œ๋ฅผ ์„ผํ„ฐ ์ขŒํ‘œ๋กœ ๊ณ ์ •ํ•˜๊ณ  ์ง€๋„๋ฅผ ๋„์šฐ๋ฉด ์„์ˆ™๋„ ์ดˆ๋“ฑํ•™๊ต๊ฐ€ ์ž˜ ๋œจ๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

 

 

 

3. ๊ตฌํ˜„ & Test

์ด ๋’ค๋ก  ๋”ฐ๋กœ ์„ค๋ช…์ด ํ•„์š”์—†์„ ๊ฒƒ ๊ฐ™์•„ ์ฝ”๋“œ๋งŒ ์ฒจ๋ถ€ํ•˜์˜€๋‹ค.

 

- Controller

์ง€๋„ ๊ฒฝ๊ณ„์˜ ์œ„๋„, ๊ฒฝ๋„์™€ ๊ฐ„๋‹จํ•œ ํ•„ํ„ฐ๋ง ์กฐ๊ฑด์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์ฃผ์—ˆ๋‹ค.

@Operation(summary = "์ง€๋„์—์„œ ๋ชจ์ง‘ ๊ณต๊ณ  ์กฐํšŒ")
@GetMapping("/api/worker/job-post/map")
public ResponseEntity<Response> getJobPostOnMap(@AuthenticationPrincipal PrincipalDetails principalDetails,
                                                @RequestParam(name = "northEastLat") Float northEastLat,
                                                @RequestParam(name = "northEastLng") Float northEastLng,
                                                @RequestParam(name = "southWestLat") Float southWestLat,
                                                @RequestParam(name = "southWestLng") Float southWestLng,
                                                @RequestParam(name = "workDateList", required = false) List<LocalDate> dateList,
                                                @RequestParam(name = "scrap", required = false) Boolean scrap) {
    List<JobPostMapResponse> jobPostsOnMap = jobPostWorkerService.findJobPostsOnMap(principalDetails.getMember().getId(), northEastLat, northEastLng, southWestLat, southWestLng, dateList, scrap);
    return ResponseEntity.ok(new Response(jobPostsOnMap, "์ง€๋„์—์„œ ๊ฒฝ๊ณ„ ์•ˆ์— ์†ํ•œ ๋ชจ์ง‘ ๊ณต๊ณ  ์กฐํšŒ ์™„๋ฃŒ"));
}

 

- Service

/**
 * ๋ชจ์ง‘ ๊ณต๊ณ  ์ง€๋„์—์„œ ์กฐํšŒ
 */
@Transactional(readOnly = true)
public List<JobPostMapResponse> findJobPostsOnMap(Long workerId, Float northEastLat, Float northEastLng, Float southWestLat, Float southWestLng, List<LocalDate> dateList, Boolean scrap) {
    Member worker = memberRepository.findById(workerId)
            .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));

    return jobPostRepository.findJobPostOnMap(worker.getId(), northEastLat, northEastLng, southWestLat, southWestLng, dateList, scrap).stream()
            .map(JobPostMapResponse::from)
            .collect(Collectors.toList());
}

 

 

- Repository

@Override
public List<JobPost> findJobPostOnMap(Long memberId, Float northEastLat, Float northEastLng, Float southWestLat, Float southWestLng, List<LocalDate> dateList, Boolean scrap) {
    return queryFactory
            .selectFrom(jobPost)
            .where(
                    jobPost.address.latitude.between(southWestLat, northEastLat).and(jobPost.address.longitude.between(southWestLng, northEastLng)),
                    eqWorkDate(dateList),
                    eqScrap(memberId, scrap)
            )
            .fetch();
}

 

 

 

swagger์—์„œ ์œ„๋„, ๊ฒฝ๋„ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ํ•„ํ„ฐ๋ง์„ ๊ฑด ํ›„ ์š”์ฒญํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ์ž˜ ๋‚˜๊ฐ€๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

    select
	// ์ƒ๋žต
    from
        job_post j1_0       
    where
        j1_0.latitude between 35.103577 and 35.126644           
        and j1_0.longitude between 128.89316 and 129.02708           
        and exists(select
            1           
        from
            work_date w1_0           
        where
            w1_0.date in('2024-04-10T00:00:00.000+0900','2024-04-11T00:00:00.000+0900')               
            and j1_0.job_post_id=w1_0.job_post_id)