본문 바로가기
[ JAVA ]/JAVA Spring

[ Spring ] 도로명주소 API 연동

by 환이s 2023. 4. 27.


도로명주소 (DAUM API)

 

오늘은 게시판 기능 추가 하기 전, 회원 가입에 필요한 우편번호, 주소 검색을 API를 활용하여 검색된 주소가 회원 가입 페이지의 주소 필드에 입력되는 방법을 포스팅 해보려 합니다.

 

우선 daum api 주소인 http://postcode.map.daum.net/guide

 

Daum 우편번호 서비스

우편번호 검색과 도로명 주소 입력 기능을 너무 간단하게 적용할 수 있는 방법. Daum 우편번호 서비스를 이용해보세요. 어느 사이트에서나 무료로 제약없이 사용 가능하답니다.

postcode.map.daum.net

 

들어가시면 자세하게 다음에서 사용 방법까지 친절하게 설명해주고 있습니다.

사용하고자 하는 코드를 정해서 변수명만 수정해서 사용하시면 됩니다.

 

 

예제 코드로 member 테이블에 주소 컬럼을 추가하고 회원가입 기능을 추가해 보겠습니다.

 


MEMBER TABLE

 

-- 기존 테이블
create table member(
userid varchar2(50) not null primary key,
passwd varchar2(50) not null,
name varchar2(50) not null,
email varchar2(50),
join_date date default sysdate
);

-- 컬럼 추가
alter table member add zipcode varchar2(7);
alter table member add address1 varchar2(200);
alter table member add address2 varchar2(200);

commit;

 

칼럼을 추가하면 프로젝트 구조를 수정해야 하는데, 먼저 DTO에 변수 추가 합니다.

 


DTO

 

DTO에서는 간단하게 getter/setter , toString 만 생성하겠습니다.

package com.example.spring.model.member.dto;

import java.util.Date;

public class MemberDTO {

	
	private String userid;
	private String passwd; 
	private String name; 
	private String email; 
	private Date join_date;
	private String zipcode; // 추가 우편번호
	private String address1; // 추가 도로명 주소
	private String address2; // 추가 상세 주소
	
	
	public String getZipcode() {
		return zipcode;
	}
	public void setZipcode(String zipcode) {
		this.zipcode = zipcode;
	}
	public String getAddress1() {
		return address1;
	}
	public void setAddress1(String address1) {
		this.address1 = address1;
	}
	public String getAddress2() {
		return address2;
	}
	public void setAddress2(String address2) {
		this.address2 = address2;
	}
	public String getUserid() {
		return userid;
	}
	public void setUserid(String userid) {
		this.userid = userid;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Date getJoin_date() {
		return join_date;
	}
	public void setJoin_date(Date join_date) {
		this.join_date = join_date;
	}

	@Override
	public String toString() {
		return "MemberDTO [userid=" + userid + ", passwd=" + passwd + ", name=" + name + ", email=" + email
				+ ", join_date=" + join_date + ", zipcode=" + zipcode + ", address1=" + address1 + ", address2="
				+ address2 + "]";
	}
	public MemberDTO() {
		
	
	} 
	
	
	
}

 

다음으로 menu 페이지에 비로그인 상태 코드 줄에  회원가입 기능 추가 합니다.


menu.jsp

 

메뉴에서는 클릭 시 해당 urlController에 요청을 보내서 폼으로 이동할 수 있게 해 줍니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="path" value="${pageContext.request.contextPath}" />
<div style="text-align: center;"> 
 <a href="${path}">Home</a> |
  <a href="${path}/member/address.do">도로명주소</a> |
 <a href="${path}/shop/product/list.do">상품목록</a> |
 <c:if test="${sessionScope.admin_userid == null}">
	 <a href="${path}/memo/list.do">메모장</a> |
	  <a href="${path}/board/list.do">게시판</a> |
	 <a href="${path}/upload/uploadForm">업로드 테스트</a> |
	  <a href="${path}/upload/uploadAjax">업로드(Ajax)</a> |
 </c:if>
 
 <c:if test="${sessionScope.userid != null && sessionScope.admin_userid == null}">
 	<a href="${path}/shop/cart/list.do">장바구니</a> |
 </c:if>
 
 <div style="text-align: right;">
  <c:choose>
   <c:when test="${sessionScope.userid == null}">
    <!-- 로그인하지 않은 상태 -->
    <a href="${path}/member/write.do">회원가입</a> | <!-- 기능 추가 -->
  	<a href="${path}/member/login.do">로그인</a> |
  	<a href="${path}/admin/login.do">관리자 로그인</a> |
   </c:when>
   <c:otherwise>
    <!-- 로그인한 상태 -->
    ${sessionScope.name}님이 로그인중입니다.    
    <a href="${path}/member/view.do?userid=${sessionScope.userid}">회원정보</a>
    <a href="${path}/member/logout.do">로그아웃</a>
   </c:otherwise>	
  </c:choose>
 </div>
</div>
<hr>

memberController

 

Controller에서는 간단하게 폼으로 리턴 시켜줍니다.

 

