Skip to main content
Version: Next

ScrollView

플랫폼의 ScrollView를 감싸면서 터치 잠금 "응답자" 시스템과의 통합을 제공하는 컴포넌트다.

ScrollView는 동작하기 위해 반드시 높이가 제한되어야 한다. 무한한 높이를 가진 자식 엘리먼트들을 제한된 높이의 컨테이너 안에 넣기 때문이다(스크롤 인터랙션을 통해). ScrollView의 높이를 제한하려면, 뷰의 높이를 직접 설정하거나(비추천), 모든 부모 뷰가 제한된 높이를 가지도록 해야 한다. {flex: 1}을 뷰 스택 아래로 전달하지 않으면 오류가 발생할 수 있으며, 엘리먼트 검사기를 통해 빠르게 디버깅할 수 있다.

아직은 다른 응답자가 이 스크롤 뷰가 응답자가 되는 것을 막는 경우를 지원하지 않는다.

<ScrollView> vs <FlatList> - 어떤 것을 사용해야 할까?

ScrollView는 모든 자식 React 컴포넌트를 한 번에 렌더링하지만, 이는 성능 저하를 초래할 수 있다.

예를 들어, 매우 긴 목록을 표시해야 하고, 여러 화면 분량의 콘텐츠가 있다고 가정해보자. 모든 항목에 대해 JS 컴포넌트와 네이티브 뷰를 한 번에 생성하면, 보이지 않는 항목까지도 렌더링되어 느린 성능과 메모리 사용량 증가를 초래할 수 있다.

이때 FlatList가 유용하다. FlatList는 항목이 화면에 나타나기 직전에 렌더링하고, 화면에서 벗어난 항목은 제거하여 메모리와 처리 시간을 절약한다.

FlatList는 또한 항목 사이에 구분선을 추가하거나, 여러 컬럼을 표시하거나, 무한 스크롤 로딩을 구현하는 등 다양한 기능을 기본적으로 지원한다.


참조

Props

View Props

View Props를 상속한다.

StickyHeaderComponent

스크롤 시 화면 상단에 고정되는 헤더를 렌더링하는 React 컴포넌트이다. stickyHeaderIndices와 함께 사용해야 한다. 커스텀 트랜지션을 사용하는 스틱키 헤더가 필요한 경우, 예를 들어 리스트에 애니메이션이 적용되거나 숨겨지는 헤더를 구현할 때 이 컴포넌트를 설정해야 한다. 컴포넌트를 제공하지 않으면 기본적으로 ScrollViewStickyHeader 컴포넌트가 사용된다.

타입
component, element

alwaysBounceHorizontal
iOS

이 값을 true로 설정하면 스크롤 뷰의 콘텐츠가 스크롤 뷰 자체보다 작더라도 수평 방향으로 끝에 도달했을 때 바운스 효과가 발생한다.

타입기본값
boolhorizontal={true}일 때 true
그 외의 경우 false

alwaysBounceVertical
iOS

이 값을 true로 설정하면, 스크롤 뷰의 콘텐츠가 스크롤 뷰 자체보다 작더라도 수직 방향으로 끝에 도달했을 때 바운스 효과가 발생한다.

타입기본값
boolvertical={true}일 때 false
그 외의 경우 true

automaticallyAdjustContentInsets
iOS

네비게이션 바나 탭 바/툴바 뒤에 위치한 스크롤 뷰의 콘텐츠 여백을 iOS가 자동으로 조정할지 여부를 제어한다.

타입기본값
booltrue

automaticallyAdjustKeyboardInsets
iOS

키보드 크기가 변경될 때 ScrollView가 contentInsetscrollViewInsets을 자동으로 조정할지 여부를 제어한다.

타입기본값
boolfalse

automaticallyAdjustsScrollIndicatorInsets
iOS

iOS가 스크롤 인디케이터의 패딩을 자동으로 조정할지 여부를 제어한다. Apple의 해당 속성 문서를 참고한다.

타입기본값
booltrue

