
대학교 캡스톤디자인 중 배송 주소를 입력받고 데이터베이승에 저장하기 위해 외부 API를 찾아보던 중 Kakao 주소 API를 적용해보기로 하였다.
//address.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/submit/new" method="post" enctype="application/json">
<input type="text" id="sample6_postcode" name="postcode" placeholder="우편번호">
<input type="button" onclick="sample6_execDaumPostcode()" value="우편번호 찾기"><br>
<input type="text" id="sample6_address" name="postAddress" placeholder="주소"><br>
<input type="text" id="sample6_detailAddress" name="detailAddress" placeholder="상세주소">
<input type="text" id="sample6_extraAddress" name="extraAddress" placeholder="참고항목">
<input type="submit" value="전송">
</form>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script>
function sample6_execDaumPostcode() {
new daum.Postcode({
oncomplete: function (data) {
// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
// 각 주소의 노출 규칙에 따라 주소를 조합한다.
// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
let addr = ''; // 주소 변수
let 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("sample6_extraAddress").value = extraAddr;
} else {
document.getElementById("sample6_extraAddress").value = '';
}
// 우편번호와 주소 정보를 해당 필드에 넣는다.
document.getElementById('sample6_postcode').value = data.zonecode;
document.getElementById("sample6_address").value = addr;
// 커서를 상세주소 필드로 이동한다.
document.getElementById("sample6_detailAddress").focus();
}
}).open();
}
</script>
</body>
</html>
<form> 태그를 사용해서 action 속성에 POST: /summit/new 로 입력된 값들을 서버에 전송합니다.// address.java
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
@Entity
@Getter
@Setter
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "postcode")
private String postcode;
@Column(name = "post_address")
private String postAddress;
@Column(name = "detail_address")
private String detailAddress;
@Column(name = "extra_address")
private String extraAddress;
@Builder
public static Address createAddress(
final String postcode,
final String postAddress,
final String detailAddress,
final String extraAddress
) {
Address address = new Address();
address.postcode = postcode;
address.postAddress = postAddress;
address.detailAddress = detailAddress;
address.extraAddress = extraAddress;
return address;
}
}
import com.example.PostcodeTutorial.domain.Address.application.AddressService;
import com.example.PostcodeTutorial.domain.Address.web.dto.CreateAddressRequest;
import com.example.PostcodeTutorial.domain.Address.web.dto.CreateAddressResponse;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@Controller
public class AddressController {
private final AddressService addressService;
public AddressController(AddressService addressService) {
this.addressService = addressService;
}
@GetMapping("/address")
public String showAddressSearchForm() {
return "address";
}
@GetMapping("/submit")
public String showSubmitForm() {
return "submit";
}
@PostMapping("/submit/new")
public String submitForm(@RequestBody @Valid CreateAddressRequest request) {
Long id = addressService.join(request);
return "redirect:/submit";
}
}
@PostMapping("/submit/new")으로 매핑합니다.DTO
import jakarta.validation.constraints.NotBlank;
import org.springframework.web.bind.annotation.RequestParam;
public record CreateAddressRequest(
@NotBlank String postcode,
@NotBlank String postAddress,
@NotBlank String detailAddress,
String extraAddress,
Long id
) { }
import org.springframework.data.jpa.repository.JpaRepository;
public interface AddressRepository extends JpaRepository<Address, Long> {
}
import com.example.PostcodeTutorial.domain.Address.persistence.Address;
import com.example.PostcodeTutorial.domain.Address.persistence.AddressRepository;
import com.example.PostcodeTutorial.domain.Address.web.dto.CreateAddressRequest;
import com.example.PostcodeTutorial.global.exception.service.PostNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Array;
import static com.example.PostcodeTutorial.global.exception.ErrorCode.NOT_FOUND_POST;
@Service
public class AddressService {
private final AddressRepository addressRepository;
public AddressService(AddressRepository addressRepository) {
this.addressRepository = addressRepository;
}
@Transactional
public Long join(final CreateAddressRequest request) {
Address address = Address.builder()
.postcode(request.postcode())
.postAddress(request.postAddress())
.detailAddress(request.detailAddress())
.extraAddress(request.extraAddress())
.build();
addressRepository.save(address);
return address.getId();
}
}
서버를 실행하여 주소 값을 입력하여 보냈는데
[org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported]해당 에러가 발생하였다.
<form>에서 enctype="application/json"을 사용하여 JSON 형식으로 전송하고 있으나 실제로는 application/x-www-form-urlencoded를 사용하여 요청이 전송되어 문제가 발생했던 것이다. @PostMapping("/submit/new")
public String submitForm(@ModelAttribute @Valid CreateAddressRequest request) {
Long id = addressService.join(request);
return "redirect:/submit";
}
임시적인 방안이지만 application/x-www-form-urlencoded 으로 요청이 전송되기에 Controller 에서 CreateAddressRequest에 있는 @RequestBody 어노테이션을 @ModelAttribute 을 사용하였더니 해결되었다.
JavaScript를 사용하여 AJAX 요청을 수행하면 JSON 형식의 요청을 처리할 수 있다고 한다. 해당 내용을 좀 더 공부하고 코드를 수정해보고자 한다 !

