๐Ÿ˜ตโ€๐Ÿ’ซPreview ๋•Œ๋ฌธ์— ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด์š”! (PreviewParameter)

์•ˆ์„ธํ™ยท2025๋…„ 2์›” 2์ผ
post-thumbnail

์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜์€ Compose๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ Preview ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด์ ธ ๊ณ ๋ฏผํ–ˆ๋˜ ๊ฒฝํ—˜๊ณผ ์ด๋ฅผ ๊ฐœ์„ ํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณต์œ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

Preview๊ฐ€ ๊ธธ์–ด์ง„ ์ด์œ 

๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ํ”ผ๊ทธ๋งˆ ๋””์ž์ธ์— ์žˆ๋Š” ๋ชจ๋“  ๋ฒ„ํŠผ ์Šคํƒ€์ผ์„ Preview๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋‹ˆ Preview ์ฝ”๋“œ๊ฐ€ ์ ์  ๊ธธ์–ด์ง€๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

PR์„ ์˜ฌ๋ฆด ๋•Œ๋Š” ๋ฆฌ๋ทฐ์–ด๋ถ„๋“ค๊ป˜ "๋ฒ„ํŠผ ์ปดํฌ๋„ŒํŠธ์— Preview๊ฐ€ ๋งŽ์•„ ์ฝ”๋“œ๊ฐ€ ๊ธธ ์ˆ˜ ์žˆ๋‹ค" ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋‚จ๊ฒจ์•ผ ํ•  ์ •๋„์˜€์ฃ .

ํ•˜์ง€๋งŒ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์ค‘ ํ•œ ๋ฆฌ๋ทฐ์–ด๋ถ„๊ป˜์„œ PreviewParameter๋ผ๋Š” ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์„ ์•Œ๋ ค์ฃผ์…จ๊ณ , ์ด๋ฅผ ํ™œ์šฉํ•ด ์ฝ”๋“œ ๊ธธ์ด๋ฅผ ํš๊ธฐ์ ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

PreviewParameter๋ฅผ ํ™œ์šฉํ•œ ์ฝ”๋“œ ๊ฐ„์†Œํ™”

Compose์˜ PreviewParameter๋Š” Preview๋ฅผ ์œ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์–‘ํ•œ ์ƒํƒœ๋กœ Previewํ•  ๋•Œ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปดํฌ์ €๋ธ” ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋กœ UI ๋ฏธ๋ฆฌ๋ณด๊ธฐ ย |ย  Jetpack Compose ย |ย  Android Developers

PreviewParameterProvider ์ •์˜

๋จผ์ €, Preview์— ์‚ฌ์šฉ๋  ๋ฒ„ํŠผ ์Šคํƒ€์ผ์„ ์ •์˜ํ•˜๋Š” PreviewParameterProvider๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๊ฐ ๋ฒ„ํŠผ ์Šคํƒ€์ผ์„ ์ œ๊ณตํ•˜๋Š” ButtonStyleProvider๋ฅผ ์ž‘์„ฑํ–ˆ์–ด์š”.

private class ButtonStyleProvider : PreviewParameterProvider<ButtonStyle> {
    override val values: Sequence<ButtonStyle> = sequenceOf(
        ButtonStyle.Primary,
        ButtonStyle.Secondary,
        ButtonStyle.Tertiary
    )
}

์ œ๊ฐ€ ์ž‘์„ฑํ•œ ์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉฐ ์„ค๋ช…ํ• ๊ฒŒ์š”!

1. PreviewParameterProvider ๋ฅผ ํ†ตํ•œ ButtonStyleProvider ํด๋ž˜์Šค ์ •์˜

๋จผ์ €, ButtonStyleProvider๋Š” Preview์— ์ „๋‹ฌํ•  ๊ฐ’์„ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” PreviewParameterProvider<T>๋ฅผ ์ƒ์†๋ฐ›์•„ values ์†์„ฑ์„ ํ†ตํ•ด Preview์—์„œ ์‚ฌ์šฉํ•  ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๋ชฉ๋ก์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