bounces
iOS

이 값이 true로 설정되면, 스크롤 방향 축에서 콘텐츠가 스크롤 뷰보다 큰 경우, 콘텐츠 끝에 도달했을 때 스크롤 뷰가 튕기는 효과가 발생한다. false로 설정하면, alwaysBounce* 속성이 true로 설정되어 있어도 모든 튕김 효과를 비활성화한다.

타입기본값
booltrue

bouncesZoom
iOS

true로 설정하면, 제스처로 인해 줌이 최소/최대 값을 넘어갈 수 있으며, 제스처가 끝날 때 줌이 최소/최대 값으로 애니메이션과 함께 돌아간다. false로 설정하면 줌이 한계를 넘지 않는다.

타입기본값
booltrue

canCancelContentTouches
iOS

이 값을 false로 설정하면, 트래킹이 시작된 후 터치가 이동해도 드래그를 시도하지 않는다.

타입기본값
booltrue

centerContent
iOS

true로 설정하면, 콘텐츠가 스크롤 뷰의 경계보다 작을 때 자동으로 콘텐츠를 중앙에 배치한다. 콘텐츠가 스크롤 뷰보다 큰 경우, 이 속성은 아무런 영향을 미치지 않는다.

타입기본값
boolfalse

contentContainerStyle

이 스타일은 모든 자식 뷰를 감싸는 스크롤 뷰 컨텐츠 컨테이너에 적용된다. 예를 들면 다음과 같다:

return (
<ScrollView contentContainerStyle={styles.contentContainer}>
</ScrollView>
);
...
const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 20
}
});
타입
View Style

contentInset
iOS

스크롤 뷰의 콘텐츠가 스크롤 뷰의 가장자리로부터 얼마나 안쪽으로 들어간지를 나타낸다.

타입기본값
객체: {top: number, left: number, bottom: number, right: number}{top: 0, left: 0, bottom: 0, right: 0}

contentInsetAdjustmentBehavior
iOS

이 속성은 스크롤 뷰의 콘텐츠 영역을 수정할 때 안전 영역 마진을 어떻게 사용할지 지정한다. iOS 11 이상에서 사용 가능하다.

타입기본값
enum('automatic', 'scrollableAxes', 'never', 'always')'never'

contentOffset

스크롤의 시작 위치를 수동으로 설정할 때 사용한다.

타입기본값
Point{x: 0, y: 0}

decelerationRate

사용자가 손가락을 뗀 후 스크롤 뷰가 얼마나 빠르게 감속하는지를 결정하는 부동소수점 숫자이다. 문자열 단축키 "normal""fast"를 사용할 수도 있으며, 이는 각각 iOS의 UIScrollViewDecelerationRateNormalUIScrollViewDecelerationRateFast 설정에 대응한다.

  • 'normal': iOS에서는 0.998, Android에서는 0.985.
  • 'fast': iOS에서는 0.99, Android에서는 0.9.
타입기본값
enum('fast', 'normal'), number'normal'

directionalLockEnabled
iOS

이 값을 true로 설정하면, ScrollView는 드래그 중에 수직 또는 수평 스크롤 중 하나로만 고정하려고 시도한다.

타입기본값
boolfalse

disableIntervalMomentumtrue로 설정하면, 스크롤 뷰는 제스처의 속도와 상관없이 릴리스 시점의 스크롤 위치를 기준으로 다음 인덱스에서 멈춘다. 이 기능은 페이지의 너비가 가로 스크롤 뷰의 너비보다 작거나, 페이지의 높이가 세로 스크롤 뷰의 높이보다 작을 때 페이징에 유용하게 사용할 수 있다.

타입기본값
boolfalse

disableScrollViewPanResponder

