-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] - 좋아요 순 여행기 목록 조회 페이징 캐싱 #631
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
64c42a9
feat: 좋아요 순 여행기 목록 조회에 Cache 적용
eunjungL 93a03bb
feat: PageImpl Deserializer 추가
eunjungL b9b6c7a
fix: PageDeserializer 제대로 동작되게 수정
eunjungL c2278c7
refactor: PageDeserializer 클래스 코드 정리
eunjungL 0fd25ac
fix: Sort 객체가 무조건 unsorted로 처리되던 현상 수정
eunjungL 813750b
style: 필요 없는 로그 제거
eunjungL 5889279
feat: 여행기 컨텐츠 페이지 캐싱 범위 설정 (PageNumber가 4이하인 것들만 캐싱)
Libienz 37b982c
refactor: CacheConfig 불필요한 애너테이션 제거 개선
Libienz ca123ae
feat: Cache Default TTL 1시간에서 30분으로 변경
Libienz 537d2f7
Merge branch 'develop/be' into feature/be/#630
Libienz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
backend/src/main/java/kr/touroot/global/util/PageDeserializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package kr.touroot.global.util; | ||
|
||
import com.fasterxml.jackson.core.JsonParseException; | ||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.core.JsonToken; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.databind.JsonDeserializer; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.springframework.data.domain.PageImpl; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Sort; | ||
|
||
public class PageDeserializer extends JsonDeserializer<PageImpl<?>> { | ||
|
||
@Override | ||
public PageImpl<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { | ||
List<Object> content = new ArrayList<>(); | ||
int pageNumber = 0; | ||
int pageSize = 0; | ||
long totalElements = 0; | ||
Sort sort = Sort.unsorted(); | ||
|
||
if (p.getCurrentToken() != JsonToken.START_OBJECT) { | ||
throw new JsonParseException("Page 객체를 역직렬화하는 과정에서 예외가 발생했습니다."); | ||
} | ||
|
||
while (p.nextToken() != JsonToken.END_OBJECT) { | ||
String fieldName = p.getCurrentName(); | ||
p.nextToken(); | ||
|
||
if (fieldName == null) { | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("content") && p.getCurrentToken() == JsonToken.START_ARRAY) { | ||
content = ctxt.readValue( | ||
p, | ||
ctxt.getTypeFactory().constructCollectionType(List.class, Object.class) | ||
); | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("number")) { | ||
pageNumber = p.getIntValue(); | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("size")) { | ||
pageSize = p.getIntValue(); | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("totalElements")) { | ||
totalElements = p.getLongValue(); | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("sort")) { | ||
while (p.getCurrentToken() == JsonToken.START_OBJECT) { | ||
p.nextToken(); | ||
} | ||
sort = ctxt.readValue(p, Sort.class); | ||
continue; | ||
} | ||
|
||
p.skipChildren(); | ||
} | ||
|
||
PageRequest pageable = PageRequest.of(pageNumber, pageSize, sort); | ||
return new PageImpl<>(content, pageable, totalElements); | ||
} | ||
} | ||
|
77 changes: 77 additions & 0 deletions
77
backend/src/main/java/kr/touroot/global/util/SortDeserializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package kr.touroot.global.util; | ||
|
||
import com.fasterxml.jackson.core.JsonParseException; | ||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.core.JsonToken; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.databind.JsonDeserializer; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.data.domain.Sort.Direction; | ||
import org.springframework.data.domain.Sort.Order; | ||
|
||
public class SortDeserializer extends JsonDeserializer<Sort> { | ||
|
||
@Override | ||
public Sort deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { | ||
List<Sort.Order> orders = new ArrayList<>(); | ||
boolean sorted = false; | ||
|
||
Comment on lines
+15
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 역직렬화 설정은 PageImpl을 생성하기 위해 필요한 Sort 객체의 역직렬화 로직입니다. |
||
if (p.getCurrentToken() != JsonToken.START_OBJECT) { | ||
throw new JsonParseException("Sort 객체를 역직렬화하는 과정에서 예외가 발생했습니다."); | ||
} | ||
|
||
while (p.nextToken() != JsonToken.END_OBJECT) { | ||
String fieldName = p.getCurrentName(); | ||
p.nextToken(); | ||
|
||
if (fieldName.equals("sorted")) { | ||
sorted = p.getBooleanValue(); | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("orders")) { | ||
deserializeOrders(p, orders); | ||
continue; | ||
} | ||
|
||
p.skipChildren(); | ||
} | ||
|
||
if (sorted) { | ||
return Sort.by(Sort.Order.asc("dummy")); | ||
} | ||
|
||
return Sort.unsorted(); | ||
} | ||
|
||
private void deserializeOrders(JsonParser p, List<Order> orders) throws IOException { | ||
if (p.getCurrentToken() != JsonToken.START_ARRAY) { | ||
throw new JsonParseException("Sort.orders 객체를 역직렬화하는 과정에서 예외가 발생했습니다."); | ||
} | ||
|
||
while (p.nextToken() != JsonToken.END_ARRAY) { | ||
String direction = null; | ||
String property = null; | ||
|
||
while (p.nextToken() != JsonToken.END_OBJECT) { | ||
String fieldName = p.getCurrentName(); | ||
|
||
if (fieldName.equals("property")) { | ||
property = p.getText(); | ||
continue; | ||
} | ||
|
||
if (fieldName.equals("direction")) { | ||
direction = p.getText(); | ||
} | ||
} | ||
|
||
if (property != null && direction != null) { | ||
orders.add(new Order(Direction.fromString(direction), property)); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
회의에서 말씀드린데로 저와 클로버는 Page를 캐싱했습니다.
그런데 캐싱된 페이지를 꺼내오는 과정에서 PageImpl로의 역직렬화가 실패했었는데요, 이는 PageImpl의 기본 생성자가 존재하지 않아 ObjectMapper가 리플렉션하지 못하기 때문이었습니다.
문제를 해결하기 위해서는 다음의 두가지 방법 중 하나를 선택해야 합니다.
저와 클로버는 Wrapper 클래스를 운용하게 되는 경우 어색한 점이 있다고 판단했습니다.
Wrapper 클래스를 운용하게 되면 기존 코드의 수정이 불가피하고 캐싱하는 메서드와 캐싱하지 않는 메서드의 반환타입이 달라지는 부분이 클래스 운용 명세가 숨겨지는 잠재적 위험이라고 생각한 것이 이유에요.
따라서 PageImpl 객체를 커스텀 역직렬화하는 코드를 작성한 것이 해당 코드입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 래퍼로 감싸서 해당 래퍼 클래스를 직접 사용하는 것은 좋지 못한 구조라 생각합니다.
캐시 도입이 어노테이션을 넘어서 동작하고 있는 서비스 코드에 변경을 주지 않는 것이 좋다고 생각합니다.
좋은 방향으로 역직렬화 문제를 해결해 주셨네요!