
이전 글에서는 Compose를 시작하기 위한 개발 환경 설정과 프로젝트 생성 방법을 알아보았습니다.
이번에는 Compose를 활용한 UI 구성의 기초를 본격적으로 살펴볼 예정입니다. 먼저 Android 앱 화면에서 가장 많이 사용되는 Text, Button, Image 컴포저블의 기본 사용법과 함께, 이 컴포저블들을 화면에 효과적으로 배치하는 Column, Row, Box 레이아웃의 활용 방법을 알아보겠습니다.
이와 함께, Compose에서 모든 컴포저블을 자유롭고 유연하게 꾸밀 수 있도록 돕는 Modifier의 핵심 원리와 사용법까지 알아봅시다!
컴포저블 함수를 만드는 연습을 하기 위한 환경을 만들고 갑시다!
컴포저블 함수를 자유롭게 작성해 볼 파일을 생성합니다. (연습장을 준비하는 단계라고 생각하시면 됩니다.)


MainActivity가 있는 패키지(폴더)에 우클릭 후 “New” 버튼에 마우스를 올리고 “Kotlin Class/File” 버튼을 클릭합니다.
ComposeBeginnerGuide로 작성했기 때문에, composebeginnerguide라는 이름의 폴더를 선택하게 됩니다.이후, 아래의 여러 옵션 중에 “File”을 클릭하고 “BasicComposable”이라는 이름을 작성한 후 엔터를 누르면 BasicComposable.kt이라는 이름의 파일이 생성됩니다.
package로 시작되는 파일 위치 정보 외에는 작성된 내용이 없을 것입니다.아래와 같이 코드를 작성해봅니다.
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
@Composable
fun BasicComposable() {
// 여기에서 컴포저블을 작성하면 Preview로 바로 확인할 수 있게 됩니다.
}
@Preview(showBackground = true)
@Composable
private fun BasicComposablePreview() {
BasicComposable()
}
Compose에서 화면의 모든 글자를 책임지는 기본 컴포넌트입니다.
// import 구문은 상단에 import 구문이 모여있는 곳에서 작성해 주세요!
import androidx.compose.material3.Text
// 아래 코드는 BasicComposable 함수 안에 작성해 주세요!
Text(text = "Hello Compose")