이 값을 true로 설정하면 ScrollView의 기본 JS pan responder가 비활성화되고, ScrollView 내부의 터치 제어가 자식 컴포넌트에 완전히 위임된다. 이 옵션은 snapToInterval이 활성화된 경우 특히 유용하다. snapToInterval은 일반적인 터치 패턴을 따르지 않기 때문이다. snapToInterval 없이 일반적인 ScrollView 사용 사례에서는 이 옵션을 사용하지 않는 것이 좋다. 스크롤 중 예기치 않은 터치가 발생할 수 있다.

타입기본값
boolfalse

endFillColor
Android

스크롤뷰가 콘텐츠보다 더 많은 공간을 차지하는 경우가 있다. 이럴 때 이 프로퍼티를 사용하면 스크롤뷰의 남은 공간을 색상으로 채울 수 있다. 이렇게 하면 배경을 설정할 필요 없이 불필요한 오버드로를 방지할 수 있다. 일반적인 경우에는 필요하지 않은 고급 최적화 기법이다.

타입
color

fadingEdgeLength
Android

스크롤 콘텐츠의 가장자리를 흐리게 처리한다.

이 값이 0보다 크면, 현재 스크롤 방향과 위치에 따라 가장자리가 흐려진다. 이를 통해 더 많은 콘텐츠가 있는지 여부를 표시한다.

타입기본값
number0

horizontaltrue로 설정되면, 스크롤 뷰의 자식 엘리먼트들이 세로가 아닌 가로로 배열된다.

타입기본값
boolfalse

indicatorStyle
iOS

스크롤 인디케이터의 스타일을 지정한다.

  • 'default': black과 동일하다.
  • 'black': 스크롤 인디케이터가 검정색이다. 밝은 배경에 적합하다.
  • 'white': 스크롤 인디케이터가 흰색이다. 어두운 배경에 적합하다.
타입기본값
enum('default', 'black', 'white')'default'

invertStickyHeaders

스크롤 뷰에서 스틱키 헤더가 상단이 아닌 하단에 고정되도록 설정한다. 주로 뒤집힌 스크롤 뷰와 함께 사용한다.

타입기본값
boolfalse

keyboardDismissMode

드래그 동작에 따라 키보드가 사라지는 방식을 결정한다.

  • 'none': 드래그해도 키보드가 사라지지 않는다.
  • 'on-drag': 드래그가 시작되면 키보드가 사라진다.

iOS 전용

  • 'interactive': 드래그와 함께 키보드가 상호작용하며 사라지고, 터치와 동기화되어 움직인다. 위로 드래그하면 키보드 사라짐이 취소된다. Android에서는 이 기능을 지원하지 않으며, 'none'과 동일하게 동작한다.
타입기본값
enum('none', 'on-drag')
Android

enum('none', 'on-drag', 'interactive')
iOS
'none'

keyboardShouldPersistTaps

키보드가 탭 이후에도 계속 표시될지 여부를 결정한다.

  • 'never': 키보드가 올라온 상태에서 포커스된 텍스트 입력 외부를 탭하면 키보드가 사라진다. 이 경우, 자식 컴포넌트는 탭 이벤트를 받지 못한다.
  • 'always': 키보드가 자동으로 사라지지 않으며, 스크롤 뷰가 탭을 잡아내지 않는다. 하지만 스크롤 뷰의 자식 컴포넌트가 탭을 잡아낼 수 있다.
  • 'handled': 스크롤 뷰의 자식 컴포넌트(또는 상위 컴포넌트)가 탭을 처리한 경우, 키보드가 자동으로 사라지지 않는다.
  • false: 더 이상 사용되지 않음, 'never'를 대신 사용한다.
  • true: 더 이상 사용되지 않음, 'always'를 대신 사용한다.
타입기본값
enum('always', 'never', 'handled', false, true)'never'

maintainVisibleContentPosition

이 옵션을 설정하면 스크롤 뷰는 현재 보이는 첫 번째 자식 엘리먼트의 위치를 유지하도록 스크롤 위치를 조정한다. 이때 해당 엘리먼트는 minIndexForVisible 이상의 인덱스를 가져야 한다. 이 기능은 양방향으로 콘텐츠를 로드하는 리스트(예: 채팅 스레드)에서 유용하다. 새로운 메시지가 추가될 때 스크롤 위치가 튀는 현상을 방지할 수 있다. 일반적으로 값은 0으로 설정하지만, 로딩 스피너나 위치를 유지하지 않아야 할 콘텐츠를 건너뛰기 위해 1과 같은 다른 값을 사용할 수도 있다.

