☭DEVELOPER/#2 웹개발(자바기반 풀스택)

[BACKEND]스프링 MVC 공공 Open API 연동 개발

조반짝 2025. 2. 10. 00:00
728x90
반응형

주소정보누리집(도로명주소 안내시스템)
https://www.juso.go.kr/openIndexPage.do

 

 

https://business.juso.go.kr/addrlink/openApi/searchApi.do

검색API

본인인증 사용중인 휴대전화번호로 인증 인증하기 아이핀 인증 본인 명의 아이핀 계정으로 인증 인증하기

business.juso.go.kr


[Oracle11gDB 계정 생성]

1. 윈도우즈키 + r키 = cmd

2. C:\Users\starh>sqlplus system/System1234

SQL*Plus: Release 11.2.0.1.0 Production on 월 1월 10 19:23:38 2022

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


다음에 접속됨:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options


3. SQL>drop user jsp_openapi cascade;

4. SQL>create user jsp_openapi identified by jsp_openapi;

5. SQL>grant connect, resource, dba to jsp_openapi;

6. SQL>conn jsp_openapi/jsp_openapi;

7. SQL>show user

8. SQL>create table jsp_address(
          address_id number primary key,
          basic_address varchar2(80) not null,
          detail_address varchar2(50) not null
);

9. SQL> desc jsp_address;

10. SQL>create sequence idx_seq start with 0 minvalue 0;

11. SQL>select * from user_sequences;

-- select * from tab; 조회 시 휴지통 내용(삭제 내용) 지울때 활용함
12. SQL>purge recyclebin;  

13. SQL>select * from jsp_address;

14. SQL> commit;

[Spring Legacy Project 개발환경 세팅]

15. SpringMVC 프로젝트를 다음과 같이 생성합니다.

   1) 프로젝트명 = JAVA_Servlet_JSP_SpringMVC_OracleDB
 
   2) top-level package 명 = cohttp://m.openapi.spring

   3) STS(또는 Eclipse) 상단 File 클릭 - New - Spring Legacy Project 클릭 선택
       - Project name: 필드란에 JAVA_Servlet_JSP_SpringMVC_OracleDB 입력하고,
       중앙에 Templates: 에서 하단에 Spring MVC Project 클릭
       - Next 버튼 클릭
       - Enter a topLevelPackage 하단 필드 입력란에
         cohttp://m.openapi.spring 입력 - 하단 Finish 버튼 클릭!

   4) 빌드툴 = 메이븐 방식 pom.xml 파일 안에 다음과 같이 소스를 수정 처리함.

~~ 위에 생략 ~~
<java-version>1.8</java-version>
<org.springframework-version>5.0.7.RELEASE</org.springframework-version>

~~ 중간 생략 ~~

            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                 <version>2.5.1</version>
                <configuration>
                      <source>${java-version}</source>
             <target>${java-version}</target>

~~ 아래 생략 ~~

   5) 프로젝트 클릭 선택 - Properties - Java Build Path - Libraries - Add Library

      - Server Runtime 에서 Apache Tomcat v9.0 선택 추가 바랍니다.

   6) 프로젝트 클릭 선택 - Properties - Project Facets에서 Java 버전을 1.8로 변경해 주고,

       우측 상단 Runtimes에서 Apache Tomcat v9.0 선택 체크해 줌.

16. ojdbc6.jar 파일 삽입(예시)

  C:\app\starh\product\11.2.0\dbhome_1\jdbc\lib 폴더에 있는 

   ojdbc6.jar 파일을 복사함.

17. webapp 폴더 안에 있는 WEB-INF 폴더 안에 - lib 폴더 안에

   ojdbc6.jar 파일을 넣어줌.

18. JAVA_Servlet_JSP_SpringMVC_OracleDB 프로젝트 선택 - 마우스 우클릭 - properties

   - Java Build Path 클릭 - Add Library... 클릭 - Web App Libraries 클릭해서 추가해줌.
 


Microsoft Windows [Version 10.0.19045.3570]
(c) Microsoft Corporation. All rights reserved.

C:\Users\guro-hi>sqlplus system/System1234

SQL*Plus: Release 11.2.0.1.0 Production on 월 11월 6 11:42:24 2023

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


다음에 접속됨:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> show user
USER은 "SYSTEM"입니다
SQL> drop user jsp_openapi cascade;
drop user jsp_openapi cascade
          *
1행에 오류:
ORA-01918: 사용자 'JSP_OPENAPI'(이)가 존재하지 않습니다


SQL> create user jsp_openapi identified by jsp_openapi;

사용자가 생성되었습니다.

SQL> grant connect, resource, dba to jsp_openapi;

권한이 부여되었습니다.