private class ButtonStyleProvider : PreviewParameterProvider<ButtonStyle> {
    override val values: Sequence<ButtonStyle> = sequenceOf(
        ButtonStyle.Primary,
        ButtonStyle.Secondary,
        ButtonStyle.Tertiary
    )
}
  • PreviewParameterProvider<T>: Preview์— ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ ํƒ€์ž… T๋ฅผ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ButtonStyle ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • values: Sequence ํƒ€์ž…์œผ๋กœ Preview์—์„œ ์‚ฌ์šฉํ•  ์—ฌ๋Ÿฌ ๊ฐ’์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
    • sequenceOf()๋ฅผ ์‚ฌ์šฉํ•ด ํ•„์š”ํ•œ ๋ฒ„ํŠผ ์Šคํƒ€์ผ๋“ค์„ ๋‚˜์—ดํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์—ฌ๊ธฐ์„œ๋Š” ButtonStyle.Primary, ButtonStyle.Secondary, ButtonStyle.Tertiary ์„ธ ๊ฐ€์ง€ ์Šคํƒ€์ผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

2. PreviewParameter ์• ๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ

์ด์ œ ButtonStyleProvider๋ฅผ ํ™œ์šฉํ•ด Preview ํ•จ์ˆ˜์—์„œ ๋‹ค์–‘ํ•œ ์Šคํƒ€์ผ์„ ๋ฏธ๋ฆฌ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

@PreviewParameter ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด, Preview ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Preview
@Composable
fun SpoonyButtonEnabledPreview(
    @PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle
) {
    SpoonyAndroidTheme {
        Column(
            modifier = Modifier.fillMaxWidth(),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            // ์—ฌ๊ธฐ์„œ ์ „๋‹ฌ๋ฐ›์€ style์„ ์‚ฌ์šฉ
            ButtonSize.entries.forEach { size ->
                SpoonyButton(
                    text = "๋ฒ„ํŠผ",
                    style = style, // ์ „๋‹ฌ๋ฐ›์€ style
                    size = size,   // ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๋ชจ๋“  ํฌ๊ธฐ ์ฒ˜๋ฆฌ
                    onClick = { }
                )
            }
        }
    }
}

๋™์ž‘ ๋ฐฉ์‹

  1. ๋งค๊ฐœ๋ณ€์ˆ˜ style์— ๊ฐ’ ์ „๋‹ฌ:
    • @PreviewParameter(ButtonStyleProvider::class)๋Š” ButtonStyleProvider์—์„œ ์ •์˜ํ•œ values๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ Preview๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • values์—์„œ ์ œ๊ณต๋œ ๊ฐ ButtonStyle(Primary, Secondary, Tertiary)์— ๋Œ€ํ•ด ๋ณ„๋„์˜ Preview ํ™”๋ฉด์ด ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค.
  2. Preview ์ƒ์„ฑ:
    • Compose๋Š” ๊ฐ ButtonStyle์— ๋Œ€ํ•ด ํ•œ ๋ฒˆ์”ฉ Preview๋ฅผ ์ƒ์„ฑํ•˜์—ฌ, ๋™์ผํ•œ UI๋ฅผ ๋‹ค์–‘ํ•œ ์Šคํƒ€์ผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

Preview์˜ ๊ฒฐ๊ณผ

์œ„ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฒ„ํŠผ ์Šคํƒ€์ผ(Primary, Secondary, Tertiary) ๊ฐ๊ฐ์— ๋Œ€ํ•ด Preview ํ™”๋ฉด์ด ๋”ฐ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ์Šคํƒ€์ผ๋ณ„ Preview๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์ค‘๋ณต๋œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง‘๋‹ˆ๋‹ค.

์ฝ”๋“œ ๋ณ€๊ฒฝ ์ „

