Light Blue Pointer
본문 바로가기
Developing/Trouble shooting

JPA 순환참조/무한루프 문제 해결 (Could not write JSON: Infinite recursion (StackOverflowError))

by Greedy 2024. 1. 11.

⛳문제 발생 : 재귀가 끝나지 않음

@Override
    public DetailedPostResponse getPost(Long postId, User user) {
        Post post = getPostById(postId);
        List<UserPost> userPosts = getUserPostsByPost(post);
        List<List<Menu>> allMenus = getMenus(userPosts,post);

        return DetailedPostResponse.builder()
            .author(getAuthor(userPosts))
            .address(post.getAddress())
            .store(post.getStore())
            .minPrice(post.getMinPrice())
            .deliveryCost(post.getDeliveryCost())
            .participants(getParticipants(userPosts))
            .myMenus(getMyMenus(user, allMenus))
            .menus(allMenus)
            .sumPrice(getSumPrice(getUserPostsByPost(post),post))
            .deadline(getDeadline(post))
            .build();
    }
{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "author": "가나다라",
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "myMenus": [
            {
                "id": 1,
                "post": {
                    "id": 1,
                    "address": "주소주소",
                    "store": "storestore",
                    "minPrice": 20000,
                    "deliveryCost": 2000,
                    "category": "KOREAN",
                    "menus": [
                        {
                            "id": 1,
                            "post": {
                                "id": 1,
                                "address": "주소주소",
                                "store": "storestore",
                                "minPrice": 20000,
                                "deliveryCost": 2000,
                                "category": "KOREAN",
                                "menus": [
                                    {
                                        "id": 1,
                                        "post": {
                                            "id": 1,
                                            "address": "주소주소",
                                            "store": "storestore",
                                            "minPrice": 20000,
                                            "deliveryCost": 2000,
                                            "category": "KOREAN",
                                            "menus": [
                                                {
                                                    "id": 1,
                                                    "post": {
                                                        "id": 1,
                                                        "address": "주소주소",
                                                        "store": "storestore",
                                                        "minPrice": 20000,
                                                        "deliveryCost": 2000,
                                                        "category": "KOREAN",
                                                        "menus": [
                                                            {
                                                                "id": 1,
                                                                "post": {
                                                                    "id": 1,
                                                                    "address": "주소주소",
                                                                    "store": "storestore",
                                                                    "minPrice": 20000,
                                                                    "deliveryCost": 2000,
                                                                    "category": "KOREAN",
                                                                    "menus": [
                                                                        {
                                                                            "id": 1,
                                                                            "post": {
                                                                                "id": 1,
                                                                                "address": "주소주소",
                                                                                "store": "storestore",
                                                                                "minPrice": 20000,
                                                                                "deliveryCost": 2000,
                                                                                "category": "KOREAN",
                                                                                "menus": [
                                                                                    {
                                                                                        "id": 1,
                                                                                        "post": {
                                                                                            "id": 1,
                                                                                            "address": "주소주소",
                                                                                            "store": "storestore",
                                                                                            "minPrice": 20000,
                                                                                            "deliveryCost": 2000,
                                                                                            "category": "KOREAN",
                                                                                            "menus": [
                                                                                                {
                                                                                                    "id": 1,
                                                                                                    "post": {
                                                                                                        "id": 1,
                                                                                                        "address": "주소주소",
                                                                                                        "store": "storestore",
                                                                                                        "minPrice": 20000,
                                                                                                        "deliveryCost": 2000,
                                                                                                        "category": "KOREAN",
                                                                                                        "menus": [
                                                                                                                                                                     "deliveryCost": 2000,
                                                                                                                                                                                "category": "KOREAN",
... 이하 반복 후 에러메시지가 출력됨                                                                                                                                                                                "menus": [

{
    "status": 400,
    "message": "에러가 발생했습니다",
    "data": "Could not write JSON: Infinite recursion (StackOverflowError)"
}

myMenus가 문제임

private List<Menu> getMyMenus(User user, List<List<Menu>> allMenus){
        List<Menu> myMenus = null;

        for(List<Menu> menus : allMenus){
            if(menus.size()>0){
                if(menus.get(0).getUser().getId().equals(user.getId())){
                    myMenus = menus;
                    break;
                }
            }
        }

        return myMenus;
    }

저기에서 뭐가 오류가 나는지 모르겠네?

break가 안 되는건가 싶어서 break대신 return을 해봄

private List<Menu> getMyMenus(User user, List<List<Menu>> allMenus){
        for(List<Menu> menus : allMenus){
            if(menus.size()>0){
                if(menus.get(0).getUser().getId().equals(user.getId())){
                    return menus;
                }
            }
        }

        return null;
    }

상황이 똑같음

mymenus가 아니라 allmenus가 문제인가 싶어서 순서를 한번 바꿔봄

@Builder
public record DetailedPostResponse (
    String author,
    String address,
    String store,
    Integer minPrice,
    Integer deliveryCost,
    List<List<Menu>> menus,
    List<Menu> myMenus,
    List<String> participants,
    
    Integer sumPrice,
    LocalDateTime deadline
){
}
return DetailedPostResponse.builder()
            .author(getAuthor(userPosts))
            .address(post.getAddress())
            .store(post.getStore())
            .minPrice(post.getMinPrice())
            .deliveryCost(post.getDeliveryCost())
            .participants(getParticipants(userPosts))
            .menus(allMenus)
            .myMenus(getMyMenus(user, allMenus))
            .sumPrice(getSumPrice(getUserPostsByPost(post),post))
            .deadline(getDeadline(post))
            .build();

 

 

음 바꾸니까 allMenus가 문제였다는 걸 알게됨

{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "author": "가나다라",
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "menus": [
            [
                {
                    "id": 1,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "menus": [
                            {
                                "id": 1,
                                "post": {
                                    "id": 1,
                                    "address": "주소주소",
                                    "store": "storestore",
                                    "minPrice": 20000,
                                    "deliveryCost": 2000,
                                    "category": "KOREAN",
                                    "menus": [
                                        {
                                            "id": 1,
                                            "post": {
                                                "id": 1,
                                                "address": "주소주소",
                                                "store": "storestore",
                                                "minPrice": 20000,
                                                "deliveryCost": 2000,
                                                "category": "KOREAN",
                                                "menus": [

 

 

지금 allMenus가 어떻게 되고 있냐면

List<List<Menu>> allMenus = getMenus(userPosts,post);
private List<List<Menu>> getMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = new ArrayList<>();

        for(UserPost userpost : userposts){
            List<Menu> myMenus = getUserMenus(userpost.getUser(),post);
            menus.add(myMenus);
        }

        return menus;
    }

private List<Menu> getUserMenus(User user, Post post){
        return menuRepository.findAllByUserAndPost(user,post);
    }

음… 왜 무한반복이 되는거지…

        List<List<Menu>> menus = new ArrayList<>(); -> 미부분을 이렇게 쓰면 알아서 안 되는건가?

List<List<Menu>> menus = new ArrayList<List<Menu>>(); 이렇게 바꿔봄

아무 상관 없었음~~

ArrayList 에 add하는게 맞나 싶어서 찾아봄

https://www.baeldung.com/java-list-of-lists

private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = new ArrayList<>();

        for(UserPost userpost : userposts){
            List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
            menus.add(userMenus);
        }

        return menus;
    }
private List<String> getParticipants(List<UserPost> userPosts){
        return userPosts.stream()
            .filter((UserPost userPost)->userPost.getRole().equals(UserPostRole.PARTICIPANT))
            .map((UserPost userPost)->userPost.getUser().getNickname()).toList();
    }
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = new ArrayList<>();

        for(UserPost userpost : userposts){
            List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
            menus.add(userMenus);
        }

        return menus;
    }

다시봐도 뭐가 잘못되었는지 모르겠고 일단 스트림으로 해봄

stream으로 바꾸다보니 List<List<Menu>>에다가 List<ArrayList<Menu>> 넣지 말라고 해서 그 부분 다 수정함

@Builder
public record DetailedPostResponse (
    String author,
    String address,
    String store,
    Integer minPrice,
    Integer deliveryCost,
    List<String> participants,
    List<ArrayList<Menu>> menus,
    List<Menu> myMenus,
    Integer sumPrice,
    LocalDateTime deadline
){
}
private List<Menu> getMyMenus(User user, List<ArrayList<Menu>> allMenus){
        for(List<Menu> menus : allMenus){
            if(menus.size()>0){
                if(menus.get(0).getUser().getId().equals(user.getId())){
                    return menus;
                }
            }
        }
        return null;
    }
private List<ArrayList<Menu>> getAllMenus(List<UserPost> userposts, Post post){
        
        List<ArrayList<Menu>> menus = userposts.stream().map((UserPost userpost)->new ArrayList<>(getUserMenus(userpost.getUser(),userpost.getPost()))).toList();
        return menus;
    }
{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "author": "가나다라",
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "participants": [],
        "menus": [
            [
                {
                    "id": 1,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "menus": [
                            {
                                "id": 1,
                                "post": {
                                    "id": 1,
                                    "address": "주소주소",
                                    "store": "storestore",
                                    "minPrice": 20000,
                                    "deliveryCost": 2000,
                                    "category": "KOREAN",
                                    "menus": [
                                        {

오 ~~ 여러가지 시도 다 해봐도 menus는 스트림으로 하나마나 무한반복임

private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = userposts.stream().map((UserPost userpost)->getUserMenus(userpost.getUser(),userpost.getPost())).toList();
        return menus;
    }

이렇게 해봄

상황 똑같음

for문으로 다시 돌아가봄

private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = new ArrayList<>();

        for(UserPost userpost : userposts){
            List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
            menus.add(userMenus);
        }

        return menus;
    }
"menus": [
            [
                {
                    "id": 1,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "menus": [
                            {
                                "id": 1,
                                "post": {
                                    "id": 1,
                                    "address": "주소주소",
                                    "store": "storestore",
                                    "minPrice": 20000,
                                    "deliveryCost": 2000,
                                    "category": "KOREAN",
                                    "menus": [

 

💡참조에 문제가 있다고 함

menu를 가져올때 post를 가져오고 다시 menu를 가져오고 무한반복의 루프에 빠짐

Post entity에 JSON Ignore를 붙였더니 끝나긴 끝났다 아직 상호참조를 하고있지만…

@OneToMany(mappedBy = "post")
    @JsonIgnore//상호참조문제?
    private List<Menu> menus;
{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "participants": [
            "가나다라"
        ],
        "menus": [
            [
                {
                    "id": 1,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "sumPrice": null,
                        "deadline": "2024-01-09T23:03:49.701351"
                    },
                    "user": {
                        "id": 1,
                        "email": "email@dot.com",
                        "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                        "nickname": "가나다라"
                    },
                    "menuname": "통새우버거",
                    "price": 5000
                },
                {
                    "id": 2,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "sumPrice": null,
                        "deadline": "2024-01-09T23:03:49.701351"
                    },
                    "user": {
                        "id": 1,
                        "email": "email@dot.com",
                        "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                        "nickname": "가나다라"
                    },
                    "menuname": "통새우버거",
                    "price": 5000
                },
                {
                    "id": 3,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "sumPrice": null,
                        "deadline": "2024-01-09T23:03:49.701351"
                    },
                    "user": {
                        "id": 1,
                        "email": "email@dot.com",
                        "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                        "nickname": "가나다라"
                    },
                    "menuname": "통새우버거",
                    "price": 5000
                }
            ]
        ],
        "myMenus": [
            {
                "id": 1,
                "post": {
                    "id": 1,
                    "address": "주소주소",
                    "store": "storestore",
                    "minPrice": 20000,
                    "deliveryCost": 2000,
                    "category": "KOREAN",
                    "sumPrice": null,
                    "deadline": "2024-01-09T23:03:49.701351"
                },
                "user": {
                    "id": 1,
                    "email": "email@dot.com",
                    "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                    "nickname": "가나다라"
                },
                "menuname": "통새우버거",
                "price": 5000
            },
            {
                "id": 2,
                "post": {
                    "id": 1,
                    "address": "주소주소",
                    "store": "storestore",
                    "minPrice": 20000,
                    "deliveryCost": 2000,
                    "category": "KOREAN",
                    "sumPrice": null,
                    "deadline": "2024-01-09T23:03:49.701351"
                },
                "user": {
                    "id": 1,
                    "email": "email@dot.com",
                    "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                    "nickname": "가나다라"
                },
                "menuname": "통새우버거",
                "price": 5000
            },
            {
                "id": 3,
                "post": {
                    "id": 1,
                    "address": "주소주소",
                    "store": "storestore",
                    "minPrice": 20000,
                    "deliveryCost": 2000,
                    "category": "KOREAN",
                    "sumPrice": null,
                    "deadline": "2024-01-09T23:03:49.701351"
                },
                "user": {
                    "id": 1,
                    "email": "email@dot.com",
                    "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                    "nickname": "가나다라"
                },
                "menuname": "통새우버거",
                "price": 5000
            }
        ],
        "sumPrice": 15000,
        "deadline": "2024-01-09T23:03:49"
    }
}

 

Post entity에서 menus를 그냥 참조해올수 있는데 menu repository에서 해서 문제가 됐던걸까!

private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = new ArrayList<>();

        for(UserPost userpost : userposts){
            List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
            menus.add(userMenus);
        }

        return menus;
    }

    private List<Menu> getUserMenus(User user, Post post){
        return menuRepository.findAllByUserAndPost(user,post);
    }

private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = new ArrayList<>();

        for(UserPost userpost : userposts){
            List<Menu> userMenus = userpost.getPost().getMenus();
            menus.add(userMenus);
        }

        return menus;
    }

이렇게 바꿔봄

{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "participants": [
            "가나다라"
        ],
        "menus": [
            [
                {
                    "id": 1,
                    "post": {
                        "id": 1,
                        "address": "주소주소",
                        "store": "storestore",
                        "minPrice": 20000,
                        "deliveryCost": 2000,
                        "category": "KOREAN",
                        "menus": [
                            {
                                "id": 1,
                                "post": {
                                    "id": 1,
                                    "address": "주소주소",
                                    "store": "storestore",
                                    "minPrice": 20000,
                                    "deliveryCost": 2000,
                                    "category": "KOREAN",
                                    "menus": [
                                        {

음 똑같은 문제가 일어난다

 

⚠️Spring Data JPA, @OneToMany 무한 반복 오류

 

@OneToMany Entity을 RestAPI로 리턴할때 부한 반복 오류

양방향 관계의 Entity에서 @OneToMany를 사용하면, 엔티티를 리턴할 때 순환 참조(Circular Reference) 문제가 발생할 수 있다고 함!

JSON 직렬화 시 무한 루프 -> StackOverflowError가 발생함 ( 나도 저거 발생했음! )

 

💡순환참조 해결법

  1. @JsonIgnore : 이 어노테이션을 붙이면 JSON 데이터에 해당 property는 null로 들어가게 된다. 즉, 데이터에 아예 포함시키지 않는다.
  2. @JsonManagedReference 와 @JsonBackReference : 부모 클래스(Posts entity)의 Comment 필드에 @JsonManagedReference를, 자식 클래스(Comment entity)의 Posts 필드에 @JsonBackReference를 추가해주면 순환 참조를 막을 수 있다.
  3. @JsonIgnoreProperties : 부모 클래스(Posts entity)의 Comment 필드에 @JsonIgnoreProperties({"posts"}) 를 붙여주면 순환 참조를 막을 수 있다.
  4. DTO 사용 : 위와 같은 상황이 발생하게된 주원인은 '양방향 매핑'이기도 하지만, 더 정확하게는 Entity 자체를 response로 리턴한데에 있다. entity 자체를 return 하지 말고, DTO 객체를 만들어 필요한 데이터만 옮겨담아 Client로 리턴하면 순환 참조 관련 문제는 애초에 방지 할 수 있다.
  5. 양방향 매핑을 단방향 매핑으로

🚩해결 : @JsonManagedReference 와 @JsonBackReference 달아서 해결함!!

public class Menu {

    @JsonBackReference
    @ManyToOne
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "post_id", nullable = false)
    private Post post;
public class Post {

    @JsonManagedReference
    @OneToMany(mappedBy = "post")
    private List<Menu> menus;
{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "participants": [
            "가나다라"
        ],
        "menus": [
            [
                {
                    "id": 1,
                    "user": {
                        "id": 1,
                        "email": "email@dot.com",
                        "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                        "nickname": "가나다라"
                    },
                    "menuname": "통새우버거",
                    "price": 5000
                },
                {
                    "id": 2,
                    "user": {
                        "id": 1,
                        "email": "email@dot.com",
                        "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                        "nickname": "가나다라"
                    },
                    "menuname": "통새우버거",
                    "price": 5000
                },
                {
                    "id": 3,
                    "user": {
                        "id": 1,
                        "email": "email@dot.com",
                        "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                        "nickname": "가나다라"
                    },
                    "menuname": "통새우버거",
                    "price": 5000
                }
            ]
        ],
        "myMenus": [
            {
                "id": 1,
                "user": {
                    "id": 1,
                    "email": "email@dot.com",
                    "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                    "nickname": "가나다라"
                },
                "menuname": "통새우버거",
                "price": 5000
            },
            {
                "id": 2,
                "user": {
                    "id": 1,
                    "email": "email@dot.com",
                    "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                    "nickname": "가나다라"
                },
                "menuname": "통새우버거",
                "price": 5000
            },
            {
                "id": 3,
                "user": {
                    "id": 1,
                    "email": "email@dot.com",
                    "password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
                    "nickname": "가나다라"
                },
                "menuname": "통새우버거",
                "price": 5000
            }
        ],
        "sumPrice": 15000,
        "deadline": "2024-01-09T23:03:49"
    }
}

잘 나온다!!

다시 Stream으로 바꿔봄

private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){

        List<List<Menu>> menus = userposts.stream().map((UserPost userpost)->getUserMenus(userpost.getUser(),userpost.getPost())).toList();
        return menus;
    }

post 필요없는거 같아서 삭제함

private List<List<Menu>> getAllMenus(List<UserPost> userposts){

        List<List<Menu>> menus = userposts.stream().map((UserPost userpost)->userpost.getPost().getMenus()).toList();
        return menus;
    }

잘된다!

 

💡생각해봄

애초에 dto를 쓰는데 이유가 있는 거였다 ㅋㅋ

Menu를 안 돌려보내고 Menu response를 돌려보냈으면 이럴 일이 애초에 없고 user 정보도 안 나올거잖아...

User 정보가 왜 써있나 했다

Menu에 User가 들어있으니까 그걸 또 쓴거구나

Menu에 Post가 들어있으니까 그거 정보 쓰다가 그 안에 Menu가 있으니까 그거 쓰다가 무한반복이 그래서 시작된거군….

뭔가 DetailedPostResponse 짜는 중 무의식중에 dto안 만들고 그냥 Menu를 돌려보냈었는데 앞으로는 절대 그럴 일이 없을듯 ㅋㅋㅋ 

 

🚩💡더 나은 해결책

public record MenuResponse(
    String menuname,
    Integer price
) {
}
public record MenusResponse(
    String nickname,
    List<MenuResponse> menus
) {

}

걍 참여자 이름도 따로 넣지 않고 메뉴에다 넣고 myMenus를 없애고 allMenus 하나로 하는게 좋을듯

@Builder
public record DetailedPostResponse (
    String address,
    String store,
    Integer minPrice,
    Integer deliveryCost,
    List<List<MenuResponse>> menus,
    Integer sumPrice,
    LocalDateTime deadline
){
}
private List<MenusResponse> getAllMenus(List<UserPost> userposts){
        
        List<MenusResponse> menus = userposts.stream().map((UserPost userpost)->
            new MenusResponse(userpost.getUser().getNickname(),
                userpost.getPost().getMenus()
            .stream().map((Menu menu)->new MenuResponse(menu.getMenuname(),menu.getPrice())).toList()
        )).toList();
        return menus;
    }
{
    "status": 200,
    "message": "글 상세페이지 조회에 성공했습니다.",
    "data": {
        "address": "주소주소",
        "store": "storestore",
        "minPrice": 20000,
        "deliveryCost": 2000,
        "menus": [
            {
                "nickname": "가나다라",
                "menus": [
                    {
                        "menuname": "통새우버거",
                        "price": 5000
                    },
                    {
                        "menuname": "통새우버거",
                        "price": 5000
                    },
                    {
                        "menuname": "통새우버거",
                        "price": 5000
                    }
                ]
            }
        ],
        "sumPrice": 15000,
        "deadline": "2024-01-09T23:03:49"
    }
}

잘 된다!!