선택적으로 autoscrollToTopThreshold를 설정하면, 사용자가 조정 전에 상단 임계값 이내에 있었다면 콘텐츠를 자동으로 상단으로 스크롤할 수 있다. 이는 채팅과 같은 애플리케이션에서 새 메시지가 자연스럽게 표시되도록 할 때 유용하다. 단, 사용자가 이미 상단에서 멀리 스크롤한 경우에는 스크롤이 방해가 될 수 있으므로 주의가 필요하다.

주의사항 1: 이 기능을 활성화한 상태에서 스크롤 뷰 내부의 엘리먼트 순서를 재정렬하면 스크롤이 튀거나 끊기는 현상이 발생할 수 있다. 이 문제는 해결 가능하지만, 현재는 개선할 계획이 없다. 따라서 이 기능을 사용하는 모든 ScrollView 또는 List의 콘텐츠 순서를 변경하지 않는 것이 좋다.

주의사항 2: 이 기능은 네이티브 코드에서 contentOffsetframe.origin을 사용해 콘텐츠의 가시성을 계산한다. 따라서 오클루전, 변환 등과 같은 복잡한 요소는 "보이는지 여부"를 판단할 때 고려되지 않는다.

타입
object: {minIndexForVisible: number, autoscrollToTopThreshold: number}

maximumZoomScale
iOS

허용되는 최대 확대 비율이다.

타입기본값
number1.0

minimumZoomScale
iOS

허용되는 최소 줌 배율.

타입기본값
number1.0

nestedScrollEnabled
Android

Android API 레벨 21 이상에서 중첩 스크롤을 활성화한다.

타입기본값
boolfalse

onContentSizeChange

ScrollView의 스크롤 가능한 콘텐츠 뷰가 변경될 때 호출된다.

핸들러 함수는 콘텐츠의 너비와 높이 (contentWidth, contentHeight)를 두 개의 인자로 받는다.

이 기능은 ScrollView가 렌더링하는 콘텐츠 컨테이너에 부착된 onLayout 핸들러를 통해 구현된다.

타입
function

onMomentumScrollBegin

스크롤 뷰가 미끄러지기 시작할 때 발생하는 모멘텀 스크롤이 시작될 때 호출된다.

타입
function

onMomentumScrollEnd

스크롤뷰가 미끄러지듯 멈출 때 발생하는 모멘텀 스크롤이 끝나면 호출된다.

타입
function

onScroll

스크롤 중에 최대 프레임당 한 번씩 발생한다. 이벤트는 다음과 같은 구조를 가진다(모든 값은 숫자 타입이다):

js
{
nativeEvent: {
contentInset: {bottom, left, right, top},
contentOffset: {x, y},
contentSize: {height, width},
layoutMeasurement: {height, width},
zoomScale
}
}
타입
function

onScrollBeginDrag

사용자가 스크롤 뷰를 드래그하기 시작할 때 호출된다.

타입
function

onScrollEndDrag

사용자가 스크롤 뷰 드래그를 멈추고, 스크롤이 완전히 정지하거나 미끄러지기 시작할 때 호출된다.

타입
function

onScrollToTop
iOS

스크롤 뷰가 상단으로 스크롤될 때 발생한다. 주로 상태 표시줄을 탭한 후에 이 이벤트가 실행된다.

타입
function

overScrollMode
Android

오버스크롤 모드의 기본값을 재정의할 때 사용한다.

가능한 값:

  • 'auto' - 콘텐츠가 충분히 크고 의미 있는 스크롤이 가능한 경우에만 오버스크롤을 허용한다.
  • 'always' - 항상 오버스크롤을 허용한다.
  • 'never' - 오버스크롤을 허용하지 않는다.
