# Scale URL: /foundations/feedback/scale Source: https://github.com/daangn/seed-design/blob/dev/docs/content/foundations/feedback/scale.mdx 누를 수 있는 요소는 눌린 동안 살짝 작아집니다. SEED는 모든 요소에서 눌린 느낌의 양이 같도록 축소량을 배율이 아닌 거리로 정의합니다. 누를 수 있는 요소는 눌린 동안 살짝 작아집니다. 이는 물리적인 버튼이 눌려 들어가는 감각을 차용한 것으로, 사용자가 손끝의 입력이 요소에 도달했음을 즉각적으로 인지하게 합니다. ![기본 상태와 눌린 상태의 버튼 비교 — 눌린 쪽이 점선으로 표시된 원래 크기보다 작아져 있다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/ba87da65-b188-46b9-865d-0cfdcf52de59) 이때 중요한 것은 **모든 요소에서 눌린 느낌의 양이 동일하게 느껴지는 것**입니다. SEED는 이를 위해 축소량을 배율이 아닌 거리로 정의합니다. 요소마다 고정된 배율(예: 0.98)을 지정하는 방식은 요소의 크기가 달라지면 실제로 움직이는 거리가 함께 달라진다는 한계가 있습니다. | 요소 크기 (폭 × 높이) | 지정된 배율 | 가로 축소 | 세로 축소 | | ------------------- | ------ | ------ | ------ | | 80 × 52 | 0.98 | 1.6px | 1.04px | | 160 × 52 | 0.98 | 3.2px | 1.04px | | 343 × 52 (모바일 전체 폭) | 0.98 | 6.9px | 1.04px | | 720 × 52 (태블릿 전체 폭) | 0.98 | 14.4px | 1.04px | 세로로는 모두 똑같이 줄어들지만, 가로로 줄어드는 양은 9배까지 차이가 납니다. 이 값에는 상한이 없기 때문에 화면이 커질수록 어색해집니다. 그래서 SEED는 **눌렸을 때 요소가 정해진 거리만큼 줄어든다**고 정의합니다. 배율은 미리 정하는 값이 아니라 요소의 실제 크기에서 계산되는 결과입니다. 요소가 크든 작든 움직이는 거리가 같으므로, 어떤 화면에서 무엇을 누르든 눌린 느낌이 비슷하게 전달됩니다. ## 계산 방식 축소량은 세로 `2px`입니다. 눌리면 요소가 세로로 이만큼 줄어듭니다. 이 거리를 어떤 길이에서 빼는지를 정하는 값을 \**기준 길이(basis)*\* 라고 합니다. ``` basis = max(요소 높이, 요소 폭 ÷ 4, 24) 배율 = (basis - 2) ÷ basis ``` ![높이 40px 버튼이 2px 줄어 배율 0.95가 되는 모습](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/03fc834d-0b38-411f-88d5-1d70f4e3dbdb) ![높이 100px 버튼이 같은 2px 줄어 배율 0.98이 되는 모습](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/a562c1a0-b240-491b-bc3c-3d03ba43f853) 기준 길이는 기본적으로 **요소의 높이**입니다. 가로쓰기 환경에서는 누를 수 있는 대부분의 요소가 가로로 길기 때문에, 폭보다 높이가 요소의 덩치를 더 잘 대표합니다. 여기에 두 가지 보정을 더해, 셋 중 가장 큰 값을 기준 길이로 씁니다. - **`요소 폭 ÷ 4`** — 좌우로 길고 위아래로 짧은 요소를 보정합니다. [List Item](/components/list)처럼 폭이 높이보다 훨씬 큰 요소에서 높이만 기준으로 삼으면 가로로 지나치게 많이 움직입니다. 폭이 넓을수록 기준 길이를 키워, 같은 2px이 그만큼 작은 비율이 되도록 합니다. - **최소 `24`** — 아주 작은 요소를 보정합니다. 원래 크기가 작으면 같은 2px이라도 축소 비율이 과도해집니다. 최소 기준 길이 24px은 축소 비율이 8.3%를 넘지 않도록 보장합니다. 축소량 `2`, 폭 보정값 `4`, 최소 기준 길이 `24`는 SEED를 사용하는 모든 화면에 동일하게 적용되는 고정값입니다. 눌린 느낌의 양을 어디서나 같게 만드는 것이 목적이므로 개별 요소나 서비스 단위로 변경하지 않습니다. ## 적용 결과 | 요소 | 크기 (폭 × 높이) | 적용된 basis | 계산된 배율 | 실제 축소 | | --------- | ----------- | --------- | ------ | ------------------ | | 아이콘 버튼 | 32 × 32 | 높이 | 0.938 | 가로 2px, 세로 2px | | 텍스트 버튼 | 120 × 48 | 높이 | 0.958 | 가로 5px, 세로 2px | | 가로로 긴 버튼 | 343 × 48 | 폭 ÷ 4 | 0.977 | 가로 8px, 세로 1.1px | | List Item | 375 × 60 | 폭 ÷ 4 | 0.979 | 가로 8px, 세로 1.3px | | 작은 버튼 | 22 × 22 | 최소 24 | 0.917 | 가로 1.8px, 세로 1.8px | 표에서 세로 축소가 2px인 것은 basis가 높이일 때입니다. 폭 보정이나 최소 기준 길이가 적용되면 basis가 커지므로 세로 축소는 2px보다 작아집니다. 좌우로 긴 요소에서는 세로 축소가 거의 사라지고, 대신 좌우 가장자리의 움직임이 눌린 느낌을 전달합니다. ## 축소의 기준점 축소는 항상 요소의 정가운데를 기준으로 일어납니다. ![버튼 정가운데에 중심점과 십자선이 표시되어, 축소가 그 지점을 기준으로 일어남을 보여준다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/9c6bf2f2-a0d0-4a8a-addd-ca8ca21e5144) ## 축소는 자리를 바꾸지 않습니다 축소는 요소가 차지하는 자리에 영향을 주지 않습니다. 눌린 요소가 작아져도 주변 요소는 움직이지 않고, 리스트에서 한 항목을 눌러도 위아래 항목의 위치는 그대로입니다. ## 직접 만드는 요소에 적용할 때 SEED가 제공하지 않는 컴포넌트에 축소를 적용할 때는 세 가지를 차례로 확인합니다. ### 1. 축소를 적용할지 확인하기 누를 수 있는 모든 요소가 축소되지는 않습니다. **줄어들 영역이 하나로 잡히는가.** 축소는 요소가 차지하는 영역이 하나의 면으로 잡힐 때 적용합니다. 기본 상태에 배경이 보이지 않아도 괜찮습니다. [Action Button](/components/action-button)의 ghost button이나 [Tabs](/components/tabs)의 개별 탭은 평소 배경이 없지만 여백과 최소 높이로 영역이 확보되어 있어 축소합니다. 반대로 링크 텍스트처럼 문장 안에 놓인 요소에는 적용하지 않습니다. 줄바꿈되면 영역이 여러 줄로 나뉘고, 문장 흐름 안에 있어 경계도 드러나지 않습니다. 줄어들어도 무엇이 줄어든 것인지 읽히지 않고 글자 크기가 변한 것처럼 보입니다. ![표면을 가진 Action Button — 눌리면 원래 크기보다 작아진다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/73443513-cd31-4e5b-b7dd-a1e07e1e8d01) ![표면이 없는 Text Button — 눌려도 크기가 그대로이고 배경과 색만 바뀐다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/065e5551-0534-45e4-b8a7-4d140efee730) **하위 동작이 요소 전체와 대등한가.** 요소 안에 여러 동작이 있어도, 하위 동작이 요소가 대표하는 일에 종속된다면 축소를 적용합니다. [List Item](/components/list)의 Switch는 그 행이 나타내는 설정을 바꾸는 것이므로 행에 종속됩니다. 어디를 누르든 같은 대상을 다루기 때문에 행 전체가 줄어들어도 모호하지 않습니다. ![하위 동작이 행에 종속되는 경우 — Switch를 품은 List Item이지만 어디를 누르든 같은 대상을 다루므로 행 전체가 반응한다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/020f3286-1cc9-4255-82ce-59c28e8385e8) ![대등한 동작이 나란히 놓인 경우 — 카드 안의 닫기 버튼과 좋아요 버튼을 각각 누르면 카드 전체가 아니라 눌린 버튼만 반응한다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/6cd2f9d2-cdad-4185-94ff-3e4c46cd6d52) 반면 카드 열기·좋아요·저장·작성자 이동처럼 서로 대등한 동작이 나란히 놓인 경우에는 적용하지 않습니다. 각각이 다른 대상을 향하므로 전체가 줄어들면 무엇이 눌린 것인지 모호해집니다. 이때 반응하는 것은 요소 전체가 아니라 사용자가 실제로 누른 타깃이며, 각 타깃이 자신의 피드백을 가집니다. ### 2. 무엇이 줄어들지 정하기 ![Root Scale — Switch 전체가 함께 작아진다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/17c9adc4-484c-4ccb-9310-cd7b6050671d) ![Content Scale — Accordion 배경은 그대로이고 안쪽 콘텐츠만 작아진다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/ec4d330f-2a94-4bd4-bc07-4dbb2d8b5407) 요소 전체를 줄였을 때 정렬·여백·모서리가 어긋나 보이는지로 판단합니다. - **어긋나지 않는다 → Root Scale.** 요소 전체가 함께 줄어듭니다. [Action Button](/components/action-button)처럼 배경과 콘텐츠가 하나의 표면으로 인식되는 요소가 여기 해당합니다. 전체가 함께 줄어도 내부 관계가 그대로 유지됩니다. - **어긋나 보인다 → Content Scale.** 배경은 그대로 두고 콘텐츠만 줄어듭니다. [List Item](/components/list), [Accordion](/components/accordion), Select Box Item처럼 배경이 화면 폭을 가득 채우고 그 안에 여러 요소가 정렬된 구조가 여기 해당합니다. 이런 구조를 통째로 줄이면 세 가지가 한꺼번에 어긋납니다. ![세로로 쌓인 List Item 중 하나만 전체 축소되어 정렬·여백·모서리가 어긋난 모습](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/75f95f0b-d52f-4a17-961e-365f6e5e1762) - **정렬** — 좌우 끝에 맞춰져 있던 요소가 안쪽으로 밀려 들어와, 위아래 항목과 시작선이 어긋납니다. - **여백** — 화면 가장자리까지 닿아 있던 배경이 줄어들면서 원래 설계한 여백과 달라집니다. - **모서리** — 모서리 반경까지 함께 줄어들어 주변 요소와 곡률이 맞지 않습니다. 배경은 대부분 변화를 주지 않습니다. 다만 [List Item](/components/list)처럼 배경이 화면 폭을 가득 채우고 Divider로 항목이 나뉘는 경우에는, 배경도 좌우 여백을 좁히고 모서리 반경을 키우는 방식으로 눌림을 함께 표현합니다. ### 3. 중첩되는지 확인하기 이미 축소하는 요소 안에 놓인다면 안쪽 요소의 축소를 끕니다. 두 축소가 겹치면 배율이 곱해져 안쪽 요소만 과도하게 작아집니다. [List Item](/components/list) 안의 Checkmark가 여기 해당합니다. 행 전체가 눌리면 Checkmark는 콘텐츠의 일부로 함께 줄어들 뿐, 자신의 축소를 따로 일으키지 않습니다. ### 유틸리티로 적용하기 세 가지를 확인했다면 공식을 직접 구현할 필요는 없습니다. 플랫폼마다 유틸리티를 제공합니다. | 플랫폼 | 사용 방법 | | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | React | 축소할 요소를 `ScaleFeedback`으로 감쌉니다. 감싸기 어려운 구조라면 `useScaleFeedback` hook으로 같은 값을 받을 수 있습니다. 계산된 배율은 `--seed-feedback-scale` CSS 변수로도 공개됩니다. Content Scale처럼 배경과 콘텐츠를 나눠야 하는 경우, 이 값을 콘텐츠 쪽에만 적용합니다. [Scale Feedback 가이드](/react/components/concepts/scale-feedback)를 참고하세요. | | iOS | UIKit은 `SeedPressedEffectInteraction`, SwiftUI는 `seedScaleEffect()`를 사용합니다. | | Android | Compose용 `Modifier.dynamicScale()`을 붙이면 렌더된 실제 크기 기반 배율이 자동으로 적용됩니다. `clickable`을 쓰는 구조라면 `indication = DynamicScaleIndication`으로 대신 넘길 수 있습니다. | 감싸기만 하면 요소 전체가 줄어듭니다. Content Scale이 필요한 요소는 콘텐츠 영역에만 배율을 적용해야 하므로, 플랫폼별 적용 방법을 확인하세요. ## 다른 상태와 함께 있을 때 요소는 눌림과 다른 상태를 동시에 가질 수 있습니다. 축소는 누르고 있는 동안에만 일어나므로, 원래 상태의 표현을 그대로 두고 잠시 더해집니다. ![Selected·Loading·Disabled 각 상태에서 눌렀을 때의 모습](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/e27d8783-0cbf-41a1-8d67-44729862760f) - **Selected** — 선택된 요소도 누르면 축소됩니다. 선택 상태를 나타내는 색상 표현은 그대로 유지됩니다. - **Loading** — 축소하지 않습니다. 이미 진행 중인 동작이 있어 추가 입력을 받지 않습니다. - **Disabled** — 축소하지 않습니다. 상호작용을 받지 않는 상태이므로 누름에 대한 반응도 일어나지 않습니다. 상태의 정의는 [State](/foundations/state)에서 다룹니다. ## Accessibility OS의 동작 줄이기(Reduce Motion) 설정이 켜져 있으면 배율은 항상 `1`로 계산되어 축소가 일어나지 않습니다. 이 경우 색상 변화 등 다른 상태 표현이 눌림을 전달합니다. ![Reduce Motion이 꺼진 경우 — 색 전환과 축소가 함께 일어난다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/dd580ad5-048f-41e4-937a-c337d99db5f4) ![Reduce Motion이 켜진 경우 — 축소 없이 색 전환만 일어난다](https://figma-alpha-api.s3.us-west-2.amazonaws.com/images/7eb4c479-3035-466d-b72f-114103801b03)