tgyuuAn / BaekyoungE

์ž์—ฐ์–ด ์ฒ˜๋ฆฌ ๊ธฐ๋ฐ˜ ์ง„๋กœ ์ƒ๋‹ด chat bot ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜
5 stars 0 forks source link

Feature/#33 #34

Closed tgyuuAn closed 2 months ago

tgyuuAn commented 2 months ago

1. ๐Ÿ“„ ๊ด€๋ จ๋œ ์ด์Šˆ ๋ฐ ์†Œ๊ฐœ

2. ๐Ÿ”ฅ๋ณ€๊ฒฝ๋œ ์ 

3. ๐Ÿ“ธ ์Šคํฌ๋ฆฐ์ƒท(์„ ํƒ)

bandicam2024-04-1311-02-30-847-ezgif com-crop

4. ๐Ÿ’ก์•Œ๊ฒŒ๋œ ํ˜น์€ ๊ถ๊ธˆํ•œ ์‚ฌํ•ญ๋“ค

1. Retrofit2๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, GsonConverter vs kotlin Serealization ์ฐจ์ด




GsonConverter

-> ์‚ฌ์šฉ๋ฒ• ๋งค์šฐ ๊ฐ„๋‹จ -> ๋ฐ์ดํ„ฐ์— ๊ธฐ๋ณธ ๊ฐ’์„ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์—†์Œ. -> null๊ฐ’์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ฌ ๊ฒฝ์šฐ ์—˜๋น„์Šค ์—ฐ์‚ฐ์ž ?: ์„ ์ด์šฉํ•ด์„œ ๊ธฐ๋ณธ ๊ฐ’์„ ์ค„ ์ˆ˜ ์žˆ๊ธด ํ•˜์ง€๋งŒ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ๋ฐœ์ƒ.




Kotlinx.Sereilization

-> ๊ธฐ๋ณธ๊ฐ’์„ ํ• ๋‹นํ•ด์ค„ ์ˆ˜ ์žˆ์Œ.







2. Retrofit2๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, @POST, @BODY ์ฐจ์ด

@Field




@Body

image







3. Retrofit2 Converter๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ์—๋Ÿฌ ๋ฐœ์ƒ