타입기본값
enum('auto', 'always', 'never')'auto'

pagingEnabled

이 값을 true로 설정하면 스크롤 뷰가 스크롤할 때 스크롤 뷰의 크기 배수 위치에서 멈춘다. 이 기능은 가로 방향 페이지네이션을 구현할 때 사용할 수 있다.

타입기본값
boolfalse

persistentScrollbar
Android

스크롤바가 사용되지 않을 때 투명해지지 않도록 설정한다.

타입기본값
boolfalse

pinchGestureEnabled
iOS

이 값을 true로 설정하면 ScrollView에서 핀치 제스처를 사용해 확대 및 축소할 수 있다.

타입기본값
booltrue

refreshControl

refreshControlScrollView당겨서 새로고침(pull-to-refresh) 기능을 제공하는 컴포넌트다. 이 기능은 세로 방향의 ScrollView에서만 동작하며, horizontal 속성을 false로 설정해야 한다.

자세한 내용은 RefreshControl 문서를 참고한다.

타입
엘리먼트

removeClippedSubviews

실험적 기능: true로 설정하면, 화면 밖에 있는 자식 뷰들( overflow 값이 hidden인 경우)이 네이티브 상위 뷰에서 제거된다. 이 기능은 긴 목록에서 스크롤 성능을 향상시킬 수 있다.

타입기본값
boolfalse

scrollEnabled

이 값을 false로 설정하면 터치 인터랙션을 통해 뷰를 스크롤할 수 없다.

단, scrollTo를 호출하면 언제든지 뷰를 스크롤할 수 있다.

타입기본값
booltrue

scrollEventThrottle

스크롤 이벤트가 발생하는 빈도를 제한하며, 시간 간격(ms)으로 지정한다. 스크롤에 반응해 비용이 많이 드는 작업을 수행할 때 유용하다. 값이 16 이하인 경우, 디바이스의 새로 고침 빈도와 상관없이 스로틀링이 비활성화된다.

타입기본값
number0

scrollIndicatorInsets
iOS

스크롤 뷰의 표시기(인디케이터)가 스크롤 뷰의 가장자리에서 얼마나 안쪽으로 들어갈지를 설정한다. 일반적으로 contentInset과 동일한 값으로 설정한다.

타입기본값
객체: {top: number, left: number, bottom: number, right: number}{top: 0, left: 0, bottom: 0, right: 0}

scrollPerfTag
Android

스크롤 성능을 기록하기 위해 사용되는 태그다. 이 태그는 모멘텀 이벤트를 강제로 활성화한다(자세한 내용은 sendMomentumEvents 참조). 기본적으로는 아무런 동작을 하지 않으며, 이를 활용하려면 커스텀 네이티브 FpsListener를 구현해야 한다.

타입
string

scrollToOverflowEnabled
iOS

이 값이 true로 설정되면, 스크롤 뷰는 프로그래밍 방식으로 콘텐츠 크기를 넘어서 스크롤할 수 있다.

타입기본값
boolfalse

scrollsToTop
iOS

true로 설정하면, 상태 바를 탭할 때 스크롤 뷰가 상단으로 스크롤된다.

타입기본값
booltrue

showsHorizontalScrollIndicator

이 값을 true로 설정하면 수평 스크롤 표시기가 나타난다.

타입기본값
booltrue

showsVerticalScrollIndicator

true로 설정하면 세로 스크롤 표시기를 보여준다.

타입기본값
booltrue

snapToAlignment
iOS

snapToInterval이 설정된 경우, snapToAlignment는 스크롤 뷰에서 스냅핑의 위치를 정의한다.

가능한 값:

  • 'start'는 스냅을 왼쪽(가로) 또는 상단(세로)에 정렬한다.
  • 'center'는 스냅을 중앙에 정렬한다.
  • 'end'는 스냅을 오른쪽(가로) 또는 하단(세로)에 정렬한다.
