
사용자가 배송지나 주소를 입력할 때 정확한 도로명 주소를 검색하고 선택할 수 있도록 도와주는 API입니다.
주요 사용처


OnAndHome (백엔드)
├── order/
│ ├── entity/Order.java
│ ├── dto/CreateOrderRequest.java
│ └── OrderService.java
OnAndHomeFront (프론트엔드)
├── public/
│ └── index.html # Daum 스크립트 로드
└── src/
└── pages/Checkout.jsx
@Entity
@Getter
@Setter
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
// 배송 정보
private String recipientName; // 받는 사람
private String recipientPhone; // 연락처
private String shippingAddress; // 배송지 주소
private String shippingRequest; // 배송 요청사항
@Column(nullable = false)
private int totalPrice;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private OrderStatus status;
}
@Getter
@Setter
public class CreateOrderRequest {
private Long userId;
private List<OrderItemRequest> orderItems;
private String paymentMethod;
// 배송 정보
private String recipientName;
private String recipientPhone;
private String shippingAddress;
private String shippingRequest;
}
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepo;
private final UserRepository userRepo;
@Transactional
public OrderDTO createOrder(CreateOrderRequest request) {
// 사용자 조회
User user = userRepo.findById(request.getUserId())
.orElseThrow(() -> new IllegalArgumentException(
"사용자를 찾을 수 없습니다."));
// 주문 생성
Order order = Order.create(user, orderItems, paymentMethod);
// 배송 정보 저장
order.setRecipientName(request.getRecipientName());
order.setRecipientPhone(request.getRecipientPhone());
order.setShippingAddress(request.getShippingAddress());
order.setShippingRequest(request.getShippingRequest());
// 주소 유효성 검증
validateAddress(request.getShippingAddress());
// 저장
return OrderDTO.fromEntity(orderRepo.save(order));
}
/**
* 주소 유효성 검증
*/
private void validateAddress(String address) {
// 1. 빈 값 체크
if (address == null || address.trim().isEmpty()) {
throw new IllegalArgumentException(
"배송지를 입력해주세요.");
}
// 2. 길이 체크
if (address.length() < 10) {
throw new IllegalArgumentException(
"배송지가 너무 짧습니다.");
}
if (address.length() > 200) {
throw new IllegalArgumentException(
"배송지가 너무 깁니다.");
}
// 3. 특수문자 체크
if (address.matches(".*[<>\"'].*")) {
throw new IllegalArgumentException(
"배송지에 사용할 수 없는 문자가 포함되어 있습니다.");
}
}
}
OnAndHomeFront/public/index.html
<head>
<!-- Daum 우편번호 서비스 -->
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
</head>
const handleAddressSearch = () => {
new window.daum.Postcode({
oncomplete: function (data) {
// 도로명 주소 우선, 없으면 지번 주소
const address = data.roadAddress || data.jibunAddress;
setShippingAddress(address);
},
}).open();
};

1. 정상 케이스 - 주문 생성
POST URL http://localhost:8080/api/orders
Headers
KeyValueContent-Typeapplication/jsonAuthorizationBearer {your_token}
{
"userId": 1,
"orderItems": [
{
"productId": 10,
"quantity": 2
}
],
"paymentMethod": "CARD",
"recipientName": "김현수",
"recipientPhone": "010-1234-5678",
"shippingAddress": "서울특별시 강남구 테헤란로 123 (선릉타워)",
"shippingRequest": "문 앞에 놓아주세요"
}
기대 결과
{
"success": true,
"message": "주문이 완료되었습니다.",
"data": {
"orderId": 42,
"shippingAddress": "서울특별시 강남구 테헤란로 123 (선릉타워)"
}
}
{
"userId": 1,
"orderItems": [
{
"productId": 10,
"quantity": 2
}
],
"paymentMethod": "CARD",
"recipientName": "김현수",
"recipientPhone": "010-1234-5678",
"shippingAddress": "서울특별시 강남구 테헤란로 123 (선릉타워)",
"shippingRequest": "문 앞에 놓아주세요"
}