0.4, 0, 0.2, 1은 어떤 움직임인가
시리즈 베지어 곡선 읽기 2 / 2
- 1베지어 곡선: 곡선은 옆에 놓인 점을 따라온다
- 20.4, 0, 0.2, 1은 어떤 움직임인가

개발자: “모달 곡선 값 뭘로 할까요?”
디자이너: “0.4, 0, 0.2, 1로 해주세요.”
이 네 숫자를 넘겨 놓고 화면에서 어떤 움직임이 나오는지는 서로 확인하지 않는다. 1편에서 이 숫자가 무엇인지는 봤다. 짧게 되짚으면 이렇다. 네 숫자는 좌표 두 개이고, (0.4, 0)과 (0.2, 1)은 곡선에서 떨어진 자리에 놓인 점 둘의 위치다. 이 글에서는 그 둘을 가운데 두 제어점이라고 부른다. 곡선은 그 둘에 닿지 않고, 나가고 들어오는 방향과 세기만 그 둘이 정한다. 곡선이 실제로 지나는 양 끝 점은 언제나 (0, 0)과 (1, 1)이라 적을 필요가 없고, 그래서 적어 줄 값이 네 개다.
여기까지는 종이 위의 모양이다. 이 글은 그 모양이 화면에서 어떤 움직임이 되는지를 본다. 축에 시간과 진행률이라는 이름이 붙는 순간 무엇이 달라지는지, 왜 네 숫자 가운데 둘만 0과 1 사이에 갇히는지, 그리고 0.4, 0, 0.2, 1이 결국 어떤 움직임인지 순서대로 본다.
CSS의 베지어 곡선은 가로가 시간이고 세로가 진행률이다
0.3초짜리 이동에서 가로 0.5는 0.15초가 지난 순간이고, 세로 0.5는 갈 길의 절반을 갔다는 뜻이다. 펜툴로 그리는 베지어 곡선이 종이 위의 모양이라면, CSS가 쓰는 베지어 곡선은 가로가 시간이고 세로가 진행률인 그래프다. 계산은 똑같고 두 축에 붙은 이름만 다르다. 가로축의 0부터 1까지는 애니메이션이 시작해서 끝날 때까지의 시간이고, 세로축의 0부터 1까지는 목적지까지 얼마나 갔느냐다. 두 축이 이렇게 정해져 있으면 적어 줄 값의 개수까지 정해진다. 그 까닭은 조금 뒤에 본다.
여기서 그래프를 화면으로 착각하기 쉽다. 곡선이 위로 볼록하게 솟았다고 화면의 물건이 위로 뜨는 게 아니다. 솟았다는 것은 같은 시각에 이미 많이 갔다는 뜻일 뿐이고, 물건은 원래 가기로 한 방향으로만 간다.
모달이 화면 아래에서 올라오는 장면을 놓고 보면 어디서 헷갈리는지가 드러난다. 모달은 화면에서 위아래로 움직이고 그래프에도 세로축이 있다. 그런데 그래프의 세로축은 화면의 위아래가 아니라 갈 길 중 얼마나 갔느냐다. 같은 모달을 옆으로 미끄러지게 바꿔도 그래프는 똑같이 생긴다.
그럼 왜 숫자가 네 개인가. 점은 네 개인데 CSS가 받는 값은 두 점의 좌표뿐이다. 시작점이 언제나 (0, 0)이고 끝점이 언제나 (1, 1)이기 때문이다. 0초에 0%에서 나와 주어진 시간을 다 쓰면 100%에 닿는다는 것은 어느 곡선에서도 바뀌지 않는다. 안 바뀌는 값이라 적을 필요가 없고, 남은 가운데 두 제어점의 좌표 네 개가 그대로 cubic-bezier(x1, y1, x2, y2)다. x가 가로, 곧 시간이고 y가 세로, 곧 진행률이라, 네 숫자는 시간, 진행률, 시간, 진행률 순으로 늘어선다.
CSS 키워드도 결국 같은 좌표다. 스펙이 밝혀 둔 값을 보면 ease-in-out은 (0.42, 0, 0.58, 1)이고 ease-out은 (0, 0, 0.58, 1)이다.W3C, CSS Easing Functions Level 1, Cubic Bézier easing functions 섹션. ease-in-out Equivalent to cubic-bezier(0.42, 0, 0.58, 1). / ease-out Equivalent to cubic-bezier(0, 0, 0.58, 1). 2026년 7월에 w3.org/TR/css-easing-1/에서 원문을 확인했다.
키워드를 쓰든 괄호에 숫자를 적든 그리는 것은 같은 곡선이고, CSS는 이 곡선을 이징 곡선이라고 부른다.
아래 슬라이더로 네 값을 직접 옮겨 보면 좌표와 곡선과 움직임이 한 화면에서 같이 바뀐다.
cubic-bezier(0.42, 0, 0.58, 1)
방금 민 슬라이더 네 개는 좌표다. 그런데 곡선 위의 점을 실제로 구할 때 쓰는 값이 하나 더 있다. 두 점 사이를 어디서 나눌지 정하는 비율인데, 1편에서 이 비율을 0.3으로 놓고 세 번 나눠 봤더니 나온 점의 가로 좌표가 0.3이 아니라 0.2412였다. 둘 다 0에서 1까지라 같아 보여도 비율과 가로 좌표는 서로 다른 값이다.둘은 서로 다른 값이라, 비율을 0.5로 놓아도 가로 좌표가 0.5라는 보장이 없다. 어느 시점의 진행률을 알려면, 그 시점에 해당하는 비율을 거꾸로 찾은 다음 그 비율로 세로 좌표를 내야 한다.
가로축이 시간이라서 네 숫자에는 규칙이 하나 붙는다.
시간인 x만 0과 1 사이에 갇힌다
영상 재생 바의 손잡이는 왼쪽에서 오른쪽으로만 가고 저절로 되돌아가지 않는다. 이징 곡선의 가로축도 한 방향으로만 간다. 그래서 네 숫자 가운데 x 자리인 첫째와 셋째는 0과 1 사이를 벗어나면 값 자체가 무효이고, y 자리인 둘째와 넷째는 1을 넘어도 되고 음수여도 된다.
스펙은 가운데 두 제어점의 x가 0과 1 사이여야 하고 아니면 정의가 무효라고 적어 뒀다. y에는 같은 제한이 없다.W3C, CSS Easing Functions Level 1, Cubic Bézier easing functions 섹션. The x coordinates of P1 and P2 are restricted to the range [0, 1] / Both x values must be in the range [0, 1] or the definition is invalid. y에 제한이 없다는 것은 문법 줄이 정한다. cubic-bezier( <number [0,1]> , , <number [0,1]> , )로 x 두 자리에만 범위가 붙어 있다. 2026년 7월 확인.
x가 0과 1 밖으로 나가면 곡선이 한 번 왼쪽으로 되돌아가는 구간이 생길 수 있다. 그러면 0.3초 자리에 세로줄을 하나 그었을 때 곡선이 그 줄을 두 번 지나가서 진행률 값이 두 개가 되고, 그 순간에 무엇을 그려야 할지 정할 수가 없다. 재생 바의 손잡이가 저절로 왼쪽으로 되돌아가는 재생이 없는 것과 같은 이유다.
그래서 스펙은 되돌아가는 구간이 절대 안 생기는 범위를 잡아 x를 그 안에 가둬 뒀다. 0과 1 사이에 있기만 하면 어떤 값을 넣어도 안전하다.0과 1 사이를 잘게 나눠 x1과 x2의 조합 4만 쌍 남짓을 전부 훑어 봤더니 되돌아가는 구간이 한 번도 안 나왔다(2026년 7월, 직접 계산). 거꾸로 밖의 값이 전부 되돌아가는 것은 아니다. x1을 0 아래로 내리거나 x2를 1 위로 올리면 바로 나오지만, x1을 1 위로 올리는 정도로는 안 나오는 값도 있다. 스펙의 제한은 안 되는 값을 전부 골라낸 것이 아니라 언제나 되는 범위를 잡아 둔 것이다.
y는 사정이 다르다. 서랍을 세게 밀면 끝까지 나갔다가 살짝 도로 들어온다. y가 1을 넘으면 화면에서도 같은 일이 벌어져서, 물건이 목적지를 지나쳤다가 되돌아오는 구간이 생긴다. 이 움직임을 모션에서 오버슛이라고 부른다. cubic-bezier(0.34, 1.56, 0.64, 1)이 그런 값인데, 둘째 숫자가 1.56이라 곡선이 목적지를 한 번 지나쳤다 돌아온다. 이 글이 예로 고른 값이고, 앞의 슬라이더에 오버슛 프리셋으로 들어 있다.둘째 숫자는 앞의 제어점이 가진 세로 좌표다. 그 값이 1을 넘어서 오버슛이 나는데, 곡선 자체가 1.56까지 솟는 것은 아니다. 제어점은 곡선이 들르는 자리가 아니어서, 실제로 곡선이 닿는 가장 높은 값은 1.1에 조금 못 미친다.
반대로 y가 음수면 물건이 나가는 방향과 반대쪽으로 살짝 물러났다가 간다. 버튼이 눌리기 전에 잠깐 움츠리는 듯한 움직임이 이렇게 나온다. 진행률이 잠깐 0 아래로 내려간다는 뜻인데, 시간과 달리 진행률은 음수여도 그릴 그림이 하나로 정해진다. 0.1초에 어디 있는지만 답이 나오면 되고, 그 자리가 시작점 뒤여도 상관없다.
앞의 슬라이더에서 오버슛 프리셋을 눌러 보면 y만 1 위로 올라가고 x는 0과 1 사이를 안 벗어난다. 스펙이 건 제한이 슬라이더가 움직이는 범위로 그대로 드러나 있다.
그래서 0.4, 0, 0.2, 1은 어떤 움직임인가
여기까지 왔으니 처음의 그 값을 판에 올려놓을 수 있다.
두 점선 손잡이가 엇갈려 있는 것이 이 값의 성격이다. 아래쪽 손잡이는 오른쪽으로 길게 뻗어 출발을 붙잡고, 위쪽 손잡이는 왼쪽으로 길게 뻗어 도착을 붙잡는다. 곡선이 양쪽 끝에서 가로선에 붙어 나가고 들어오는 게 그 결과다.
숫자로 보면 이렇다. 0.3초짜리 이동이라 치고 시간을 따라가 보자.
- 시작하고 10%(0.03초)가 지났을 때 겨우 2.6% 갔다. 거의 제자리다.
- 시간이 절반(0.15초) 지났을 때 이미 77.6% 가 있다.
- 그리고 마지막 20%(0.06초) 동안 남은 2.5%를 간다.
앞은 뜸을 들이고, 가운데서 확 가고, 끝에서 아주 길게 미끄러져 멈춘다. 흔히 부드럽다고 말하는 움직임이 이 모양이다. 시간의 5분의 1을 남은 2.5%에 쓰기 때문에 멈추는 순간이 눈에 안 띈다.
핸드오프에서 이 네 숫자를 받았을 때 물어볼 것도 여기서 나온다. 출발이 느린 게 맞나, 도착이 느린 게 맞나, 그 둘이 얼마나 차이 나야 하나. 앞의 판에서 슬라이더를 밀어 보면 첫째와 둘째 숫자가 출발을, 셋째와 넷째가 도착을 쥐고 있다는 것이 손에 잡힌다.
정리: 네 숫자를 좌표 두 개로 읽기
네 숫자는 외울 값이 아니라 읽을 수 있는 자리다. 가운데 두 제어점을 어디에 놓았는지가 그 넷에 적혀 있다.
- 가운데 두 제어점은 곡선이 지나가는 곳이 아니라 나가고 들어오는 방향과 세기를 정한다.
- CSS로 넘어오면 가로가 시간이라 그래프가 위로 부풀어도 물건이 위로 뜨지 않고, 양 끝 두 점은 늘 같은 자리라 적어 줄 값이 네 개다.
- 시간을 나타내는 x만 갇혀 있는 것은 같은 순간에 진행률이 두 개일 수 없기 때문이다.
값을 어떻게 고를지는 모션 디자인 원칙: easing과 duration을 정하는 기준에서 다룬다.
다음에 핸드오프로 값을 받으면 네 숫자를 두 좌표로 끊어 읽고, 앞의 좌표가 출발을, 뒤의 좌표가 도착을 쥐고 있다고 보면 된다.
그 네 숫자가 뭘 가리키느냐고 누가 다시 물으면, 이제 제어점 두 개의 자리로 답할 수 있다.
이 글, 어떠셨어요?
이 글에 오류가 있나요?
사실이 틀렸거나 오탈자, 깨진 링크를 발견하셨다면 알려주세요. 확인하고 고치겠습니다.