java.lang.IllegalArgumentException: Unable to create @Body converter for class com.tgyuu.network.model.consulting.AiChatRequest (parameter #1) for method OpenAiApi.postChatMessage




๋””๋ฒ„๊น…

Response๋‚˜ Request DTO ์—์„œ @Serilizaion ์–ด๋…ธํ…Œ์ด์…˜์—์„œ @Suppress("PLUGIN_IS_NOT_ENABLED") ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”๊ฒŒ ์ˆ˜์ƒํ–ˆ์Œ.

์ฐพ์•„๋ณด๋‹ˆ kotlin serialization์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”,

์‚ฌ์šฉํ•˜๋ ค๋Š” ๋ชจ๋“ˆ์˜ plugin{} ์— kotlin("plugin.serialization") version "1.9.23" ์„ ์ถ”๊ฐ€ํ–ˆ์–ด์•ผ ํ–ˆ์Œ.




์—ฌ๊ธฐ์„œ ๊ทธ๋Ÿผ, plugin์„ importํ•  ๋•Œ ๋’ค์— ํ•ญ์ƒ ๋ถ™๋Š” apply false๋ฅผ ๋ถ™์ด์ง€ ์•Š๋Š” ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ–ˆ์Œ.


image

์Œ... ๊ทธ๋ ‡๋‹ค๊ณ  ํ•œ๋‹ค...! ํ•˜ํ•˜...







4. StateFlow<MutableList>๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Compose๊ฐ€ ๋ณ€ํ™”๋ฅผ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•ด์š”.

MutableLIst<T> ์™€ ๊ฐ™์ด mutableํ•œ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ’์„ add ์‹œํ‚ค๋ฉด compose๋Š” ์ด์˜ ๊ฐ’ ๋ณ€ํ™”๋ฅผ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•˜๊ณ  Recomposition์„ ์œ ๋ฐœํ•˜์ง€ ์•Š๋Š”๋‹ค.

image

ํ˜„์žฌ OpenAi Api๋ฅผ ํ˜ธ์ถœํ•จ์œผ๋กœ์จ ์‘๋‹ต๋˜๋Š” AI์‘๋‹ต ๋‹ต๋ณ€์„ ๊ณ„์†ํ•ด์„œ mutableList<T>์— ์ €์žฅํ•ด์•ผํ–ˆ๊ณ ,

์ด๋ฅผ ๊ณ„์† LazyColumn ์ด ๋ฐ›์•„๋จน์œผ๋ฉด์„œ ์ž๋™์œผ๋กœ ๊ทธ๋ ค์ง€๋Š” ์ด์ƒ์ ์ธ ๋ชจ์Šต์„ ์›ํ–ˆ๋‹ค.




ํ•˜์ง€๋งŒ, ViewModel์—์„œ StateFlow<MutableList<T>>๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š”, ๋ฐ์ดํ„ฐ๋Š” ์ œ๋•Œ ๋“ค์–ด๊ฐ€์ง€๋งŒ

๋ณ„๋„๋กœ ๋ฆฌ์ปดํฌ์ง€์…˜์„ ์ผ์œผํ‚ค๋Š” ํ–‰์œ„๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ํ•ด์•ผ์ง€๋งŒ ๋งํ’์„ ์ด ์—…๋ฐ์ดํŠธ๊ฐ€ ๋˜์—ˆ๋‹ค.







๋””๋ฒ„๊น…

mutableํ•œ ๊ฐ์ฒด๋ฅผ immutableํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด,

// BAD
@Composable
fun NamesList() {
    val names by remember {
        mutableStateOf(mutableListOf<String>())
    }

    LazyColumn {
        item {
            Button(onClick = { names.add("Hans") }) {
                Text(text = "Add name")
            }
        }
        items(names) { name ->
            Text(name)
        }
    }
}

์ด๋ผ๋Š” ์ฝ”๋“œ๋Š”

// GOOD
@Composable
fun NamesList() {
    var names by remember {
        mutableStateOf(listOf<String>())
    }

    LazyColumn {
        item {
            Button(onClick = { 
                names = names + "Hans"
            }) {
                Text(text = "Add name")
            }
        }
        items(names) { name ->
            Text(name)
        }
    }
}

๋กœ MutableList + add() ์—์„œ List ์œผ๋กœ ์น˜ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.







ํ•˜์ง€๋งŒ ๋” ์ข‹์€ ๋ฐฉ์•ˆ์ด ์žˆ๋Š”๋ฐ,

๊ทธ๊ฒƒ์€ ๊ณต์‹๋ฌธ์„œ ์ฝ”๋“œ๋žฉ์—์„œ ์†Œ๊ฐœํ•˜๋Š” mutableStateList๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

mutableStateList๋Š” ๊ด€์ฐฐ๊ฐ€๋Šฅํ•œ MutableList์˜ ์—ญํ• ์„ ํ•ด์ฃผ๋Š” ๋‚˜์ด์“ฐํ•œ ์•„์ด์ด๋‹ค.










5. LazyColumn ๋งˆ์ง€๋ง‰ item์œผ๋กœ ์Šคํฌ๋กค ํ•˜๋Š” ๋ฐฉ๋ฒ•

1 ์ด์ „ ์ฑ„ํŒ…์˜ ํ…์ŠคํŠธ ์‚ฌ์ด์ฆˆ๋ฅผ ์ €์žฅํ•ด๋‘ 

2. ์ƒˆ๋กœ์šด ์ฑ„ํŒ…์ด ๋“ค์–ด์™”์„ ๋•Œ, ํ˜„์žฌ ์‚ฌ์ด์ฆˆ์™€ ๋‹ค๋ฅผ๊ฒฝ์šฐ, ๋งˆ์ง€๋ง‰ ์•„์ดํ…œ์˜ ์ธ๋ฑ์Šค๋กœ ์Šคํฌ๋กค ํ•จ.

    val listState = rememberLazyListState()
    var previousChatSize by remember { mutableStateOf(1) }
    val coroutineScope = rememberCoroutineScope()




    LaunchedEffect(chatLog) {
        if (previousChatSize != chatLog.size) {
            coroutineScope.launch {
                listState.animateScrollToItem(chatLog.size - 1)
            }

            previousChatSize = chatLog.size
        }
    }




LazyColumn(
                state = listState,
                verticalArrangement = Arrangement.spacedBy(20.dp),
                contentPadding = PaddingValues(horizontal = 25.dp),
                modifier = Modifier
                    .fillMaxSize()
                    .padding(top = topBarHeight, bottom = textFieldHeight),
            ) {