SQL> conn jsp_openapi/jsp_openapi;
연결되었습니다.
SQL> show user
USER은 "JSP_OPENAPI"입니다
SQL> create table jsp_address(
  2            address_id number primary key,
  3            basic_address varchar2(80) not null,
  4            detail_address varchar2(50) not null
  5  );

테이블이 생성되었습니다.

SQL> desc jsp_address;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 ADDRESS_ID                                NOT NULL NUMBER
 BASIC_ADDRESS                             NOT NULL VARCHAR2(80)
 DETAIL_ADDRESS                            NOT NULL VARCHAR2(50)

SQL> create sequence idx_seq start with 0 minvalue 0;

시퀀스가 생성되었습니다.

SQL> select * from user_sequences;

SEQUENCE_NAME                   MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE
------------------------------ ---------- ---------- ------------ - - ----------
LAST_NUMBER
-----------
IDX_SEQ                                 0 1.0000E+28            1 N N         20
          0


SQL> purge recyclebin;

휴지통이 지워졌습니다.

SQL> select * from jsp_address;

선택된 레코드가 없습니다.

SQL>  commit;

커밋이 완료되었습니다.

SQL>

 
sts 실행

properties 옵션 설정 하기!!

 


Spring Back_End 코딩

19. JAVA 및 웹 소스 코딩

1) src\main\java\com\openapi\spring 패키지 안에 common 패키지 생성 후 JDBCUtil.java 소스 코딩함

package cohttp://m.openapi.spring.common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// Oracle DB 연결 및 close() 처리 JDBC Utility 클래스 작성 
public class JDBCUtil {
public static Connection getConnection() {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl",
"jsp_openapi", "jsp_openapi");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

public static void close(PreparedStatement stmt, Connection conn) {
if (stmt != null) {
try {
if (!stmt.isClosed()) {
stmt.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
stmt = null;
}
}

if (conn != null) {
try {
if (!conn.isClosed()) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}

public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {

if (rs != null) {
try {
if (!rs.isClosed()) {
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs = null;
}
}

if (stmt != null) {
try {
if (!stmt.isClosed()) {
stmt.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
stmt = null;
}
}

if (conn != null) {
try {
if (!conn.isClosed()) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}

public static void rollback(Connection conn) {
if(conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {

}
}
}
}


2) src\main\webapp 폴더 안에 dbconnTest.jsp 소스 코딩함

<%@page import="cohttp://m.openapi.spring.common.JDBCUtil"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- JDBCUtil 활용 OracleDB 연결 접속을 확인해 봅니다. -->
<% 
try (Connection conn = JDBCUtil.getConnection()){
out.println("커넥션 연결 성공함");

} catch (SQLException e) {
out.println("커넥션 연결 실패함 : " + e.getMessage());
application.log("커넥션 연결 실패", e);
}
%>
</body>
</html>

3) dbconnTest.jsp 파일 클릭 선택 - 마우스 우클릭 - Run As - Run on Server 클릭
    - 웹 주소창에 http://localhost:9007(사용포트입력바랍니다)/spring/dbconnTest.jsp 입력해서
   "커넥션 연결 성공함" 메시지 확인함

4) src\main\java\com\openapi\spring 패키지 안에 address 패키지 생성 후 AddressVO.java 소스 코딩함

package cohttp://m.openapi.spring.address;

import java.util.Map;

// AddressVO 클래스 작성
public class AddressVO {

private String mainAddress;  // 기본 주소 필드
private String subAddress;   // 상세 주소 필드

public String getMainAddress() {
return mainAddress;
}
public String getSubAddress() {
return subAddress;
}
public void setMainAddress(String mainAddress) {
this.mainAddress = mainAddress;
}
public void setSubAddress(String subAddress) {
this.subAddress = subAddress;
}

// 기본 주소가 비어있는지 검증하는 메서드 작성
public void validateMain(Map<String, Boolean> errors) {
if(mainAddress == null || mainAddress.trim().isEmpty()) {
errors.put("main", Boolean.TRUE);
}
}
// 상세 주소가 비어있는지 검증하는 메서드 작성
public void validateSub(Map<String, Boolean> errors) {
if(subAddress == null || subAddress.trim().isEmpty()) {
errors.put("sub", Boolean.TRUE);
}
}

}


5) src\main\java\com\openapi\spring 패키지 안에 address 패키지 생성 후 AddressDAO.java 소스 코딩함

package cohttp://m.openapi.spring.address;

import java.sql.Connection;
import java.sql.PreparedStatement;

import cohttp://m.openapi.spring.common.JDBCUtil;

// OracleDB 연동 DAO(Data Access Object) AddressDAO 클래스 작성
public class AddressDAO {

private Connection conn = null;
private PreparedStatement stmt = null;

// PreparedStatement 활용 insert 처리 쿼리문 작성
// insert into jsp_address values(idx_seq.nextval, '서울시 행복한 아파트', '살기좋은 동 1004호');
private static final String INSERT_ADDRESS = "insert into jsp_address values(idx_seq.nextVal, ?, ?)";

// insertAddress 메서드 작성
public void insertAddress(AddressVO vo) {
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(INSERT_ADDRESS);
stmt.setString(1, vo.getMainAddress());
stmt.setString(2, vo.getSubAddress());
stmt.executeUpdate();
} catch(Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(stmt, conn);
}
}
}


6) src\main\java\com\openapi\spring 패키지 안에 controller 패키지 생성 후 AddressController.java 소스 코딩함

package cohttp://m.openapi.spring.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cohttp://m.openapi.spring.address.AddressDAO;
import cohttp://m.openapi.spring.address.AddressVO;

// 웹 URL을 /update.do 로 매핑 처리함 : 서블릿 파일로 HttpServlet 상속 AddressController 클래스 작성
@WebServlet("/update.do")
public class AddressController extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}

