Skip to content

Commit 574ca24

Browse files
committed
hotfix: ISBN 검증 강화 및 검색 결과 처리 개선
**IsbnValidator** - 기존 정규식 검사에 더해 ISBN-10, ISBN-13의 체크섬 검증 추가 - 하이픈(-), 공백, 소문자 'x' 처리용 전처리 기능 추가 **AladinBookQueryService** - filter → mapNotNull로 변경하여 ISBN-10만 있는 경우 ISBN-13 변환 후 포함 - isbn13 필드 누락 문제 해결 - totalResults를 필터링 후 아이템 개수로 수정하여 데이터 정합성 확보
1 parent 84f1e58 commit 574ca24

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

apis/src/main/kotlin/org/yapp/apis/book/service/AladinBookQueryService.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AladinBookQueryService(
2424
private val log = KotlinLogging.logger {}
2525

2626
override fun searchBooks(request: BookSearchRequest): BookSearchResponse {
27-
log.info("Service - Converting BookSearchRequest to AladinBookSearchRequest and calling Aladin API for book search.")
27+
log.info { "Service - Converting BookSearchRequest to AladinBookSearchRequest and calling Aladin API for book search." }
2828
val aladinSearchRequest = AladinBookSearchRequest.of(
2929
request.validQuery(),
3030
request.queryType,
@@ -35,32 +35,37 @@ class AladinBookQueryService(
3535
request.categoryId
3636
)
3737
val response: AladinSearchResponse = aladinApi.searchBooks(aladinSearchRequest)
38-
.onSuccess { response ->
39-
log.info("Aladin search successful for query: '${request.query}', total results: ${response.totalResults}")
38+
.onSuccess { res ->
39+
log.info { "Aladin search successful for query: '${request.query}', total results: ${res.totalResults}" }
4040
}
4141
.getOrElse { exception ->
42-
log.error("Failed to call Aladin search API for request: '$request'", exception)
42+
log.error(exception) { "Failed to call Aladin search API for request: '$request'" }
4343
throw BookException(BookErrorCode.ALADIN_API_SEARCH_FAILED, exception.message)
4444
}
4545

46-
val filteredItems = response.item.filter { item ->
47-
getValidAndFilteredIsbn13(item) != null
46+
log.info { "Before filtering - Full Response: $response" }
47+
48+
val transformedItems = response.item.mapNotNull { item ->
49+
val validIsbn13 = getValidAndFilteredIsbn13(item)
50+
validIsbn13?.let { item.copy(isbn13 = it) }
4851
}
4952

5053
val filteredResponse = AladinSearchResponse(
5154
version = response.version,
5255
title = response.title,
5356
link = response.link,
5457
pubDate = response.pubDate,
55-
totalResults = response.totalResults,
58+
totalResults = transformedItems.size,
5659
startIndex = response.startIndex,
5760
itemsPerPage = response.itemsPerPage,
5861
query = response.query,
5962
searchCategoryId = response.searchCategoryId,
6063
searchCategoryName = response.searchCategoryName,
61-
item = filteredItems
64+
item = transformedItems
6265
)
6366

67+
log.info { "After filtering - Full Response: $filteredResponse" }
68+
6469
return BookSearchResponse.from(filteredResponse)
6570
}
6671

global-utils/src/main/kotlin/org/yapp/globalutils/validator/IsbnValidator.kt

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,47 @@ object IsbnValidator {
66
private val ISBN10_REGEX = Regex(RegexUtils.ISBN10_PATTERN)
77
private val ISBN13_REGEX = Regex(RegexUtils.ISBN13_PATTERN)
88

9-
fun isValidIsbn10(isbn: String): Boolean {
10-
return isbn.matches(ISBN10_REGEX)
9+
fun isValidIsbn10(isbnInput: String): Boolean {
10+
val isbn = preprocess(isbnInput)
11+
12+
if (!isbn.matches(ISBN10_REGEX)) {
13+
return false
14+
}
15+
16+
var sum = 0
17+
for (i in 0 until 9) {
18+
val digit = isbn[i].toString().toInt()
19+
sum += digit * (10 - i)
20+
}
21+
22+
val lastChar = isbn[9]
23+
val checkDigit = if (lastChar == 'X') 10 else lastChar.toString().toInt()
24+
25+
return (sum + checkDigit) % 11 == 0
26+
}
27+
28+
fun isValidIsbn13(isbnInput: String): Boolean {
29+
val isbn = preprocess(isbnInput)
30+
31+
if (!isbn.matches(ISBN13_REGEX)) {
32+
return false
33+
}
34+
35+
var sum = 0
36+
for (i in 0 until 12) {
37+
val digit = isbn[i].toString().toInt()
38+
sum += if (i % 2 == 0) digit else digit * 3
39+
}
40+
41+
val calculatedCheckDigit = (10 - (sum % 10)) % 10
42+
val actualCheckDigit = isbn[12].toString().toInt()
43+
44+
return calculatedCheckDigit == actualCheckDigit
1145
}
1246

13-
fun isValidIsbn13(isbn: String): Boolean {
14-
return isbn.matches(ISBN13_REGEX)
47+
private fun preprocess(isbn: String): String {
48+
return isbn.replace("-", "")
49+
.replace(" ", "")
50+
.uppercase()
1551
}
1652
}

0 commit comments

Comments
 (0)