text 파라미터 하나만 지정해도 바로 화면에 표시됩니다.| 파라미터 | 설명 | 예시 |
|---|---|---|
fontSize | 글꼴 크기 | 20.sp |
fontWeight | 굵기 | FontWeight.Bold |
color | 글자색 | Color.Blue, Color.Black |
lineHeight | 행간 | 24.sp |
maxLines + overflow | 줄 수·말줄임 처리 | maxLines = 1, overflow = TextOverflow.Ellipsis |
stringResource(id = R.string…) 를 사용하면, 문자열 관리 및 다국어 지원에 용이해집니다.Compose에서 사용자의 클릭 액션을 처리하는 기본 컴포넌트입니다.
import androidx.compose.material3.Button
Button(onClick = { /* 클릭 시 실행할 동작 */ }) {
Text("확인")
}
onClick은 간단히 람다로 전달되며, 별도의 리스너 인터페이스 설정이 필요 없습니다.| 버튼 컴포저블 | 설명 | 특징 예시 |
|---|---|---|
Button | 가장 많이 사용되는 기본 버튼 | 선명한 배경색과 Elevation(그림자 효과) 적용 |
FilledTonalButton | 상대적으로 부드러운 느낌의 강조 버튼 | 배경색은 있지만 대비가 낮아 부드러운 인상을 줌 |
ElevatedButton | 살짝 띄워진 효과로 강조하는 버튼 | 배경색은 없음, 대신 Elevation으로 시각적 강조 |
OutlinedButton | 덜 중요한 행동에 사용하는 보조 버튼 | 테두리만 있고 배경색 없음 |
TextButton | 강조가 거의 필요 없는 간단한 텍스트 링크처럼 사용하는 버튼 | 배경·테두리 없음, 글자만 표시 |
Button, 추가 설명이나 부가 기능은 TextButton처럼 의도에 따라 명확한 구분을 두는 것이 좋습니다.버튼은 다양한 속성을 조합하여 상태(활성/비활성), 모양, 내용 구성을 자유롭게 변경할 수 있습니다.
| 커스터마이징 요소 | 설명 |
|---|---|
| 활성화/비활성화 | enabled = false 처럼 Boolean 값으로 설정하여, 클릭 가능 여부를 제어할 수 있습니다. |
| 모양 조정 | shape = RoundedCornerShape(12.dp) 를 통해 버튼의 모서리를 둥글게 만들 수 있습니다. |
| 아이콘 포함 | 버튼 내부에 Icon(), Spacer(), Text()를 조합해 아이콘이 있는 버튼을 쉽게 만들 수 있습니다. |
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun BasicComposable(isFormValid: Boolean) {
Button(
onClick = { /* 클릭 시 동작 */ },
enabled = isFormValid, // 활성/비활성 상태 제어
shape = RoundedCornerShape(12.dp), // 모서리 둥글기 조정
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.Send,
contentDescription = "보내기"
)
Spacer(modifier = Modifier.width(8.dp))
Text("보내기")
}
}
@Preview(showBackground = true)
@Composable
private fun BasicComposablePreview() {
BasicComposable(
isFormValid = true,
)
}
isFormValid는 입력값이 유효한지를 판단하는 Boolean 변수로, 이 값이 false일 경우 버튼이 비활성화되어 클릭할 수 없도록 제어할 수 있습니다.Icon()과 Text() 사이에 Spacer()를 넣어 적절한 간격을 확보하면, 가독성과 터치 정확성이 모두 향상됩니다.RoundedCornerShape를 활용하면 버튼 모양을 앱의 전체 디자인 톤에 맞게 조절할 수 있어, UI 일관성과 사용자 경험 측면에서 큰 장점이 됩니다.정적 이미지부터 네트워크 이미지까지 폭넓게 지원하는 컴포넌트입니다.
Compose의 Image() 컴포저블은 Bitmap이 아닌 Painter 객체를 받습니다. 이를 통해 아래와 같은 다양한 이미지 리소스를 동일한 방식으로 쉽게 처리할 수 있습니다.
painterResource)rememberVectorPainter)rememberAsyncImagePainter)Image(
painter = painterResource(id = R.drawable.banner),
contentDescription = null, // 접근성 설명
modifier = Modifier.fillMaxWidth(),
contentScale = ContentScale.Crop // 잘라내기 방식 지정
)
contentScale(예: Fit, Crop), alpha, colorFilter 등 다양한 미디어 전용 파라미터를 활용해 시각 효과를 간단히 조절할 수 있습니다.rememberAsyncImagePainter를 사용할 수 있으며, 내부에 이미지 캐싱과 로딩 인디케이터 기능이 내장되어 있어 매우 효율적입니다.contentDescription)스크린 리더와 같은 보조 기술을 사용하는 사용자를 위해, 이미지에는 반드시 적절한 설명을 함께 제공해야 합니다.
contentDescription = null → 화면 해설 기능이 이미지를 무시합니다."상품 이미지", "사용자 프로필" 등 의미 있는 텍스트를 입력합니다.UI를 구성할 때 가장 많이 사용되는 배치용 컴포저블입니다.
방향성과 겹침 유무에 따라 세 가지가 구분됩니다.
| 레이아웃 | 방향 | 주요 파라미터 | 용도 예시 |
|---|---|---|---|
Column | 수직 배치 | verticalArrangement, horizontalAlignment | 위에서 아래로 요소 나열 – 리스트, 폼 등 |
Row | 수평 배치 | horizontalArrangement, verticalAlignment | 좌우로 나란한 배치 – 버튼 그룹, 카드 레이아웃 등 |
Box | 겹침 배치(Z축) | contentAlignment, propagateMinConstraints | 겹치는 요소 – 썸네일 위 아이콘, 오버레이 등 |
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun BasicComposable() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
text = "제목",
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
)
Text(
text = "본문 설명입니다.",
fontSize = 16.sp,
)
Text(
text = "날짜: 2025.xx.xx",
fontSize = 12.sp,
color = Color.Gray,
)
}
}
@Preview(showBackground = true)
@Composable
private fun BasicComposablePreview() {
BasicComposable()
}

Column을 사용하면 각 요소를 위에서 아래로 나열할 수 있습니다.verticalArrangement에 Arrangement.spacedBy(8.dp) 같은 값을 사용하면 요소 간의 간격을 쉽게 조절할 수 있습니다.fontSize, fontWeight, color 등의 속성을 직접 지정하여, 원하는 텍스트 스타일을 간단하게 표현할 수 있습니다.📌 학습 포인트
Column은 세로 방향 배치의 기본 컴포저블 함수입니다.- 내부 요소 간 간격은
Arrangement를 사용해 조절할 수 있습니다.
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun BasicComposable() {
Row(
modifier =
Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
painter = painterResource(R.drawable.ic_launcher_background),
contentDescription = "프로필 사진",
modifier =
Modifier
.size(56.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop,
)
Text(
text = "Username",
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
modifier =
Modifier
.padding(start = 12.dp)
.weight(1f),
)
IconButton(onClick = { /* TODO */ }) {
Icon(Icons.Default.MoreVert, contentDescription = "메뉴")
}
}
}
@Preview(showBackground = true)
@Composable
private fun BasicComposablePreview() {
BasicComposable()
}