private void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 인코딩 타입 설정
request.setCharacterEncoding("utf-8");

// 기본 주소와 상세 주소를 파라미터로 받은 뒤 변수에 대입해 줍니다.
String mainAddress = request.getParameter("mainAddress");
String subAddress = request.getParameter("subAddress");

// vo 객체 생성 후 위에서 받은 변수로 값을 set 처리합니다.
AddressVO vo = new AddressVO();
vo.setMainAddress(mainAddress);
vo.setSubAddress(subAddress);

// error에 관한 해쉬맵 생성 및 Attribute 설정을 처리합니다.
Map<String, Boolean> errors = new HashMap<>();
request.setAttribute("errors", errors);

// 검증 메서드를 호출합니다.
vo.validateMain(errors);
vo.validateSub(errors);

// DAO 객체 생성 후 insert 메서드를 실행 처리합니다.
AddressDAO addressDAO = new AddressDAO();
addressDAO.insertAddress(vo);

// 만약 errors에 값이 존재한다면!
if(!errors.isEmpty()) {
// 포워딩을 통해 초기화면으로 되돌리게 합니다.
// 포워드는 RequestDispatcher을 이용하여 응답으로 사용할 jsp 방식으로 넘기는 방식으로 
// 실행속도가 빠르나 브라우저 입장에서는 URL이 바뀌지 않는 단점이 있습니다.

// 리다이렉트는 두번의 요청과 응답으로 처리되서 실행속도가 느리지만
// 클라이언트가 URL을 확인할 수 있는 장점이 있습니다.

// 1. 에러가 존재하여 초기화면을 돌리는 작업은 같은 페이지 내에서 일어나므로 포워드로 처리하고
request.getRequestDispatcher("index.jsp").forward(request, response);
}

// 2. 에러가 존재하지 않아 성공화면을 보여주는 작업은
// URL이 바뀔 필요가 있으므로 리다이렉트로 처리했습니다.
response.sendRedirect("success.jsp");
}
}

 

package com.openapi.spring.common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// Oracle DB 연결 및 close() 처리 JDBC Utility 클래스 작성 
public class JDBCUtil {
   public static Connection getConnection() {
      try {
         Class.forName("oracle.jdbc.driver.OracleDriver");
         return DriverManager.getConnection(
               "jdbc:oracle:thin:@localhost:1521:orcl",
               "jsp_openapi", "jsp_openapi");
      } catch (Exception e) {
         e.printStackTrace();
      }
      return null;
   }

