주소창 백엔드단에서 api 호출하도록 변경함

dev
박성영 3 months ago
parent b6cf830661
commit 870318ace5

@ -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);
}
}

@ -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);
}

@ -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<String> 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<String> 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());
}
}
}

@ -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 # 단속행위 조치 사진
crdn-actn-photo: crdn/actn # 단속행위 조치 사진
# Juso API configuration
juso:
api:
key: "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY="
url: "http://www.juso.go.kr/addrlink/addrLinkUrl.do"

@ -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 # 단속행위 조치 사진
crdn-actn-photo: crdn/actn # 단속행위 조치 사진
# Juso API configuration
juso:
api:
key: "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY="
url: "http://www.juso.go.kr/addrlink/addrLinkUrl.do"

@ -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 # 단속행위 조치 사진
crdn-actn-photo: crdn/actn # 단속행위 조치 사진
# Juso API configuration
juso:
api:
key: "devU01TX0FVVEgyMDI1MDYxOTE1MjgxODExNTg2MTY="
url: "http://10.182.60.20/addrlink/addrLinkApi.do"

@ -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" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
@ -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 = "<p class='loading'>검색 중입니다...</p>";
// 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: '<c:url value="/common/address/search.ajax" />',
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") {

@ -54,24 +54,24 @@
<tr>
<th class="th"><span class="required">*</span> 우편번호</th>
<td>
<input type="text" id="zip" name="zip" class="input" maxlength="6" style="width: 120px;" validation-check="required" value="${data.zip}" readonly />
<input type="text" id="zip" name="zip" class="input" maxlength="6" style="width: 120px;" validation-check="required" value="${data.zip}" />
<button class="newbtn bg1 smallb-2" type="button" onclick="searchZipCode();">주소 찾기</button>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 지번 주소</th>
<td colspan="3">
<input type="text" id="lotnoAddr" name="lotnoAddr" class="input" style="width: 450px;" maxlength="320" readonly validation-check="required" value="${data.lotnoAddr}"/>
<input type="text" id="lotnoMno" name="lotnoMno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.lotnoMno}"/>
<input type="text" id="lotnoSno" name="lotnoSno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.lotnoSno}"/>
<input type="text" id="lotnoAddr" name="lotnoAddr" class="input" style="width: 450px;" maxlength="320" validation-check="required" value="${data.lotnoAddr}"/>
<input type="text" id="lotnoMno" name="lotnoMno" class="input" style="width: 120px;" maxlength="4" value="${data.lotnoMno}"/>
<input type="text" id="lotnoSno" name="lotnoSno" class="input" style="width: 120px;" maxlength="4" value="${data.lotnoSno}"/>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 도로명 주소</th>
<th class="th">도로명 주소</th>
<td colspan="3">
<input type="text" id="roadNmAddr" name="roadNmAddr" class="input" style="width: 450px;" maxlength="320" readonly validation-check="required" value="${data.roadNmAddr}"/>
<input type="text" id="bldgMno" name="bldgMno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.bldgMno}"/>
<input type="text" id="bldgSno" name="bldgSno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.bldgSno}"/>
<input type="text" id="roadNmAddr" name="roadNmAddr" class="input" style="width: 450px;" maxlength="320" value="${data.roadNmAddr}"/>
<input type="text" id="bldgMno" name="bldgMno" class="input" style="width: 120px;" maxlength="4" value="${data.bldgMno}"/>
<input type="text" id="bldgSno" name="bldgSno" class="input" style="width: 120px;" maxlength="4" value="${data.bldgSno}"/>
</td>
</tr>
<tr>
@ -96,6 +96,7 @@
<textarea id="rmrk" name="rmrk" class="textarea" rows="3" maxlength="1000" style="height: 50px;">${data.rmrk}</textarea>
</td>
</tr>
<!-- 중요로직: sggCd(시군구 코드는 세션에서 서버가 설정) -->
<tr style="display: none;">
<th class="th"><span class="required">*</span> 행정구역코드</th>
@ -145,6 +146,7 @@
</select>
</td>
</tr>
</table>
</form>
</div>

Loading…
Cancel
Save