๊ธฐ์กด์—๋Š” ๋ฒ„ํŠผ ์Šคํƒ€์ผ๊ณผ ํฌ๊ธฐ๋ณ„๋กœ Preview๋ฅผ ๋ชจ๋‘ ์ž‘์„ฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๊ฐ€ ์•„๋ž˜์ฒ˜๋Ÿผ ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค.

@Preview
@Composable
private fun SpoonyButtonPrimaryEnabledPreview() {
    SpoonyAndroidTheme {
        Column(
            modifier = Modifier.fillMaxWidth(),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                onClick = {},
                style = ButtonStyle.Primary,
                size = ButtonSize.Xlarge
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                onClick = {},
                style = ButtonStyle.Primary,
                size = ButtonSize.Large
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                onClick = {},
                style = ButtonStyle.Primary,
                size = ButtonSize.Medium
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                onClick = {},
                style = ButtonStyle.Primary,
                size = ButtonSize.Small
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                onClick = {},
                style = ButtonStyle.Primary,
                size = ButtonSize.Xsmall
            )
        }
    }
}

@Preview
@Composable
private fun SpoonyButtonPrimaryDisabledPreview() {
    SpoonyAndroidTheme {
        Column(
            modifier = Modifier.fillMaxWidth(),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                style = ButtonStyle.Primary,
                size = ButtonSize.Xlarge,
                enabled = false
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                style = ButtonStyle.Primary,
                size = ButtonSize.Large,
                enabled = false
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                style = ButtonStyle.Primary,
                size = ButtonSize.Medium,
                enabled = false
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                style = ButtonStyle.Primary,
                size = ButtonSize.Small,
                enabled = false
            )
            SpoonyButton(
                text = "๋ฒ„ํŠผ",
                style = ButtonStyle.Primary,
                size = ButtonSize.Xsmall,
                enabled = false
            )
        }
    }
}
...

์ฝ”๋“œ ๋ณ€๊ฒฝ ํ›„

PreviewParameter๋ฅผ ์‚ฌ์šฉํ•ด ์Šคํƒ€์ผ์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฒ„ํŠผ ํฌ๊ธฐ๋ณ„๋กœ๋„ ๋ฐ˜๋ณต๋ฌธ์„ ํ™œ์šฉํ•ด ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์˜€์–ด์š”.

@Preview
@Composable
fun SpoonyButtonEnabledPreview(
    @PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle
) {
    SpoonyAndroidTheme {
        Column(
            modifier = Modifier,
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            ButtonSize.entries.forEach { size ->
                SpoonyButton(
                    text = "๋ฒ„ํŠผ",
                    style = style,
                    size = size,
                    onClick = { }
                )
            }
        }
    }
}

์ฝ”๋“œ ์ปค๋ฐ‹ ํ›„ ์ฝ”๋“œ ์ค„ ์ˆ˜ ๋ณ€ํ™”

์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋‹ˆ Preview๊ฐ€ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ๋ฒ„ํŠผ ์Šคํƒ€์ผ๊ณผ ํฌ๊ธฐ๋ณ„ Preview๋ฅผ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์œ ์ง€๋ณด์ˆ˜๋„ ํŽธ๋ฆฌํ•ด์กŒ๊ณ , ์ฝ”๋“œ ๊ฐ€๋…์„ฑ๋„ ํฌ๊ฒŒ ํ–ฅ์ƒ๋˜์—ˆ์ฃ .

์ €๋Š” ํ•ด๋‹น ๋ฆฌ๋ทฐ๋ฅผ ํ†ตํ•ด PreviewParameter๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์•Œ๊ฒŒ ๋œ ๊ฒƒ๋„ ํฐ ์ˆ˜ํ™•์ด์—ˆ์Šต๋‹ˆ๋‹ค.

Preview๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด์ ธ ๊ณ ๋ฏผ ์ค‘์ด๋ผ๋ฉด, ์ €์ฒ˜๋Ÿผ PreviewParameter๋ฅผ ํ™œ์šฉํ•ด๋ณด๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”? ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์งˆ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜Š

profile
๋‚˜๋งŒ์˜ ๊ฐœ๋ฐœ ์ผ๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€