   public static void close(PreparedStatement stmt, Connection conn) {
      if (stmt != null) {
         try {
            if (!stmt.isClosed()) {
               stmt.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            stmt = null;
         }
      }

      if (conn != null) {
         try {
            if (!conn.isClosed()) {
               conn.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            conn = null;
         }
      }
   }

   public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {

      if (rs != null) {
         try {
            if (!rs.isClosed()) {
               rs.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            rs = null;
         }
      }

      if (stmt != null) {
         try {
            if (!stmt.isClosed()) {
               stmt.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            stmt = null;
         }
      }

      if (conn != null) {
         try {
            if (!conn.isClosed()) {
               conn.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            conn = null;
         }
      }
   }
   
   public static void rollback(Connection conn) {
      if(conn != null) {
         try {
            conn.rollback();
         } catch (SQLException ex) {
            
         }
      }
   }
}

 

 


인터페이스 따로 만드는 대신에 구현클래스에 한번에 넣엇다

서블릿을 사용하면 관련된 메소드를 자동으로 만들어준다.

 

package com.openapi.spring.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.openapi.spring.address.AddressDAO;
import com.openapi.spring.address.AddressVO;

//웹 URL을 /update.do 로 매핑 처리함 : 서블릿 파일로 HttpServlet 상속 AddressController 클래스 작성
@WebServlet("/update.do")
public class AddressController extends HttpServlet {
   private static final long serialVersionUID = 1L;
       
   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      process(request, response);
   }


   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      process(request, response);
   }

   private void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
      // 인코딩 타입 설정
      request.setCharacterEncoding("utf-8");
      
      // 기본 주소와 상세 주소를 파라미터로 받은 뒤 변수에 대입해 줍니다.
      String mainAddress = request.getParameter("mainAddress");
      String subAddress = request.getParameter("subAddress");
      
      // vo 객체 생성 후 위에서 받은 변수로 값을 set 처리합니다.
      AddressVO vo = new AddressVO();
      vo.setMainAddress(mainAddress);
      vo.setSubAddress(subAddress);
      
      // error에 관한 해쉬맵 생성 및 Attribute 설정을 처리합니다.
      Map<String, Boolean> errors = new HashMap<String, Boolean>();
      request.setAttribute("errors", errors);
      
      // 검증 메소드를 호출합니다.
      vo.validateMain(errors);
      vo.validateSub(errors);
      
      // DAO 객체 생성 후 insert 메소드를 실행 처리합니다.
      AddressDAO addressDAO = new AddressDAO();
      addressDAO.insertAddress(vo);
      
      // 만약 errors에 값이 존재한다면
      if(!errors.isEmpty()) {
         // 포워딩을 통해 초기화면으로 되돌리게 합니다.
            // 포워드는 RequestDispatcher을 이용하여 응답으로 사용할 jsp 방식으로 넘기는 방식으로 
            // 실행속도가 빠르나 브라우저 입장에서는 URL이 바뀌지 않는 단점이 있습니다.
         
            // 리다이렉트는 두번의 요청과 응답으로 처리되서 실행속도가 느리지만
            // 클라이언트가 URL을 확인할 수 있는 장점이 있습니다.
         
            // 1. 에러가 존재하여 초기화면을 돌리는 작업은 같은 페이지 내에서 일어나므로 포워드로 처리하고
         request.getRequestDispatcher("index.jsp").forward(request, response);
         
         // 2. 에러가 존재하지 않아 성공화면을 보여주는 작업은
         // URL이 바뀔 필요가 있으므로 리다이렉트로 처리했습니다.
         response.sendRedirect("success.jsp");
         
      }
      
   }
}

7) src\main\webapp\resources 폴더 안에 css 폴더 만들고, bootstrap-3.3.2.min.css 파일 넣어줌.
    그리고, js 폴더 만들고, jquery-3.5.1.min.js 파일 넣어줌.

8) src\main\webapp 폴더 안에 index.jsp 소스 코딩함

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주소 입력</title>
<link rel="stylesheet" type="text/css" media="screen" href="resources/css/bootstrap-3.3.2.min.css">
<script type="text/javascript" src="resources/js/jquery-3.5.1.min.js"></script>

<script type="text/javascript">

// 도로명주소 - 주소검색 팝업을 호출합니다.
// https://business.juso.go.kr/addrlink/openApi/popupApi.do 웹사이트에서
// 하단 "주소입력화면 소스보기"를 클릭해서 참고합니다.
function fn_openAddressPopup() {
var url = "addressAPIPopup.jsp";
var name = "AddressPopup";
var option = "width=650, height=500, top=100, left=200, location=no"
window.open(url, name, option);
}
// 주소검색 팝업 호출 콜백 callback_openAddressPopup() 메서드 입니다.
function callback_openAddressPopup(aParam) {
document.getElementById("mainAddress").value = aParam["roadAddr"];
}
</script>
</head>
<body>
<h2>[처음화면]</h2>

<!-- update.do로 데이터 전송 -->
<form action="update.do" method="post">
<div class="input-group">
<span>기본 주소</span>
<br>
<input type="text" id="mainAddress" name="mainAddress" placeholder="주소를 선택하세요!"
readonly="readonly">

<!-- errors Map에 값이 해당하는 값이 있을 경우 메세지를 출력하는 부분 -->
<span> 
<c:if test="${errors.main}">기본 주소를 입력하세요!</c:if>
</span>
<button type="button" onclick="javascript:fn_openAddressPopup();">주소 검색</button><br><br>
</div> 
<div style="margin-top: 0px;">
<span>상세 주소</span>
<br>
<input type="text" id="subAddress" name="subAddress" placeholder="나머지 주소를 입력하세요! /">
<c:if test="${errors.sub}">상세 주소를 입력하세요!</c:if> <br>
</div> <br>
<input type="submit" value="주소 등록" />
<input type="reset" value="입력 취소" />
</form>
</body>
</html>

