티스토리 뷰

<뇌 피셜로 이루어진 글 이므로 걸러서 읽기바랍니다.. 잘못된점 있으면 꼭! 알려주세요!!>

 

일단 결론은 LazyColumn안에 LazyColumn을 넣는게 아니다

LazyColumn안에 item을 여러개 넣을 수 있는 LazyListScope안에 또다시 LazyListScope를 넣는것임 그리고 그 LazyListScope에 댓글 대댓글을 item으로 넣는것

https://demat.tistory.com/71

 

[Compose] LazyColumn안에 LazyColumn넣기, NestedScroll, Column 안에 LazyColumn넣기

이런식으로 게시판 화면을 만들고 싶었다 그래서 Column에 스크롤을 넣고 그 안에 댓글부분은 LazyColumn으로 넣었다 그랬더니 아래같은 오류가 나고 터졌다 java.lang.IllegalStateException: Vertically scrollabl

demat.tistory.com

이 글에서 마지막에 쓴 부분을 보면 대댓글을 위해서

댓글이 item으로 들어가니깐

댓글인 item안에 또 item으로 대댓글이 들어갈수는 없나? 라고 했는데 그거는 아니고

item을 여러개 넣을 수 있는 LazyListScope안에 또다시 LazyListScope를 넣고 거기에 댓글, 대댓글을 넣는 방식

https://stackoverflow.com/questions/71667299/how-to-build-a-tree-using-lazycolumn-in-jetpack-compose

 

How to build a tree using LazyColumn in Jetpack Compose?

In my jetpack-compose app, I'm building a comment tree, where the top level, and the leaves, are lists, that would be best to use LazyColumn. This is of the form: List<CommentNode> ... Commen...

stackoverflow.com

집으로 오는 셔틀버스 안에서 폰으로 뒤적..뒤적 거리다가 이런 글을 발견 역시 스택오버플로우에는 없는게없다

챗 gpt? 걔는 뭘몰라 스택오버플로우 뿐.

 

일단 가장 겉(상단 글 내용, 댓글 내용 모두가 있는 스크린 부분)

                   LazyColumn(modifier = Modifier.padding(16.dp, 0.dp)) {
                        item {
                            Column() {
                                BoardDetailHead(
                                    postData = selectedPost.value!!,
                                    userDataId = viewModel.userDataId
                                )
                                BoardDetailBody(postData = selectedPost.value!!)
                                Spacer(modifier = Modifier.size(20.dp))
                                Divider()
                                Spacer(modifier = Modifier.size(20.dp))
                            }
                        }
                        BoardDetailComments(
                            viewModel = viewModel,
                            commentList = commentList,
                            reCommentList = reCommentList
                        )

                        item {
                            Spacer(modifier = Modifier.size(height))
                        }

                    }

이렇게 생겼다 

보면 다른애들은 다 item으로 감싸 있는데 BoardDetailComments얘만 item으로 감싸져 있지 않다

보면 item은 LazyItemScope이다 그러면 BoardDetailComments가 그냥 있는 이유는

BoardDetailComments자체가 LazyListScope이기 때문!

LazyListScope는 안에 item을 여러개 가질 수 있게된다 item은 LazyItemScope이다

private const val TAG = "BoardDetailComments"
fun LazyListScope.BoardDetailComments(
    viewModel: BoardViewModel,
    commentList : MutableList<CommentDto>
) {
    commentList.forEach{
        Log.d(TAG, "BoardDetailComments: 드로잉 LazyListScope추가")
        Comment(commentData = it, viewModel = viewModel)
    }
}

BoardDetailComments는 이렇게 생겼다(아.. 이름 새로 지어주고싶다 근데 안떠오른다)

댓글 리스트를 받아 forEach를 돌면서 Comment를 넣는다

엥 이러면 그냥 forEach로 Column하나씩 만드는거랑 뭐가다름 ㅋ?(맨밑에 그냥 Column으로 하는거랑 비교해보겟음)

fun LazyListScope.Comment(commentData: CommentDto, viewModel: BoardViewModel) {
    val menuItemList : MutableList<CustomMenuItem> = mutableListOf()
    menuItemList.apply {
        add(CustomMenuItem("수정"){})
        add(CustomMenuItem("삭제"){})
    }

    item{
        Log.d(TAG, "Comment: 드로잉 댓글 ${commentData.comment}")
        Column {
            Row {
                Spacer(modifier = Modifier.size(10.dp))
                CommentContent(comment = commentData)
                Row(
                    modifier = Modifier.weight(1f),
                    verticalAlignment = Alignment.Top,
                    horizontalArrangement = Arrangement.End
                ) {
                    if (viewModel.userDataId != commentData.normalUserId) {
                        ReCommentButton ({})
                    } else {
                        CommentMenuButton(menuItemList = menuItemList)
                    }

                }
                Spacer(modifier = Modifier.size(10.dp))
            }
            Spacer(modifier = Modifier.size(14.dp))

        }
    }
    if(commentData.reCommentList!=null){
        commentData.reCommentList!!.forEachIndexed { index, commentDto ->
            ReComment(commentData.reCommentList!![index], viewModel, index==0)
        }
    }
}

