diff --git a/src/main/java/go/kr/project/common/controller/AddressController.java b/src/main/java/go/kr/project/common/controller/AddressController.java new file mode 100644 index 0000000..a8633d1 --- /dev/null +++ b/src/main/java/go/kr/project/common/controller/AddressController.java @@ -0,0 +1,40 @@ +package go.kr.project.common.controller; + +import go.kr.project.common.service.AddressService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 주소 검색 관련 컨트롤러 + */ +@RestController +@RequestMapping("/common/address") +@RequiredArgsConstructor +@Tag(name = "주소 검색", description = "외부 주소 API 연동 관련") +public class AddressController { + + private final AddressService addressService; + + /** + * 외부 주소 API를 호출하여 검색 결과를 반환합니다. + * @param keyword 검색어 + * @param currentPage 현재 페이지 + * @param countPerPage 페이지당 결과 수 + * @return API 응답 결과 (JSON 문자열) + */ + @GetMapping(value = "/search.ajax", produces = "application/json; charset=UTF-8") + @Operation(summary = "주소 검색", description = "외부 도로명주소 API를 호출하여 결과를 반환합니다.") + public String searchAddress( + @Parameter(description = "검색어") @RequestParam("keyword") String keyword, + @Parameter(description = "현재 페이지") @RequestParam("currentPage") int currentPage, + @Parameter(description = "페이지당 결과 수") @RequestParam("countPerPage") int countPerPage) { + + return addressService.searchAddress(keyword, currentPage, countPerPage); + } +} diff --git a/src/main/java/go/kr/project/common/service/AddressService.java b/src/main/java/go/kr/project/common/service/AddressService.java new file mode 100644 index 0000000..0dab3bc --- /dev/null +++ b/src/main/java/go/kr/project/common/service/AddressService.java @@ -0,0 +1,17 @@ +package go.kr.project.common.service; + +/** + * 주소 검색 서비스 인터페이스 + */ +public interface AddressService { + + /** + * 외부 주소 API를 호출하여 주소를 검색합니다. + * + * @param keyword 검색어 + * @param currentPage 현재 페이지 + * @param countPerPage 페이지당 결과 수 + * @return API 응답 결과 (JSON 문자열) + */ + String searchAddress(String keyword, int currentPage, int countPerPage); +} diff --git a/src/main/java/go/kr/project/common/service/impl/AddressServiceImpl.java b/src/main/java/go/kr/project/common/service/impl/AddressServiceImpl.java new file mode 100644 index 0000000..3b5080d --- /dev/null +++ b/src/main/java/go/kr/project/common/service/impl/AddressServiceImpl.java @@ -0,0 +1,73 @@ +package go.kr.project.common.service.impl; + +import go.kr.project.common.service.AddressService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; + +/** + * 주소 검색 서비스 구현 클래스 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AddressServiceImpl implements AddressService { + + // 중요로직: application.yml에서 API 키 주입 + @Value("${juso.api.key}") + private String confmKey; + + @Value("${juso.api.url}") + private String API_URL; + + @Override + public String searchAddress(String keyword, int currentPage, int countPerPage) { + log.debug("주소 API 호출: keyword={}, currentPage={}, countPerPage={}", keyword, currentPage, countPerPage); + + RestTemplate restTemplate = new RestTemplate(); + + // HTTP 요청 헤더 설정 + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + HttpEntity entity = new HttpEntity<>(headers); + + // URI 및 파라미터 설정 + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(API_URL) + .queryParam("confmKey", confmKey) + .queryParam("currentPage", currentPage) + .queryParam("countPerPage", countPerPage) + .queryParam("keyword", keyword) + .queryParam("resultType", "json"); + + try { + // 중요로직: 외부 API 호출 + // 주소 API가 응답의 Content-Type을 text/html로 반환하는 경우가 있어, String으로 받은 후 그대로 전달 + ResponseEntity response = restTemplate.exchange( + builder.encode(StandardCharsets.UTF_8).build().toUri(), + HttpMethod.GET, + entity, + String.class); + + return response.getBody(); + + } catch (HttpClientErrorException e) { + log.error("주소 API 호출 오류: {} - {}", e.getStatusCode(), e.getResponseBodyAsString()); + // 클라이언트에 전달할 에러 메시지 포맷 생성 + return String.format("{\"results\":{\"common\":{\"errorCode\":\"%s\",\"errorMessage\":\"%s\"}}}", + e.getStatusCode().value(), + "주소 API 서버로부터 오류 응답을 받았습니다: " + e.getStatusCode().getReasonPhrase()); + } + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 27a13e8..819ddad 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -102,4 +102,10 @@ file: bbs-post: bbs/post # 게시판 파일 저장 경로 html-editor: common/html_editor # HTML 에디터 파일 저장 경로 crdn-act-photo: crdn/act # 단속행위 사진 - crdn-actn-photo: crdn/actn # 단속행위 조치 사진 \ No newline at end of file + crdn-actn-photo: crdn/actn # 단속행위 조치 사진 + +# Juso API configuration +juso: + api: + key: "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY=" + url: "http://www.juso.go.kr/addrlink/addrLinkUrl.do" \ No newline at end of file diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 519ca8b..4595394 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -102,4 +102,10 @@ file: bbs-post: bbs/post # 게시판 파일 저장 경로 html-editor: common/html_editor # HTML 에디터 파일 저장 경로 crdn-act-photo: crdn/act # 단속행위 사진 - crdn-actn-photo: crdn/actn # 단속행위 조치 사진 \ No newline at end of file + crdn-actn-photo: crdn/actn # 단속행위 조치 사진 + +# Juso API configuration +juso: + api: + key: "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY=" + url: "http://www.juso.go.kr/addrlink/addrLinkUrl.do" \ No newline at end of file diff --git a/src/main/resources/application-prd.yml b/src/main/resources/application-prd.yml index e29c647..5f40259 100644 --- a/src/main/resources/application-prd.yml +++ b/src/main/resources/application-prd.yml @@ -109,4 +109,10 @@ file: bbs-post: bbs/post # 게시판 파일 저장 경로 html-editor: common/html_editor # HTML 에디터 파일 저장 경로 crdn-act-photo: crdn/act # 단속행위 사진 - crdn-actn-photo: crdn/actn # 단속행위 조치 사진 \ No newline at end of file + crdn-actn-photo: crdn/actn # 단속행위 조치 사진 + +# Juso API configuration +juso: + api: + key: "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY=" + url: "http://10.182.60.20/addrlink/addrLinkApi.do" \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/common/address/searchAddress.jsp b/src/main/webapp/WEB-INF/views/common/address/searchAddress.jsp index a4b52e6..e424dde 100644 --- a/src/main/webapp/WEB-INF/views/common/address/searchAddress.jsp +++ b/src/main/webapp/WEB-INF/views/common/address/searchAddress.jsp @@ -1,5 +1,7 @@ -<%@ page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> @@ -54,10 +56,7 @@ function searchAddress(page) { currentKeyword = keyword; } - //팝업 API 키 - //var confmKey = "U01TX0FVVEgyMDE3MDQyMTE3MTQ1MjIwNzQ4"; - //검색 API 키 개발용 90일짜리 발급일 : 2025.06.19 - var confmKey = "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY="; + // 검색 결과 초기화 document.getElementById("resultList").innerHTML = ""; @@ -65,9 +64,9 @@ function searchAddress(page) { // 로딩 표시 document.getElementById("resultList").innerHTML = "

검색 중입니다...

"; - // API 호출 - $.ajax({ - url: "https://125.60.46.141/addrlink/addrLinkApi.do", + /* + * 기존소스 + * url: "https://125.60.46.141/addrlink/addrLinkApi.do", //url: "http://10.182.60.20/addrlink/addrLinkApi.do", type: "post", dataType: "json", @@ -83,6 +82,18 @@ function searchAddress(page) { keyword: currentKeyword || keyword, resultType: "json" }, + * */ + + // API 호출 (내부 API 경유) + $.ajax({ + url: '', + type: "get", + data: { + currentPage: page, + countPerPage: countPerPage, + keyword: currentKeyword || keyword + }, + dataType: "json", // 서버로부터 JSON 응답을 기대 success: function(data) { console.log(data); if(data.results.common.errorCode != "0") { diff --git a/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnPstnInfo/crdnPstnInfoRegistPopup.jsp b/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnPstnInfo/crdnPstnInfoRegistPopup.jsp index f7a2c00..3aff12d 100644 --- a/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnPstnInfo/crdnPstnInfoRegistPopup.jsp +++ b/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnPstnInfo/crdnPstnInfoRegistPopup.jsp @@ -54,24 +54,24 @@ * 우편번호 - + * 지번 주소 - - - + + + - * 도로명 주소 + 도로명 주소 - - - + + + @@ -96,6 +96,7 @@ + * 행정구역코드 @@ -145,6 +146,7 @@ +