본문 바로가기
Android (Kotlin & Compose)/Part 2. Jetpack Compose UI

인스타그램 뺨치는 UI? 10분 만에 끝내는 SNS 피드 앱 만들기 (Jetpack Compose 실습)

by 생각하는 개발자님 2026. 2. 9.
반응형

안녕하세요, '생각하는 개발자'입니다.

드디어 Part 2의 마지막 여정입니다! 그동안 우리는 화면을 배치하고, 상태를 관리하고, 목록을 만들고, 화면을 이동하는 법까지 숨 가쁘게 달려왔습니다. 이제 이 조각들을 모아 '진짜 앱' 같은 SNS 피드 화면을 만들어 볼 시간입니다.

이 실습을 마치면 "나도 이제 화면 하나는 뚝딱 만들 수 있겠는데?"라는 자신감을 얻게 되실 겁니다.



[내부 링크: 이전 강의 복습하기]
👉 [2-3] 무한 스크롤의 핵심, LazyColumn 완벽 가이드 (링크)

 

## 1. 실습 목표: 어떤 화면을 만드나요?

우리가 오늘 만들 화면은 전형적인 SNS 피드입니다.

  • 상단: 사용자 이름과 프로필 이미지
  • 중간: 메인 포스팅 이미지 (심플한 컬러 박스로 대체 가능)
  • 하단: 좋아요, 댓글, 공유 아이콘 및 게시물 텍스트

이 모든 것이 LazyColumn 안에서 부드럽게 스크롤되는 구조입니다.

 

## 2. 실습 코드: SnsFeedPractice.kt

안드로이드 스튜디오에서 새로운 코틀린 파일을 만들고 아래 코드를 실행해 보세요.

package com.example.composepractice.ch2_5_sns

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Send
import androidx.compose.material.icons.outlined.ChatBubbleOutline
import androidx.compose.material3.*
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.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

// 1. 데이터 모델
data class Post(val username: String, val content: String, val color: Color)

@Composable
fun SnsFeedScreen() {
    val posts = listOf(
        Post("Android_King", "오늘 날씨 정말 좋네요! 컴포즈 공부하기 딱!", Color.Cyan),
        Post("Compose_Master", "상태 관리(State)만 이해하면 끝입니다.", Color.Yellow),
        Post("Kotlin_Lover", "LazyColumn은 정말 혁신적이네요.", Color.LightGray)
    )

    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(title = { Text("오늘의 피드", fontSize = 18.sp) })
        }
    ) { paddingValues ->
        LazyColumn(modifier = Modifier.padding(paddingValues)) {
            items(posts) { post ->
                PostItem(post = post)
            }
        }
    }
}

@Composable
fun PostItem(post: Post) {
    Column(modifier = Modifier.fillMaxWidth()) {
        // 헤더 영역
        Row(
            modifier = Modifier.padding(12.dp).fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Box(modifier = Modifier.size(40.dp).clip(CircleShape).background(Color.Gray))
            Spacer(modifier = Modifier.width(10.dp))
            Text(text = post.username, style = MaterialTheme.typography.titleMedium)
            Spacer(modifier = Modifier.weight(1f))
            Icon(Icons.Default.MoreVert, contentDescription = null)
        }

        // 메인 이미지 영역 (컬러 박스로 대체)
        Box(modifier = Modifier.fillMaxWidth().height(300.dp).background(post.color))

        // 액션 버튼 영역
        Row(modifier = Modifier.padding(8.dp)) {
            IconButton(onClick = { }) { Icon(Icons.Default.FavoriteBorder, null) }
            IconButton(onClick = { }) { Icon(Icons.Outlined.ChatBubbleOutline, null) }
            IconButton(onClick = { }) { Icon(Icons.Default.Send, null) }
        }

        // 텍스트 영역
        Text(
            text = post.content,
            modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
            fontSize = 14.sp
        )
        Divider(modifier = Modifier.padding(top = 16.dp), thickness = 0.5.dp)
    }
}

@Preview(showBackground = true)
@Composable
fun SnsFeedPreview() {
    SnsFeedScreen()
}

## 3. 요약표: 사용된 컴포넌트 정리

컴포넌트 역할 비고
Scaffold 기본 앱 구조(TopBar 등) 제공 레이아웃의 뼈대
LazyColumn 효율적인 무한 스크롤 목록 구현 Part 2-3 핵심
Row/Column 가로/세로 배치 기본 레이아웃
Spacer(weight) 여백 및 아이콘 밀어내기 반응형 레이아웃 팁

 

## 4. 3초 팩트체크 이미지 가이드

빠른 렌더링: 리사이클러뷰보다 코드가 짧고 성능이 좋음.
쉬운 커스텀: 복잡한 애니메이션도 코드 몇 줄로 구현 가능.
유지보수: UI와 로직이 하나로 묶여 있어 관리가 쉬움.

## 5. Q&A 섹션

Q: 이미지를 넣으려면 어떻게 해야 하나요? A: Box 대신 AsyncImage(Coil 라이브러리)를 사용하면 인터넷 주소만으로도 이미지를 쉽게 불러올 수 있습니다. 이는 Part 4에서 자세히 다룰 예정입니다.

Q: 좋아요 버튼을 누르면 숫자가 올라가게 하고 싶어요. A: Part 2-2에서 배운 State를 활용하여 각 아이템마다 독립적인 상태값을 부여하면 됩니다.

 

[내부 링크: 다음 강의 예고]

👉 [3-1] 스파게티 코드 탈출! MVVM 아키텍처와 데이터 흐름 (링크)(예정)

반응형