보면 Comment또한 역시 LazyListScope이다 그냥 Composable이 아니다 그래서 @Composable어노테이션도 없다

댓글을 item으로 하나 넣는다(본 댓글은 하나고 거기 달리는 대댓글이 여러개니깐)

그 다음 만약 commentData에 reCommentList 즉 대댓글이 있다면 여기 또 ReComment들을 여러개 넣는다

ReComment는 LazyItemScope이므로 item으로 감싸서 넣는다 얘는 밑에서 한번 더 보겠다

Comment의 구조는 본 댓글 1개 item, 대댓글 item여러개 인 LazyListScope인것임

private const val TAG = "ReComment"
@Composable
fun LazyItemScope.ReComment(commentData: CommentDto, viewModel: BoardViewModel, isFirstReComment: Boolean) {
    val menuItemList : MutableList<CustomMenuItem> = mutableListOf()
    menuItemList.apply {
        add(CustomMenuItem("수정"){})
        add(CustomMenuItem("삭제"){})
    }
        Log.d(TAG, "ReComment: 드로잉 ${commentData.comment}")
        Column (){
            Row(modifier = Modifier.fillMaxWidth()) {
                Column(modifier = Modifier.width(30.dp)) {
                    if (isFirstReComment) {
                        Icon(
                            imageVector = MyIconPack.Childarrow,
                            contentDescription = "대댓글",
                            tint = Color.Unspecified,
                            modifier = Modifier.size(24.dp)
                        )
                    }
                }

                CommentContent(comment = commentData)
                Row(
                    modifier = Modifier.weight(1f),
                    verticalAlignment = Alignment.Top,
                    horizontalArrangement = Arrangement.End
                ) {
                    if (viewModel.userDataId == commentData.normalUserId) {
                        CommentMenuButton(menuItemList = menuItemList)
                    }
                    Spacer(modifier = Modifier.size(10.dp))
                }
            }
            Spacer(modifier = Modifier.size(14.dp))
        }


}

ReComment는 이렇게 생겼다

ReComment는 LazyItemScope이다 왜냐면 대댓글 안에 또 여러개의 item들이 들어가야되는것은 없기때문에 그냥 LazyItemScope를 했다

LazyItemScope는 @Composable인듯함

암튼 구조를 그림으로 그려보면

이렇게 되는듯

이제 데이터를 넣고 로그 찍히는것을 보겠다

데이터는 아래와같다

val reCommentList: MutableList<CommentDto> = mutableListOf()
    reCommentList.apply {
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "대댓글내용1",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "대댓글내용2",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "대댓글내용3",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "대댓글내용4",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
    }
    val reCommentList2: MutableList<CommentDto> = mutableListOf()
    reCommentList2.apply {
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "2- 대댓글내용1",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "2- 대댓글내용2",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "2- 대댓글내용3",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "2- 대댓글내용4",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = true,
                null
            )
        )
    }
    
    val commentList: MutableList<CommentDto> = mutableListOf()
    commentList.apply {
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 1,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "댓글내용1",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = false,
                reCommentList
            )
        )
        add(
            CommentDto(
                commentId = 1,
                normalUserId = 2,
                postId = 1,
                festivalId = 1,
                hostId = 1,
                comment = "댓글내용2",
                createdAt = testDate,
                createdBy = "사용자 닉네임",
                updatedAt = testDate,
                depth = false,
                reCommentList2
            )
        )
    }

대강 댓글은 2개고 거기에 각각 대댓글은 4개씩임

로그 찍은것을 확인해보면

처음 게시글 들어갔을때임

(위에 한번 더 출력되는건 뭔지 모르겠네.. 이 글에서 살펴보는 LazyListScope랑은 관련없는 문제같긴한데 이또한 나의뇌피셜임)

일단 BoardDetailComments에서 for문 돌릴때마다 (Comment추가될때마다?) LazyListScope추가를 출력하도록 햇는데

LazyListScope가 두번출력됨 근데 밑에 출력되는걸 보면 댓글1만 로그가 찍히고 화면에 안보이는 대댓글이나 댓글2에 대해서는 로그가 안찍힘

