UserDto
public class UserDto {
@Schema(description = "프로필 업데이트 요청")
public record ProfileUpdateRequest(
@Schema(description = "사용자 이름", example = "홍길동")
@NotBlank(message = "이름은 필수 입력값입니다.")
String name,
@Schema(description = "휴대폰 번호", example = "010-1234-5678")
@Pattern(regexp = "^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$", message = "휴대폰 번호 형식이 올바르지 않습니다.")
String phone
) {
}
@Schema(description = "비밀번호 변경 요청")
public record PasswordChangeRequest(
@Schema(description = "현재 비밀번호", example = "currentPass123")
@NotBlank(message = "현재 비밀번호는 필수 입력값입니다.")
String currentPassword,
@Schema(description = "새 비밀번호", example = "newPass456")
@NotBlank(message = "새 비밀번호는 필수 입력값입니다.")
@Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다.")
String newPassword
) {
}
@Builder
@Schema(description = "사용자 응답 정보")
public record UserResponse(
@Schema(description = "사용자 ID", example = "1")
Long id,
@Schema(description = "이메일", example = "user@example.com")
String email,
@Schema(description = "이름", example = "홍길동")
String name,
@Schema(description = "휴대폰 번호", example = "010-1234-5678")
String phone,
@Schema(description = "사용자 역할", example = "일반 사용자")
String role
) {
public static UserResponse from(User user) {
return UserResponse.builder()
.id(user.getId())
.email(user.getEmail())
.name(user.getName())
.phone(user.getPhone())
.role(user.getRole().getDisplayName())
.build();
}
}
}
ProductDto
public class ProductDto {
@Schema(description = "상품 생성 요청")
public record CreateRequest(
@Schema(description = "상품명", example = "새 노트북")
@NotBlank(message = "상품명은 필수 입력값입니다.")
String name,
@Schema(description = "상품 설명", example = "거의 사용하지 않은 노트북입니다.")
String description,
@Schema(description = "가격", example = "1000000")
@NotNull(message = "가격은 필수 입력값입니다.")
@Min(value = 0)
Long price,
@Schema(description = "재고 수량", example = "1")
@NotNull(message = "재고는 필수 입력값입니다.")
@Min(value = 1, message = "재고는 최소 1개 이상이어야 합니다.")
Integer stock,
@Schema(description = "상품 카테고리", example = "ELECTRONICS")
@NotNull(message = "카테고리는 필수 입력값입니다.")
ProductCategory category
) {}
@Schema(description = "상품 수정 요청")
public record UpdateRequest(
@Schema(description = "상품명", example = "새 노트북")
@NotBlank(message = "상품명은 필수 입력값입니다.")
String name,
@Schema(description = "상품 설명", example = "거의 사용하지 않은 노트북입니다.")
String description,
@Schema(description = "가격", example = "900000")
@NotNull(message = "가격은 필수 입력값입니다.")
@Min(value = 100, message = "가격은 최소 100원 이상이어야 합니다.")
Long price,
@Schema(description = "재고 수량", example = "1")
@NotNull(message = "재고는 필수 입력값입니다.")
@Min(value = 1, message = "재고는 최소 1개 이상이어야 합니다.")
Integer stock,
@Schema(description = "상품 카테고리", example = "ELECTRONICS")
@NotNull(message = "카테고리는 필수 입력값입니다.")
ProductCategory category,
@Schema(description = "상품 상태", example = "ACTIVE")
ProductStatus status
){}
@Builder
@Schema(description = "상품 응답")
public record ProductResponse(
@Schema(description = "상품 ID", example = "1")
Long id,
@Schema(description = "상품명", example = "새 노트북")
String name,
@Schema(description = "상품 설명", example = "거의 사용하지 않은 노트북입니다.")
String description,
@Schema(description = "가격", example = "1000000")
Long price,
@Schema(description = "재고 수량", example = "1")
Integer stock,
@Schema(description = "카테고리 표시명", example = "전자기기")
String category,
@Schema(description = "상품 상태", example = "판매중")
String status,
@Schema(description = "썸네일 이미지 URL", example = "https://example.com/thumbnail.jpg")
String thumbnailUrl,
@Schema(description = "이미지 URL 목록")
List<String> imageUrls,
@Schema(description = "판매자 ID", example = "123")
Long sellerId,
@Schema(description = "판매자 이름", example = "홍길동")
String sellerName
) {
public static ProductResponse from(Product product) {
return ProductResponse.builder()
.id(product.getId())
.name(product.getName())
.description(product.getDescription())
.price(product.getPrice())
.stock(product.getStock())
.category(product.getCategory().getDisplayName())
.status(product.getStatus().getDisplayName())
.thumbnailUrl(product.getRepresentativeThumbnailUrl())
.imageUrls(product.getImages().stream()
.map(ProductImage::getImageUrl)
.collect(Collectors.toList()))
.sellerId(product.getSeller().getId())
.sellerName(product.getSeller().getName())
.build();
}
}
}
UserProfileDto
public class UserProfileDto {
@Builder
@Schema(description = "판매 상품 내역")
public record SellingProductResponse(
@Schema(description = "상품 ID", example = "1")
Long productId,
@Schema(description = "상품명", example = "새 노트북")
String name,
@Schema(description = "가격", example = "1000000")
Long price,
@Schema(description = "카테고리", example = "전자기기")
String category,
@Schema(description = "상품 상태", example = "판매중")
String status,
@Schema(description = "썸네일 URL", example = "https://example.com/thumbnail.jpg")
String thumbnailUrl,
@Schema(description = "구매자 이름", example = "김철수")
String buyerName,
@Schema(description = "판매 완료 날짜", example = "2025-04-21T12:00:00")
LocalDateTime soldDate,
@Schema(description = "상품 등록 날짜", example = "2025-04-20T10:00:00")
LocalDateTime createdDate
) {}
@Builder
@Schema(description = "판매 내역 페이지 응답")
public record SellingHistoryResponse(
@Schema(description = "판매 중인 상품 목록")
List<SellingProductResponse> activeProducts,
@Schema(description = "판매 완료된 상품 목록")
List<SellingProductResponse> soldProducts,
@Schema(description = "총 상품 수", example = "10")
int totalProductCount
) {}
@Builder
@Schema(description = "구매 내역 항목")
public record PurchaseItem(
@Schema(description = "상품 ID", example = "1")
Long productId,
@Schema(description = "상품명", example = "중고 책")
String productName,
@Schema(description = "구매 가격", example = "15000")
Long price,
@Schema(description = "카테고리", example = "도서")
String category,
@Schema(description = "썸네일 URL", example = "https://example.com/thumbnail.jpg")
String thumbnailUrl,
@Schema(description = "판매자 이름", example = "이영희")
String sellerName,
@Schema(description = "구매 날짜", example = "2025-04-20T14:30:00")
LocalDateTime purchaseDate
) {}
@Builder
@Schema(description = "구매 내역 페이지 응답")
public record PurchaseHistoryResponse(
@Schema(description = "구매 내역 목록")
List<PurchaseItem> purchases,
@Schema(description = "총 구매 수", example = "5")
int totalPurchaseCount
) {}
@Builder
@Schema(description = "프로필 요약 정보")
public record ProfileSummaryResponse(
@Schema(description = "사용자 ID", example = "1")
Long userId,
@Schema(description = "이메일", example = "user@example.com")
String email,
@Schema(description = "이름", example = "홍길동")
String name,
@Schema(description = "총 판매 중인 상품 수", example = "3")
int totalSellingCount,
@Schema(description = "총 판매 완료 수", example = "7")
int totalSoldCount,
@Schema(description = "총 구매 수", example = "15")
int totalPurchaseCount,
@Schema(description = "평균 평점", example = "4.5")
double averageRating,
@Schema(description = "가입 날짜", example = "2025-01-01T09:00:00")
LocalDateTime joinDate
) {}
}
ResponseDto
@Getter
@Builder
@Schema(description = "통합 응답 DTO")
public class ResponseDTO<T> {
@Schema(description = "요청 성공 여부", example = "true")
private final boolean success;
@Schema(description = "HTTP 상태 코드", example = "200")
private final int status;
@Schema(description = "응답 메시지", example = "요청이 성공했습니다.")
private final String message;
@Schema(description = "응답 데이터")
private final T data;
@Schema(description = "응답 시간", example = "2025-04-21T12:00:00")
private final LocalDateTime timestamp;
public static <T> ResponseDTO<T> success(T data) {
return ResponseDTO.<T>builder()
.success(true)
.status(200)
.message("요청이 성공했습니다.")
.data(data)
.timestamp(LocalDateTime.now())
.build();
}
public static <T> ResponseDTO<T> success(T data, String message) {
return ResponseDTO.<T>builder()
.success(true)
.status(200)
.message(message)
.data(data)
.timestamp(LocalDateTime.now())
.build();
}
public static <T> ResponseDTO<T> error(int status, String message) {
return ResponseDTO.<T>builder()
.success(false)
.status(status)
.message(message)
.timestamp(LocalDateTime.now())
.build();
}
public static <T> ResponseDTO<T> error(int status, String message, T data) {
return ResponseDTO.<T>builder()
.success(false)
.status(status)
.message(message)
.data(data)
.timestamp(LocalDateTime.now())
.build();
}
}
AuthDto
public class AuthDto {
@Schema(description = "회원가입 요청")
public record SignupRequest(
@Schema(description = "이메일 주소", example = "user@example.com")
@NotBlank(message = "이메일은 필수 입력값입니다.")
@Email(message = "이메일 형식이 올바르지 않습니다.")
String email,
@Schema(description = "비밀번호 (최소 8자 이상)", example = "password123")
@NotBlank(message = "비밀번호는 필수 입력값입니다.")
@Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다.")
String password,
@Schema(description = "사용자 이름", example = "홍길동")
@NotBlank(message = "이름은 필수 입력값입니다.")
String name,
@Schema(description = "휴대폰 번호", example = "010-1234-5678")
@Pattern(regexp = "^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$", message = "휴대폰 번호 형식이 올바르지 않습니다.")
String phone
) {
}
@Schema(description = "로그인 요청")
public record LoginRequest(
@Schema(description = "이메일 주소", example = "user@example.com")
@NotBlank(message = "이메일은 필수 입력값입니다.")
@Email(message = "이메일 형식이 올바르지 않습니다.")
String email,
@Schema(description = "비밀번호", example = "password123")
@NotBlank(message = "비밀번호는 필수 입력값입니다.")
String password
) {
}
@Builder
@Schema(description = "토큰 응답")
public record TokenResponse(
@Schema(description = "JWT 액세스 토큰", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
String accessToken,
@Schema(description = "JWT 리프레시 토큰", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
String refreshToken,
@Schema(description = "토큰 타입", example = "Bearer")
String tokenType,
@Schema(description = "액세스 토큰 만료 시간(초)", example = "3600")
Long expiresIn
) {
}
@Schema(description = "토큰 갱신 요청")
public record TokenRefreshRequest(
@Schema(description = "리프레시 토큰", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
@NotBlank(message = "리프레시 토큰은 필수 입력값입니다.")
String refreshToken
) {
}
}
EmailVerificationDto
public class EmailVerificationDto {
@Schema(description = "이메일 인증 요청")
public record EmailVerificationRequest(
@Schema(description = "학교 이메일 주소", example = "student@office.skhu.ac.kr")
@NotBlank(message = "이메일은 필수 입력값입니다.")
@Email(message = "이메일 형식이 올바르지 않습니다.")
String email
) {}
@Schema(description = "이메일 인증 코드 확인 요청")
public record VerificationCodeRequest(
@Schema(description = "학교 이메일 주소", example = "student@office.skhu.ac.kr")
@NotBlank(message = "이메일은 필수 입력값입니다.")
@Email(message = "이메일 형식이 올바르지 않습니다.")
String email,
@Schema(description = "6자리 인증 코드", example = "123456")
@NotBlank(message = "인증 코드는 필수 입력값입니다.")
String verificationCode
) {}
@Schema(description = "이메일 인증 응답")
public record EmailVerificationResponse(
@Schema(description = "처리 성공 여부", example = "true")
boolean success,
@Schema(description = "응답 메시지", example = "인증 이메일이 발송되었습니다.")
String message
) {}
}
PasswordDto
public class PasswordDto {
@Schema(description = "비밀번호 재설정 요청")
public record PasswordResetRequest(
@Schema(description = "사용자 이메일 주소", example = "user@example.com")
@NotBlank(message = "이메일은 필수 입력값입니다.")
@Email(message = "이메일 형식이 올바르지 않습니다.")
String email
) {}
@Schema(description = "비밀번호 재설정 검증 요청")
public record PasswordResetVerifyRequest(
@Schema(description = "비밀번호 재설정 토큰", example = "1234567890abcdef")
@NotBlank(message = "토큰은 필수 입력값입니다.")
String token,
@Schema(description = "새 비밀번호 (최소 8자 이상)", example = "newPassword123")
@NotBlank(message = "새 비밀번호는 필수 입력값입니다.")
@Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다.")
String newPassword
) {}
@Builder
@Schema(description = "비밀번호 재설정 응답")
public record PasswordResetResponse(
@Schema(description = "처리 성공 여부", example = "true")
boolean success,
@Schema(description = "응답 메시지", example = "비밀번호가 성공적으로 변경되었습니다.")
String message
) {}
}
예시 이미지