9) src\main\webapp 폴더 안에 addressAPIPopup.jsp 소스 코딩함
  [중요 : addressAPIPopup.jsp 소스 안에 도로명주소 인증키 값을 입력해 줍니다]

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel='stylesheet' type='text/css' media='screen' href='resources/css/bootstrap-3.3.2.min.css'>
<script src="resources/js/jquery-3.5.1.min.js"></script>
<script>
// https://business.juso.go.kr/addrlink/openApi/searchApi.do 웹사이트에서
// 하단 "웹 호출 소스 보기"에서 "JSON" 클릭해서 참고 합니다.
// 도로명 주소로 검색 api 연동을 ajax로 처리 합니다.
function fn_search(){
$.ajax({
 url :"http://www.juso.go.kr/addrlink/addrLinkApiJsonp.do"
,type:"post"
,data:$("#searchForm").serialize()
,dataType:"jsonp"
,crossDomain:true
,success:function(jsonStr){
var errCode = jsonStr.results.common.errorCode;
var errDesc = jsonStr.results.common.errorMessage;
if(errCode != "0"){
alert(errCode+"="+errDesc);
}else{
if(jsonStr != null){
fn_makeListJson(jsonStr);  // 아래 fn_makeListJson(jsonStr) 함수 호출
}
}
}
    ,error: function(xhr,status, error){
     alert("에러발생");
    }
});

}

// 결과 테이블 생성 : 위에서 호출 받아서 처리할 fn_makeListJson(jsonStr) 메서드 선언
function fn_makeListJson(jsonStr){
var htmlStr = "";
$(jsonStr.results.juso).each(function(){
htmlStr += "<tr onclick=\"javascript:chooseAddress('"+this.roadAddr+"', '"+this.jibunAddr+"', '"+this.zipNo+"');\">";
htmlStr += "<td>";
htmlStr += "<dl>"+this.roadAddr+"</dl>";
htmlStr += "<dl>"+this.jibunAddr+"</dl>";
htmlStr += "</td>";
htmlStr += "<td>"+this.zipNo+"</td>";
htmlStr += "</tr>";
});
$("#addressTableTbody").html(htmlStr);

}

// Enter 키 이벤트
function enterSearch() {
var evt_code = (window.netscape) ? ev.which : event.keyCode;
if (evt_code == 13) {    
event.keyCode = 0;  
fn_search(); // jsonp사용하여 enter키 입력 확인 : fn_search() 함수 호출

}

// 주소 선택
function chooseAddress(roadAddr, jibunAddr, zipNo){
var aParam = [];
aParam["roadAddr"] = roadAddr;
                         // aParam["jibunAddr"] = jibunAddr;   // 필요시 추가 활용함
          // aParam["zipNo"] = zipNo;        // 필요시 추가 활용함

opener.callback_openAddressPopup(aParam);
window.close();
}
</script>
</head>
<div class="container" style="margin-top:25px;">
<div id="memberSearchDiv" class="text-center">
<form id="searchForm" name="searchForm" method="post" class="navbar-form navbar-left" role="search" onsubmit="event.preventDefault();">
<input type="hidden" name="currentPage" value="1"/>
<input type="hidden" name="countPerPage" value="100"/>
<input type="hidden" name="resultType" value="json"/>
<input type="hidden" id="confmKey" name="confmKey" value="이자리에 Open API 키를 기재하시기 바랍니다"/><!-- 요청 변수 설정 (승인키) -->

<div class="form-group">
<input type="text" id="keyword" name="keyword" class="form-control" placeholder="도로명+건물번호, 건물명, 지번을 입력하세요" onkeypress="javascript:enterSearch();" />
</div>
<input type="button" class="btn btn-default" onclick="javascript:fn_search();"  value="주소검색하기" />
</form>

</div>

<div>
<table class="table table-hover">
<thead>
<tr>
<th>주소</th>
<th>우편번호</th>
</tr>
</thead>
<tbody id="addressTableTbody">

</tbody>
</table>
</div>
</div>


10) src\main\webapp 폴더 안에 success.jsp 소스 코딩함

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주소 정보 연동 입력 성공</title>
</head>
<body>
<h2>* 주소 정보가 제대로 등록 처리 되었습니다!</h2>
<br>
<form action="index.jsp">
<input type="submit" value="처음으로" />
</form>
</body>
</html>

============================================================

20. index.jsp 파일 실행 확인함

  1) JAVA_Servlet_JSP_SpringMVC_OracleDB 프로젝트 클릭 선택 - 마우스 우클릭 - Run As - Run on Server 클릭 : [처음 화면] 확인함

  2) 상세 주소 검색해서 정상 동작 테스트하고, "처음으로" 버튼 클릭해서 처음으로 이동 확인함.

  3) OracleDB 입력 데이터 확인해 봄.

     C:\Users\starh>sqlplus jsp_openapi/jsp_openapi