즉 그리는거(컴포지션이라고 하나??)자체는 화면에 보여야만 그린다는것

 

 

그리고 살살 내려보면 화면에 대댓글이 보여지는 순간에 그려져서 로그가 찍힌다

 

 

 

그냥 Column으로 넣는거랑 뭐가 다른지 비교를 위해서 아래처럼 코드를 바꾸고 똑같은 데이터로 로그를 찍어보았다

 

제일 겉의 LazyColumn은 이렇다, items로 BoardDetailComments를 하나씩 넣는다

LazyColumn(modifier = Modifier.padding(16.dp, 0.dp)) {
                        item {
                            Column() {
                                BoardDetailHead(postData = selectedPost.value!!, userDataId = viewModel.userDataId)
                                BoardDetailBody(postData = selectedPost.value!!)
                                Spacer(modifier = Modifier.size(20.dp))
                                Divider()
                                Spacer(modifier = Modifier.size(20.dp))
                            }
                        }
                        items(commentList.size) { index ->
                            BoardDetailComments(
                                viewModel = viewModel,
                                comment = commentList[index]
                            )
                        }
                        item {
                            Spacer(modifier = Modifier.size(height))
                        }

                    }

 

 

BoardDetailComments는 이렇다

코멘트 컬럼 안에 본 댓글 넣고 리스트에 있는 대댓글을 for문 돌려서 넣는다

@Composable
fun BoardDetailComments(
    viewModel: BoardViewModel,
    comment: CommentDto
) {

    Column() {

        Comment(commentData = comment, viewModel = viewModel)
        if (comment.reCommentList != null) {
            comment.reCommentList!!.forEachIndexed { index, commentDto ->
                ReComment(
                    commentData = commentDto,
                    viewModel = viewModel,
                    isFirstReComment = index == 0
                )
            }
        }


    }

}

 

ReComment는 이렇다

private const val TAG = "ReComment"
@Composable
fun ReComment(commentData: CommentDto, viewModel: BoardViewModel, isFirstReComment: Boolean) {
    val menuItemList : MutableList<CustomMenuItem> = mutableListOf()
    menuItemList.apply {
        add(CustomMenuItem("수정"){})
        add(CustomMenuItem("삭제"){})
    }
    Log.d(TAG, "ReComment: 드로잉 ${commentData.comment}")

    Column (){
        Row(modifier = Modifier.fillMaxWidth()) {
            Column(modifier = Modifier.width(30.dp)) {
                if (isFirstReComment) {
                    Icon(
                        imageVector = MyIconPack.Childarrow,
                        contentDescription = "대댓글",
                        tint = Color.Unspecified,
                        modifier = Modifier.size(24.dp)
                    )
                }
            }

            CommentContent(comment = commentData)
            Row(
                modifier = Modifier.weight(1f),
                verticalAlignment = Alignment.Top,
                horizontalArrangement = Arrangement.End
            ) {
                if (viewModel.userDataId == commentData.normalUserId) {
                    CommentMenuButton(menuItemList = menuItemList)
                }
                Spacer(modifier = Modifier.size(10.dp))
            }
        }
        Spacer(modifier = Modifier.size(14.dp))
    }
}

 

로그를 확인해보자

이렇게(아니 이거 왜 두번찍히는거임???????) 댓글 1에 대해서 대댓글4가 화면에 보이지 않는 상황임에도 대댓글 4 까지 다 컴포지션 해서 들어간 모습

죄금 내려보면 이렇게 댓글2가 렌더링되는데 대댓글들이 모두 화면에 보이지도 않지만 일단 대댓글들이 다 같이 들어감

이게 BoardDetailComments자체는 item으로 들어갔기때매 화면에 보일때만 그려지는데 대댓글들은 그 안에 포함되어서 화면에 안보이지만 같이 들어가는 그런 현상인듯함!!

만약 대댓글이 100000개 막 이렇게 엄청 많아지면 아주 .. .. . . 좋지 않을듯?

앞에서봤던 방식으로 했을때 대댓글들이 화면에 진짜 나올때만 출력되는것과 다른모습...

 

암튼 결론은

LazyColumn 안에 LazyColumn을 넣으려고 하면 잘안된다

Nested LazyColumn은 안된다

대신 LazyColumn을 하나 두고 그 안에 item을 여러개 넣는다

만약 item안에 또 중첩해서 그 안에 item들을 더 넣고싶다면? item안에 item이 아니라!! LazyListScope안에 LazyListScope를 넣어서 그 안에 item을 여러개 넣는 방식을 쓰자

끝!

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함