flex, flexGrow 및 반응형 크기 조정
flex 속성으로 형제 View 사이에 사용 가능한 공간을 비율에 따라 나누고, 어떤 화면 너비에도 맞게 조정되는 레이아웃을 만듭니다.
flex, flexGrow 및 반응형 크기 조정은(는) CoddyKit의 무료 React Native Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Native Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
The flex Property Explained
The flex property is a shorthand that sets how a View grows and shrinks to fill available space within its parent. In React Native, flex is similar to CSS's flex-grow — it represents the proportion of available space the component takes. Setting flex: 1 on a single child makes it fill all remaining space. When multiple siblings have flex values, the space is divided proportionally: a child with flex: 2 gets twice as much space as a sibling with flex: 1.
import { View } from 'react-native';
export default function FlexDemo() {
return (
<View style={{ flex: 1, flexDirection: 'column' }}>
{/* Takes 1/3 of height */}
<View style={{ flex: 1, backgroundColor: '#ff6b6b' }} />
{/* Takes 2/3 of height */}
<View style={{ flex: 2, backgroundColor: '#4f86f7' }} />
</View>
);
}flex: 1 on the Root Container
If your root App component or the outermost screen View doesn't have flex: 1, the component collapses to the size of its content — it does not fill the screen. This is one of the most common React Native bugs for beginners: the app appears to have no layout because the root View has zero height. Always set flex: 1 on the root-level View and any intermediate containers that should fill available space. Child Views without a fixed size or flex property will shrink to wrap their content.
import { View, Text, StyleSheet } from 'react-native';
// WRONG: root View has no flex, collapses to text height
function WrongLayout() {
return (
<View style={{ backgroundColor: '#f5f5f5' }}>
<Text>This View only wraps its content.</Text>
</View>
);
}
// CORRECT: flex: 1 fills the screen
function CorrectLayout() {
return (
<View style={{ flex: 1, backgroundColor: '#f5f5f5' }}>
<Text>This View fills the entire screen.</Text>
</View>
);
}flexGrow, flexShrink, and flexBasis
React Native's flex shorthand sets flexGrow, flexShrink, and flexBasis together. flexGrow controls how much a child grows into extra space. flexShrink controls how much it shrinks when space is tight. flexBasis sets the initial size before growing or shrinking (like CSS flex-basis). In practice, flex: 1 covers most use cases. Use flexShrink: 1 on a Text inside a row when you want it to shrink and show ellipsis instead of overflowing the row.
import { View, Text, StyleSheet } from 'react-native';
export default function FlexShrinkExample() {
return (
<View style={styles.row}>
<View style={styles.icon} />
{/* flexShrink: 1 allows text to shrink if the row is too small */}
<Text style={styles.label} numberOfLines={1}>
A very long label that could overflow without flexShrink
</Text>
<Text style={styles.badge}>NEW</Text>
</View>
);
}
const styles = StyleSheet.create({
row: { flexDirection: 'row', alignItems: 'center', padding: 12, gap: 8 },
icon: { width: 40, height: 40, borderRadius: 8, backgroundColor: '#4f86f7', flexShrink: 0 },
label: { flex: 1, flexShrink: 1, fontSize: 16, color: '#333' },
badge: { paddingHorizontal: 8, paddingVertical: 2, backgroundColor: '#ff6b6b', color: '#fff', borderRadius: 10, fontSize: 11, fontWeight: 'bold' },
});Dimensions API for Screen Size
To get the current screen width and height in JavaScript, use the Dimensions API from react-native. Dimensions.get('window') returns the visible app area (excluding system bars), while Dimensions.get('screen') returns the full physical screen. However, Dimensions is a static snapshot — it won't update if the user rotates the device. For responsive layouts that react to orientation changes, use the useWindowDimensions hook, which returns updated values on every resize.
import { View, Text, Dimensions, useWindowDimensions } from 'react-native';
// Static (doesn't update on rotation)
const { width, height } = Dimensions.get('window');
// Reactive (updates on rotation — preferred)
export default function ResponsiveScreen() {
const { width, height } = useWindowDimensions();
const isLandscape = width > height;
return (
<View style={{ flex: 1, padding: 16 }}>
<Text>Width: {Math.round(width)}</Text>
<Text>Height: {Math.round(height)}</Text>
<Text>Mode: {isLandscape ? 'Landscape' : 'Portrait'}</Text>
</View>
);
}Percentage Widths for Responsive Columns
Use percentage strings for width to create layouts that adapt to different screen sizes without hardcoding pixel values. A two-column grid uses width: '48%' on each card with a small gap. A three-column layout uses width: '32%'. The percentage is relative to the parent container's width. To ensure the math works, set the parent's width explicitly or make it flex: 1, and use flexWrap: 'wrap' on the row container so columns flow to the next line correctly.
import { View, StyleSheet } from 'react-native';
export default function TwoColumnGrid() {
return (
<View style={styles.grid}>
{[1, 2, 3, 4, 5, 6].map(n => (
<View key={n} style={styles.card} />
))}
</View>
);
}
const styles = StyleSheet.create({
grid: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 12,
padding: 16,
},
card: {
width: '47%', // ~2 per row with gap
height: 120,
backgroundColor: '#4f86f7',
borderRadius: 12,
},
});Combining flex with Fixed Dimensions
You can mix flex-based sizing with fixed width and height values in the same layout. A common pattern is a sidebar layout: a fixed-width side panel (e.g., width: 280) next to a content area with flex: 1 that fills the rest of the screen. The fixed-size panel takes exactly 280 points regardless of screen size, while the content panel grows or shrinks to use all remaining space. This also works for headers and footers: fixed height containers at top/bottom with a flex: 1 content area in between.
import { View, Text, StyleSheet } from 'react-native';
export default function MasterDetail() {
return (
<View style={styles.container}>
{/* Fixed-width sidebar */}
<View style={styles.sidebar}>
<Text style={{ color: '#fff' }}>Sidebar</Text>
</View>
{/* flex: 1 content fills remaining space */}
<View style={styles.content}>
<Text>Main content area</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, flexDirection: 'row' },
sidebar: { width: 200, backgroundColor: '#333', padding: 16 },
content: { flex: 1, backgroundColor: '#f5f5f5', padding: 16 },
});useWindowDimensions for Adaptive Layouts
The useWindowDimensions hook re-renders your component whenever the device orientation changes or a multi-window layout resizes. Use it to dynamically switch between single-column (portrait) and two-column (landscape) layouts. Calculate the number of columns based on the window width: if width is above a threshold (e.g., 600), switch to two or three columns. This approach makes your app look good on phones, large phones, tablets, and even desktops with Expo Web — without writing separate layout components.
import { View, StyleSheet, useWindowDimensions } from 'react-native';
export default function AdaptiveGrid({ items }) {
const { width } = useWindowDimensions();
const numColumns = width >= 768 ? 3 : width >= 480 ? 2 : 1;
const cardWidth = (width - 32 - (numColumns - 1) * 12) / numColumns;
return (
<View style={styles.grid}>
{items.map(item => (
<View key={item.id} style={[styles.card, { width: cardWidth }]} />
))}
</View>
);
}
const styles = StyleSheet.create({
grid: { flexDirection: 'row', flexWrap: 'wrap', gap: 12, padding: 16 },
card: { height: 120, backgroundColor: '#4f86f7', borderRadius: 10 },
});minWidth, maxWidth, minHeight, maxHeight
Use minWidth, maxWidth, minHeight, and maxHeight to constrain how much a View can grow or shrink. These are useful for creating components that look good across a range of content sizes without breaking at extremes. For example, a button might have a minWidth: 120 so it is always touchable even for a single-character label, but a maxWidth: 320 so it never stretches across a full tablet screen. Combining these with flex: 1 and width: '100%' is the typical pattern for centered, bounded content on larger screens.
import { View, Text, StyleSheet } from 'react-native';
export default function BoundedContent() {
return (
<View style={styles.screen}>
{/* Content is at most 480px wide, centered */}
<View style={styles.content}>
<Text style={styles.text}>This content is bounded to look good on all screen sizes.</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, alignItems: 'center', backgroundColor: '#f5f5f5', padding: 16 },
content: {
width: '100%',
maxWidth: 480, // doesn't stretch on tablets/web
backgroundColor: '#fff',
borderRadius: 12,
padding: 20,
},
text: { fontSize: 16, lineHeight: 24, color: '#333' },
});Aspect Ratio for Consistent Proportions
The aspectRatio style property sets the width-to-height ratio of a component. When the width is set (or determined by flex), aspectRatio automatically computes the height to maintain the proportion. aspectRatio: 16/9 creates a widescreen video thumbnail. aspectRatio: 1 creates a perfect square. This is especially powerful for media content that must adapt to different screen widths — the height automatically scales proportionally without any calculations or JavaScript.
import { View, Image, StyleSheet } from 'react-native';
export default function VideoThumbnail() {
return (
<View style={styles.thumbnailContainer}>
<Image
source={{ uri: 'https://picsum.photos/640/360' }}
style={styles.thumbnail}
/>
</View>
);
}
const styles = StyleSheet.create({
thumbnailContainer: {
width: '100%',
},
thumbnail: {
width: '100%',
aspectRatio: 16 / 9, // height auto-computed = width * 9/16
borderRadius: 10,
},
});Three-Panel Responsive Layout
Bring together all the sizing concepts: flex, maxWidth, and useWindowDimensions to build a classic three-panel layout for a note-taking or email app. On small phones, only one panel shows at a time. On tablets in landscape, all three panels appear side by side using flex ratios. This adaptive pattern is achievable with React Native's Flexbox and dimension hooks — no complex CSS media queries or separate layouts needed.
import { View, useWindowDimensions, StyleSheet } from 'react-native';
export default function ThreePanel() {
const { width } = useWindowDimensions();
const isTablet = width >= 768;
if (!isTablet) {
// Phone: single panel
return <View style={{ flex: 1, backgroundColor: '#f5f5f5' }} />;
}
// Tablet: three panels
return (
<View style={styles.row}>
<View style={[styles.panel, { flex: 1 }]} />
<View style={[styles.panel, { flex: 2, backgroundColor: '#e8f0fe' }]} />
<View style={[styles.panel, { flex: 2 }]} />
</View>
);
}
const styles = StyleSheet.create({
row: { flex: 1, flexDirection: 'row' },
panel: { backgroundColor: '#f5f5f5', borderRightWidth: 1, borderRightColor: '#ddd' },
});Avoiding Layout Pitfalls
Common React Native layout pitfalls to watch for: missing flex: 1 on a container makes it collapse to zero height; percentage widths without a sized parent resolve to zero; fixed heights in deeply nested views cause clipping on small screens; minHeight instead of flex on scroll containers prevents proper sizing. Debug by temporarily adding backgroundColor tints to each View — you'll immediately see which boxes are sized correctly and which are collapsing. When a component is invisible, suspect a zero-height parent before looking at the component's own styles.
// Debugging checklist when a component is invisible:
// 1. Does its parent have flex: 1 or an explicit height?
// 2. Does the component itself have flex or height/width?
// 3. Are percentage dimensions resolving against a zero-width parent?
// 4. Is backgroundColor set (to verify the View is rendered but transparent)?
// Quick visibility check:
<View style={{ flex: 1, backgroundColor: 'rgba(255,0,0,0.1)' }}>
{/* If this shows red tint, the container is sized correctly */}
<YourComponent />
</View>Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: flex: 1 fills remaining available space proportionally, useWindowDimensions provides reactive screen dimensions for orientation-aware layouts, and aspectRatio automatically computes height from width to maintain consistent proportions. Next up we explore building a responsive card grid with Flexbox wrapping.
자주 묻는 질문
“flex, flexGrow 및 반응형 크기 조정” 강의는 무료인가요?
네 — “flex, flexGrow 및 반응형 크기 조정” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Native Academy 강의 전체를 잠금 해제할 수 있습니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“flex, flexGrow 및 반응형 크기 조정”에서 뭘 배우나요?
flex 속성으로 형제 View 사이에 사용 가능한 공간을 비율에 따라 나누고, 어떤 화면 너비에도 맞게 조정되는 레이아웃을 만듭니다. 브라우저에서 직접 실행하는 실습 코드로 React Native Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
React Native Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 React Native Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“flex, flexGrow 및 반응형 크기 조정” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 React Native Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 React Native Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- StyleSheet.create와 인라인 스타일
- Flexbox 방향, JustifyContent, AlignItems
- flex, flexGrow 및 반응형 크기 조정
- 반응형 카드 격자 만들기