SQL*Plus: Release 11.2.0.1.0 Production on 월 1월 10 19:23:38 2022

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


다음에 접속됨:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>show user

SQL>select * from jsp_address;


https://business.juso.go.kr/addrlink/openApi/popupApi.do

https://business.juso.go.kr/addrlink/openApi/searchApi.do

검색API

본인인증 사용중인 휴대전화번호로 인증 인증하기 아이핀 인증 본인 명의 아이핀 계정으로 인증 인증하기

business.juso.go.kr

function 복사 붙여넣기

 

결과 테이블 생성: 위에서 호출받아서 처리할 fn_makeListJson(jsonStr) 메서드 선언

 

AddressDAO

package com.openapi.spring.address;

import java.sql.Connection;
import java.sql.PreparedStatement;

import com.openapi.spring.common.JDBCUtil;

// OracleDB 연동 DAO(Data Access Object) AddressDAO 클래스 작성
public class AddressDAO {

	private Connection conn = null;
	private PreparedStatement stmt =null;
	
	// PreparedStatement 활용 insert 처리 쿼리문 작성
	//insert into jsp_address values(idx_seq.nextval, '서울시 행복한 아파트', '살기좋은동 1004호')
	private static final String INSERT_ADDRESS ="insert into jsp_address values(idx_seq.nextval, ?, ?)";
	
	// insertAddress 메서드 작성
	public void insertAddress(AddressVO vo) {
		try {
			conn = JDBCUtil.getConnection();
			stmt =conn.prepareStatement(INSERT_ADDRESS);
			stmt.setString(1, vo.getMainAddress());
			stmt.setString(2, vo.getSubAddress());
			stmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtil.close(stmt, conn);
		}
	}
}

AddressVO

package com.openapi.spring.address;

import java.util.Map;

// AdressVO 클래스 작성
public class AddressVO {

	private String mainAddress;  // 기본 주소 필드 선언
	private String subAddress;   // 상세 주소 필드 선언
	
	public String getMainAddress() {
		return mainAddress;
	}
	public void setMainAddress(String mainAddress) {
		this.mainAddress = mainAddress;
	}
	public String getSubAddress() {
		return subAddress;
	}
	public void setSubAddress(String subAddress) {
		this.subAddress = subAddress;
	}
	
	
	// 기본 주소가 비어있는지 검증하는 메서드 작성
	public void validateMain(Map<String, Boolean> errors) {
		
		if (mainAddress == null || mainAddress.trim().isEmpty()) {
			errors.put("main", Boolean.TRUE);
		}
	}
	// 상세 주소가 비어있는지 검증하는 메서드 작성
	public void validateSub(Map<String, Boolean> errors) {
		if (subAddress == null || subAddress.trim().isEmpty()) {
			errors.put("sub", Boolean.TRUE);
		}
	}
	
	
}

JDBCUtil

package com.openapi.spring.common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// Oracle DB 연결 및 close() 처리 JDBC Utility 클래스 작성 
public class JDBCUtil {
   public static Connection getConnection() {
      try {
         Class.forName("oracle.jdbc.driver.OracleDriver");
         return DriverManager.getConnection(
               "jdbc:oracle:thin:@localhost:1521:orcl",
               "jsp_openapi", "jsp_openapi");
      } catch (Exception e) {
         e.printStackTrace();
      }
      return null;
   }