타입기본값
enum('start', 'center', 'end')'start'

snapToEnd

snapToOffsets와 함께 사용한다. 기본적으로 리스트의 끝은 스냅 오프셋으로 간주된다. snapToEnd를 false로 설정하면 이 동작을 비활성화하고 리스트가 끝과 마지막 snapToOffsets 오프셋 사이에서 자유롭게 스크롤되도록 한다.

타입기본값
booltrue

snapToInterval

이 값을 설정하면 스크롤 뷰가 snapToInterval 값의 배수 위치에서 멈춘다. 이 기능은 스크롤 뷰보다 길이가 작은 자식 요소들을 페이지 단위로 넘길 때 유용하다. 일반적으로 snapToAlignmentdecelerationRate="fast"와 함께 사용한다. 이 설정은 덜 유연한 pagingEnabled 속성을 대체한다.

타입
number

snapToOffsets

이 속성을 설정하면 스크롤 뷰가 정의된 오프셋 위치에서 멈춘다. 스크롤 뷰보다 작은 크기의 다양한 자식 요소를 페이지 단위로 넘길 때 유용하다. 일반적으로 decelerationRate="fast"와 함께 사용한다. 이 속성은 더 제한적인 설정을 가진 pagingEnabledsnapToInterval 속성을 덮어쓴다.

타입
숫자 배열

snapToStart

snapToOffsets와 함께 사용한다. 기본적으로 리스트의 시작 부분이 스냅 오프셋으로 간주된다. snapToStartfalse로 설정하면 이 동작을 비활성화하고, 리스트의 시작 부분과 첫 번째 snapToOffsets 오프셋 사이에서 자유롭게 스크롤할 수 있다.

타입기본값
booltrue

stickyHeaderHiddenOnScroll

이 값을 true로 설정하면 리스트를 아래로 스크롤할 때 스틱키 헤더가 숨겨진다. 그리고 위로 스크롤할 때 리스트 상단에 고정된다.

타입기본값
boolfalse

stickyHeaderIndices

스크롤할 때 화면 상단에 고정될 자식 요소들의 인덱스를 지정하는 배열이다. 예를 들어, stickyHeaderIndices={[0]}을 전달하면 첫 번째 자식 요소가 스크롤 뷰의 상단에 고정된다. 여러 요소를 상단에 고정하려면 [x,y,z]와 같은 형태로 여러 인덱스를 지정할 수 있다. 이 속성은 horizontal={true}와 함께 사용할 수 없다.

타입
숫자 배열

zoomScale
iOS

스크롤 뷰 콘텐츠의 현재 확대/축소 비율을 나타낸다.

타입기본값
number1.0

메서드

flashScrollIndicators()

tsx
flashScrollIndicators();

스크롤 인디케이터를 잠시 동안 표시한다.

scrollTo()

tsx
scrollTo(
options?: {x?: number, y?: number, animated?: boolean} | number,
deprecatedX?: number,
deprecatedAnimated?: boolean,
);

특정 x, y 좌표로 즉시 이동하거나 부드러운 애니메이션과 함께 스크롤한다.

예제:

scrollTo({x: 0, y: 0, animated: true})

참고: 이 함수의 독특한 시그니처는 역사적인 이유로 인해 옵션 객체 대신 개별 인자를 받을 수 있도록 설계된 것이다. 이 방식은 모호성(y가 x보다 먼저 오는 문제) 때문에 더 이상 사용하지 않는 것이 좋다.

scrollToEnd()

tsx
scrollToEnd(options?: {animated?: boolean});

이 메서드는 수직 ScrollView인 경우 맨 아래로 스크롤한다. 수평 ScrollView인 경우 오른쪽 끝으로 스크롤한다.

부드러운 애니메이션 효과를 원한다면 scrollToEnd({animated: true})를 사용하고, 즉각적인 스크롤을 원한다면 scrollToEnd({animated: false})를 사용한다. 옵션을 전달하지 않으면 animated는 기본값인 true로 설정된다.