Row는 각 요소를 좌우로 나란히 정렬할 수 있으며, verticalAlignment = Alignment.CenterVertically를 통해 수직 정렬도 함께 지정할 수 있습니다.Text는 weight(1f)를 설정하여 남은 공간을 채우도록 했습니다.clip(CircleShape)을 통해 원형으로 표시되며, 오른쪽에는 메뉴 아이콘 버튼이 위치합니다.IconButton은 별도의 액션 버튼이나 메뉴용 아이콘 등을 배치할 때 활용됩니다.📌 학습 포인트
Row는 가로 방향 UI를 구성할 때 가장 기본이 되는 컴포저블 함수 입니다.verticalAlignment속성으로 내부 요소의 세로 정렬을 제어할 수 있습니다.weight()를 사용하면 각 요소가 차지하는 비율을 조절할 수 있어, 반응형 UI를 보다 쉽게 구성할 수 있습니다.clip(CircleShape)는 이미지를 원형으로 표현할 때 유용한 기법입니다.
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun BasicComposable() {
Box(modifier = Modifier.size(120.dp)) {
Image(
painter = painterResource(R.drawable.ic_launcher_background),
contentDescription = "썸네일",
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
Icon(
imageVector = Icons.Default.PlayArrow,
contentDescription = "재생 아이콘",
modifier =
Modifier
.align(Alignment.Center)
.size(36.dp)
.background(Color.Black.copy(alpha = 0.5f), shape = CircleShape)
.padding(4.dp),
tint = Color.White,
)
}
}
@Preview(showBackground = true)
@Composable
private fun BasicComposablePreview() {
BasicComposable()
}

align(Alignment.Center)를 사용하면 자식 요소를 정중앙에 배치할 수 있고, 아이콘 뒤에 background(Color.Black.copy(alpha = 0.5f))를 사용하면 배경이 반투명하게 보여 시각적으로 구분하기 쉬워집니다.fillMaxSize()를 사용하면 이미지가 부모(Box)의 크기를 가득 채우도록 설정할 수 있습니다.📌 학습 포인트
Box는 여러 요소를 겹쳐 배치할 수 있는 컴포저블 함수입니다align을 사용하면 자식 요소의 위치를 조절할 수 있습니다fillMaxSize()를 사용하면 이미지가 부모(Box)의 크기에 맞춰집니다background와padding을 조합하면 아이콘 주변에 공간을 만들고 터치 영역도 확보할 수 있습니다alpha값을 조정하면 배경을 반투명하게 만들어 요소를 더 잘 보이게 할 수 있습니다
컴포저블을 꾸미고 배치하는 도구
Modifier는 Jetpack Compose에서 컴포저블의 크기, 위치, 색상, 동작 등을 설정할 수 있는 핵심 구성 요소입니다. 대부분의 컴포저블 함수에서modifier파라미터를 통해 사용할 수 있으며, UI를 세밀하게 조정할 수 있도록 도와줍니다.
⚠️ Modifier 코드 예시는 BasicComposable 안에 바로 넣으면 제대로 동작하지 않습니다. 아래의 코드를 활용하면 실습을 진행하실 수 있습니다.
Box(modifier = /*Modifier 예시 코드*/ )
Modifier를 사용하면 다음과 같은 작업들을 간결하게 처리할 수 있습니다:
fillMaxWidth, padding, weight)background, shadow, clip)clickable, scrollable, pointerInput)이처럼 Modifier는 모양을 지정하는 역할 외에도, 컴포저블의 동작과 구조까지 제어하는 도구로 사용됩니다.
여러 Modifier를 함께 체이닝하여 복합적인 UI를 구성할 수 있습니다.
Modifier
.padding(12.dp)
.background(Color.Yellow)
.clip(RoundedCornerShape(8.dp))
.clickable { /* 클릭 이벤트 */ }
Modifier는 체이닝(줄줄이 연결) 방식으로 작성되며, 적용하는 순서에 따라 결과가 달라질 수 있습니다.
Modifier.background(Color.Blue).padding(16.dp)

Modifier.padding(16.dp).background(Color.Blue)

순서를 바꾸는 것만으로도 UI의 모양이 크게 달라질 수 있기 때문에, Modifier를 쓸 때는 항상 순서를 의식하며 작성해야 합니다.
📌 학습 포인트
- Modifier는 컴포저블의 스타일과 레이아웃, 동작을 제어하는 핵심 도구입니다
- Modifier는 왼쪽부터 순서대로 적용되며, 작성 순서에 따라 결과가 달라집니다
- padding과 background처럼 자주 함께 사용하는 Modifier는 순서를 바꿔보며 결과를 비교해보는 연습이 중요합니다
- 체이닝 방식이므로 여러 Modifier 옵션을 조합해 원하는 UI를 만들 수 있습니다
이번 글에서는 Jetpack Compose의 기본 UI 구성 요소와 Modifier 사용법을 익히며 화면 구성을 연습해보았습니다.
다음 글에서는 Compose에서 동적인 UI를 만들기 위한 핵심 개념인 상태 관리를 살펴보려고 합니다. remember, mutableStateOf, rememberSaveable을 통해 상태를 정의하고 활용하는 방법, 그리고 상태에 따라 UI가 어떻게 변하는지를 실습 중심으로 함께 배워보겠습니다. 🚀