   public static void close(PreparedStatement stmt, Connection conn) {
      if (stmt != null) {
         try {
            if (!stmt.isClosed()) {
               stmt.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            stmt = null;
         }
      }

      if (conn != null) {
         try {
            if (!conn.isClosed()) {
               conn.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            conn = null;
         }
      }
   }

   public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {

      if (rs != null) {
         try {
            if (!rs.isClosed()) {
               rs.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            rs = null;
         }
      }

      if (stmt != null) {
         try {
            if (!stmt.isClosed()) {
               stmt.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            stmt = null;
         }
      }

      if (conn != null) {
         try {
            if (!conn.isClosed()) {
               conn.close();
            }
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            conn = null;
         }
      }
   }
   
   public static void rollback(Connection conn) {
      if(conn != null) {
         try {
            conn.rollback();
         } catch (SQLException ex) {
            
         }
      }
   }
}

AddressController

package com.openapi.spring.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.openapi.spring.address.AddressDAO;
import com.openapi.spring.address.AddressVO;

//웹 URL을 /update.do 로 매핑 처리함 : 서블릿 파일로 HttpServlet 상속 AddressController 클래스 작성
@WebServlet("/update.do")
public class AddressController extends HttpServlet {
   private static final long serialVersionUID = 1L;
       
   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      process(request, response);
   }


   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      process(request, response);
   }

   private void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
      // 인코딩 타입 설정
      request.setCharacterEncoding("utf-8");
      
      // 기본 주소와 상세 주소를 파라미터로 받은 뒤 변수에 대입해 줍니다.
      String mainAddress = request.getParameter("mainAddress");
      String subAddress = request.getParameter("subAddress");
      
      // vo 객체 생성 후 위에서 받은 변수로 값을 set 처리합니다.
      AddressVO vo = new AddressVO();
      vo.setMainAddress(mainAddress);
      vo.setSubAddress(subAddress);
      
      // error에 관한 해쉬맵 생성 및 Attribute 설정을 처리합니다.
      Map<String, Boolean> errors = new HashMap<String, Boolean>();
      request.setAttribute("errors", errors);
      
      // 검증 메소드를 호출합니다.
      vo.validateMain(errors);
      vo.validateSub(errors);
      
      // DAO 객체 생성 후 insert 메소드를 실행 처리합니다.
      AddressDAO addressDAO = new AddressDAO();
      addressDAO.insertAddress(vo);
      
      // 만약 errors에 값이 존재한다면
      if(!errors.isEmpty()) {
         // 포워딩을 통해 초기화면으로 되돌리게 합니다.
            // 포워드는 RequestDispatcher을 이용하여 응답으로 사용할 jsp 방식으로 넘기는 방식으로 
            // 실행속도가 빠르나 브라우저 입장에서는 URL이 바뀌지 않는 단점이 있습니다.
         
            // 리다이렉트는 두번의 요청과 응답으로 처리되서 실행속도가 느리지만
            // 클라이언트가 URL을 확인할 수 있는 장점이 있습니다.
         
            // 1. 에러가 존재하여 초기화면을 돌리는 작업은 같은 페이지 내에서 일어나므로 포워드로 처리하고
         request.getRequestDispatcher("index.jsp").forward(request, response);
      }
      
         // 2. 에러가 존재하지 않아 성공화면을 보여주는 작업은
         // URL이 바뀔 필요가 있으므로 리다이렉트로 처리했습니다.
         response.sendRedirect("success.jsp");
         
      }
      
	}

home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
	<h1>
		Hello world!  
	</h1>
	
	<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

</body>
</html>

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webapp 폴더 안에 index.jsp 소스코딩</title>
<link rel="stylesheet" type="text/css" media="screen" href="resources/css/bootstrap-3.3.2.min.css">
<script type="text/javascript" src="resources/js/jquery-3.5.1.min.js"></script>

<script type="text/javascript">
	//도로명주소 - 주소검색 팝업을 호출합니다.
	//https://business.juso.go.kr/addrlink/openApi/popupApi.do 웹사이트에서
	//하단 "주소입력화면 소스보기"를 클릭해서 참고합니다.
	function fn_openAddressPopup(){
		var url = "addressAPIPopup.jsp";
		var name= "AddressPopup";
		var option = "width=650, height=500, top=100, left=200, location=no"
		window.open(url, name, option);
		
	}
	
	// 주소검색 팝업 호출 콜백 callback_openAddressPopup() 메서드 입니다.
	function callback_openAddressPopup(aParam){
		document.getElementById("mainAddress").value= aParam["roadAddr"];
	}
</script>
</head>
<body>
	<h2>[처음화면]</h2>
	<!-- update.do 로 데이터 전송 -->
	<form action="update.do" method="post">
		<div class="input-group">
			<span>기본주소</span>
			<br>
			<input type="text" id="mainAddress" name="mainAddress" placeholder="주소를 선택하세요!" size="40" readonly="readonly">
				
				<!-- errors Map 에 값이 해당하는 값이 있을 경우 메시지를 출학하는 부분 -->
				<span>
					<c:if test="${errors.main}">기본 주소를 입력하세요!</c:if>
				</span>
				<button type="button" onclick="javascript:fn_openAddressPopup();">주소 검색</button><br><br>
		</div>
		<div style="margin-top: 0px;">
			<span>상세 주소</span>
			<br>
			<input type="text" id="subAddress" name="subAddress" size="40" placeholder="나머지 주소를 입력하세요!">
				<c:if test="${errors.sub}">상세 주소를 입력하세요!</c:if>
		</div> <br>
		<input type="submit" value="주소등록" />
		<input type="reset" value="입력취소" />
	</form>
</body>
</html>

addressAPIPopup.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webapp 폴더 안에 addressAPIPopup.jsp 소스 코딩</title>
<link rel='stylesheet' type='text/css' media='screen' href='resources/css/bootstrap-3.3.2.min.css'>
<script src="resources/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
// https://business.juso.go.kr/addrlink/openApi/searchApi.do 웹사이트에서
// 하단 "웹 호출 소스 보기"에서 "JSON" 클릭해서 참고 합니다.
// 도로명 주소로 검색 api 연동을 ajax로 처리 합니다.
	function fn_search(){
		$.ajax({
			 url :"https://business.juso.go.kr/addrlink/addrLinkApiJsonp.do"  //인터넷망
			,type:"post"
			,data:$("#searchForm").serialize()
			,dataType:"jsonp"
			,crossDomain:true
			,success:function(jsonStr){
				var errCode = jsonStr.results.common.errorCode;
				var errDesc = jsonStr.results.common.errorMessage;
				if(errCode != "0"){
					alert(errCode+"="+errDesc);
				}else{
					if(jsonStr != null){
						fn_makeListJson(jsonStr);
					}
				}
			}
		    ,error: function(xhr,status, error){
		    	alert("에러발생");
		    }
		});
	}
	