	@RequestMapping("write.do") //폼으로 이동
	public String write() {
		return "member/write";
	}

write.jsp

 

회원가입 폼에서는 간단한 유효성 검사, 도로명 주소 코드를 가져오려고 하는데,

먼저 도로명 주소 홈페이지에서 스크립트 코드를 복사합니다.

 

스크롤을 내려보면 사용 방식이 자세하게 설명되어 있는데,

저는 사용자가 선택한 값 이용하기 코드를 가져오려고 합니다.

 

 

해당 방식의 예제 코드보기 클릭하시면 자바 스크립트 코드가 나옵니다.

 

 

그다음 회원가입 폼 스크립트 코드에 넣어줍니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<title>회원 가입</title>
<%@ include file="../include/header.jsp" %>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script type="text/javascript">
function daumZipCode() {
	 new daum.Postcode({
         oncomplete: function(data) {
             // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

             // 각 주소의 노출 규칙에 따라 주소를 조합한다.
             // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
             var addr = ''; // 주소 변수
             var extraAddr = ''; // 참고항목 변수

             //사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
             if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
                 addr = data.roadAddress;
             } else { // 사용자가 지번 주소를 선택했을 경우(J)
                 addr = data.jibunAddress;
             }

             // 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
             if(data.userSelectedType === 'R'){
                 // 법정동명이 있을 경우 추가한다. (법정리는 제외)
                 // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
                 if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
                     extraAddr += data.bname;
                 }
                 // 건물명이 있고, 공동주택일 경우 추가한다.
                 if(data.buildingName !== '' && data.apartment === 'Y'){
                     extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
                 }
                 // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
                 if(extraAddr !== ''){
                     extraAddr = ' (' + extraAddr + ')';
                 }
                 // 조합된 참고항목을 해당 필드에 넣는다.
                 document.getElementById("address1").value = extraAddr;
             
             } else {
                 document.getElementById("address2").value = '';
             }

             // 우편번호와 주소 정보를 해당 필드에 넣는다.
             document.getElementById('zipcode').value = data.zonecode;
             document.getElementById("address1").value = addr;
             // 커서를 상세주소 필드로 이동한다.
             document.getElementById("address2").focus();
         }
     }).open();
 }
function check() {
	//아이디 체크
	var userid = $("#userid").val();
	if(userid ==""){
		alert("아이디는 필수 입력입니다.");
		$("#userid").focus();
		return;
	}
	//비밀번호 체크
	var passwd = $("#passwd").val();
	if(passwd ==""){
		alert("비밀번호는 필수 입력입니다.");
		$("#passwd").focus();
		return;
	}
	//이름 체크
	var name = $("#name").val();
	if(name ==""){
		alert("이름은 필수 입력입니다.");
		$("#name").focus();
		return;
	}
	//이메일 체크
	var email = $("#email").val();
	if(email ==""){
		alert("이메일은 필수 입력입니다.");
		$("#email").focus();
		return;
	}
	//주소 체크
	var zipcode = $("#zipcode").val();
	if(zipcode ==""){
		alert("우편번호 찾기를 누르세요.");
		$("#zipcode").focus();
		return;
	}
	document.form1.submit();
}

</script>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<div class="container">
	<h2>회원등록</h2>
	<form name="form1" method="post" action="${path }/member/insert.do">
	<div class="form-group">
	아이디 <input class="form-control" placeholder="아이디" name="userid" id="userid" type="text">
	</div>
		<div class="form-group">
	비밀번호 <input class="form-control" placeholder="비밀번호" name="passwd" id="passwd" type="password">
	</div>
	<div class="form-group">
	이름 <input class="form-control" placeholder="이름" name="name" id="name" type="text">
	</div>
	<div class="form-group">
	이메일 <input class="form-control" placeholder="이메일" name="email" id="email" type="text">
	</div>
	<div class="form-group">
	주소 <br>
	 <input class="form-control" style="width: 40%; display: inline;"  placeholder="우편번호" name="zipcode" id="zipcode" type="text" readonly>
	 <button type="button" class="btn btn-default" onclick="daumZipCode()">  <i class="fa fa-search"></i> 우편번호 찾기</button>
	</div>
	<div class="form-group">
	 <input class="form-control" style="top:5px;" placeholder="도로명 주소" name="address1" id="address1" type="text" readonly>
	</div>
	<div class="form-group">
	 <input class="form-control" placeholder="상세 주소" name="address2" id="address2" type="text" >
	</div>
	<input type="button" class="btn btn-lg btn-success btn-block" onclick="check()" value="확인">
	</form>
</div>


</body>
</html>

 

폼 작업이 끝났다면 action 처리를 해줍니다.


memberController

 

요청 들어온 urlService 단과 연결해 주고, 회원가입 시 포워딩은 home으로 리턴해줍니다.

 

	//회원 입력
	@RequestMapping("insert.do")
	public String insert(@ModelAttribute MemberDTO dto) {
		memberService.insertMember(dto);
		return "home";
	}

memberService

 

	@Override
	public void insertMember(MemberDTO dto) {
		memberDao.insertMember(dto);
	}

memberDAO

 

예제 코드라서 간단하게 요청만 보내는 코드로 작성했습니다.

DAO에서는 DB에 요청을 보냅니다.

	@Override
	public void insertMember(MemberDTO dto) {
		sqlSession.insert("member.memberinsert", dto);
		
	}

memberMapper

 

처음에 주소 칼럼을 생성했기 때문에 각 칼럼에 맞춰서 추가로 함수 처리를 해줍니다.

 

	<insert id="memberinsert">
	insert into member(userid,passwd,name,email,zipcode,address1,address2)
	values(#{userid},#{passwd},#{name},#{email},#{zipcode},#{address1},#{address2})
	</insert>

출력

 

< main >

 


< write.jsp >

 

 

API가 제대로 작동하는지 확인해 봅니다.

 

 

 

상세 주소까지 작성하고, 확인 버튼을 눌러서 데이터가 제대로 들어갔는지 확인해 봅니다.

 


< main >

 

 

< table >

 


마치며

 

오늘은 간단한 회원가입 기능으로 도로명주소 API 사용법에 대해서 알아보았습니다.

다음 포스팅에서 뵙겠습니다.

728x90