	// 결과 테이블 생성: 위에서 호출받아서 처리할 fn_makeListJson(jsonStr) 메서드 선언
	function fn_makeListJson(jsonStr){
		var htmlStr = "";
		$(jsonStr.results.juso).each(function(){
			htmlStr += "<tr onclick=\"javascript:chooseAddress('"+this.roadAddr+"', '"+this.jibunAddr+"', '"+this.zipNo+"');\">";
			htmlStr += "<td>"
			htmlStr += "<dl>"+this.roadAddr+"</dl>";
			htmlStr += "<dl>"+this.jibunAddr+"</dl>";
			htmlStr += "</td>"
			htmlStr += "<td>"+this.zipNo+"</td>";
			htmlStr += "</tr>";
		});
		$("#addressTableTbody").html(htmlStr);
	}
	
	// Enter 키 이벤트 처리 enterSearch() 메서드 선언
	function enterSearch() {
		var evt_code = (window.netscape) ? ev.which : event.keyCode;
		if (evt_code == 13) {    
			event.keyCode = 0;  
			fn_search(); //jsonp사용시 enter검색 
		} 
	}
	
	// 주소 선택
	function chooseAddress(roadAddr, jibunAddr, zipNo) {
		var aParam = [];
		aParam["roadAddr"] = roadAddr;
        // aParam["jibunAddr"] = jibunAddr;   // 필요시 추가 활용함
        // aParam["zipNo"] = zipNo;          // 필요시 추가 활용함
        
        opener.callback_openAddressPopup(aParam);
        window.close();
	}
</script>
</head>
<body>
	<div class="container" style="margin-top:25px;">
		<div id ="memberSearchDiv" class="text-center">
			<form name="searchForm" id="searchForm" method="post" class="navbar-form navbar=left" role="search" onsubmit="event.preventDefault();">
				<input type="hidden" name="currentPage" value="1"/> 
				<input type="hidden" name="countPerPage" value="100"/>
				<input type="hidden" name="resultType" value="json"/>  
				<input type="hidden" name="confmKey" id="confmKey" value="devU01TX0FVVEgyMDIzMTEwNjE1MTU1MzExNDI0NTU="/><!-- 요청 변수 설정 (승인키) -->
				<div class="form-group">
					<input type="text" width="80px" id="keyword" name="keyword" class="form-control" placeholder="도로명 + 건물 번호, 건물명, 지번을 입력하세요" onkeypress="javascript:enterSearch();" />
				</div>
				<input type="button" class="btn btn-default" onclick="javascript:fn_search();" value="주소 검색하기" />
			</form>
		</div>
		<div>
			<table class="table table-hover">
				<thead>
					<tr>
						<th>주소</th>
						<th>우편번호</th>
					</tr>
				</thead>
				<tbody id="addressTableTbody">
					
				</tbody>
			</table>
		</div>
	</div>
	
</body>
</html>

dbconnTest.jsp

<%@page import="com.openapi.spring.common.JDBCUtil"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webapp 폴더 안에 dbconnTest.jsp 소스 코딩</title>
</head>
<body>
    <!-- JDBCUtil 활용 OracleDB 연결 접속을 확인해 봅니다. -->
   <% 
      try (Connection conn = JDBCUtil.getConnection()){
         out.println("커넥션 연결 성공함");
         
      } catch (SQLException e) {
         out.println("커넥션 연결 실패함 : " + e.getMessage());
         application.log("커넥션 연결 실패", e);
      }
   %>
</body>
</html>

 success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>webapp 폴더 안에 success.jsp 소스 코딩</title>
</head>
<body>
	<h2> * 주소 정보가 제대로 등록 처리 되었습니다!</h2>
	<br>
	<form action="index.jsp">
		<input type="submit" value="처음으로">
	</form>
</body>
</html>
반응형