베지어 곡선: 점 두 개가 곡선을 당긴다
개발자: “모달 곡선 값 뭘로 할까요?”
디자이너: “0.4, 0, 0.2, 1로 해주세요.”
개발자: “그 숫자 넷이 뭘 가리키는 거예요?”
디자이너는 답을 못 한다. 어딘가에서 복사해 온 값이라서 그렇다. 네 숫자가 무엇을 가리키는지 몰라도 화면은 잘 나오니, 누가 묻기 전까지는 모른다는 사실조차 드러나지 않는다.
그런데 디자이너는 같은 곡선을 이미 매일 만지고 있다. Figma나 Illustrator에서 펜툴로 점을 찍고 핸들을 끌 때 나오는 선이 베지어 곡선(Bézier curve)이다. 핸들 끝이 놓인 자리가 곧 CSS로 넘어온 네 숫자가 가리키는 자리다. 한쪽은 손으로 끌고 한쪽은 숫자로 받으니 서로 다른 물건처럼 보일 뿐이다.
cubic-bezier의 네 숫자는 곡선 위의 좌표가 아니라 곡선 옆에 놓인 점 두 개의 좌표다. 그 점을 쥐는 방식이 어디서 나왔는지, 점 네 개가 어떻게 곡선이 되는지, 왜 그 곡선의 가로축이 시간인지, 왜 가로 좌표만 0과 1 사이에 갇히는지를 차례로 본다.
곡선 옆의 점을 쥐는 방식은 차체 도면에서 나왔다
곡선이 지나갈 자리를 찍는 대신, 곡선에서 떨어진 곳에 점을 놓고 그 점을 옮긴다. 이렇게 거꾸로 가는 방식이 나온 자리는 공장이었다.
1950년대와 60년대의 자동차 회사는 사람이 손으로 그린 차체 곡선을 기계에 숫자로 넘길 방법이 없었다. 도면 위의 곡선에서 점을 잔뜩 찍은 다음 그 점들을 지나가는 곡선을 다시 맞추는 방식은 일찍 실패했다.Farin, G. (2002), A History of Curves and Surfaces in CAGD, Handbook of Computer Aided Geometric Design 1장. Early Developments 섹션에 Digitizing points off the blueprints and fitting curves using familiar techniques such as Lagrange interpolation failed early on이라고 적혀 있다. 2026년 7월에 저자 배포본 PDF로 원문을 확인했다.
1959년 Citroën은 박사학위를 갓 받은 수학자 Paul de Faget de Casteljau를 뽑아 손으로 그린 곡선을 숫자로 넘기는 문제를 맡겼다.같은 글 De Casteljau and Bézier 섹션. In 1959, the French car company Citroën hired a young mathematician… The mathematician was Paul de Faget de Casteljau, who had just finished his PhD. 그가 찾은 답을 Farin은 이렇게 적는다. 곡선을 직접 바꾸는 대신 제어 다각형을 바꾸면 곡선이 아주 직관적인 방식으로 따라온다.같은 섹션. The breakthrough insight was to use control polygons… Instead of defining a curve (or surface) through points on it, a control polygon utilizes points near it. Instead of changing the curve (surface) directly, one changes the control polygon, and the curve (surface) follows in a very intuitive way.
제어 다각형은 점 몇 개를 순서대로 이은 꺾은선이다. 펜툴을 쓸 때 화면에 잠깐 보이는 핸들 막대가 꺾은선의 일부고, CSS가 받는 네 숫자는 같은 꺾은선을 이루는 점 가운데 두 개의 좌표다. 디자이너가 손으로 하는 일과 개발자가 값으로 받는 것이 여기서 만난다.
곡선을 낸 사람은 de Casteljau인데 이름은 Bézier에 붙었다. Renault에서 설계 부서를 이끌던 Pierre Bézier는 Citroën에서도 비슷한 연구가 진행되고 있다는 사실을 알고 있었다. 그래도 자기 방식으로 풀어 1960년대 초에 같은 곡선에 이르렀고, 결과를 널리 발표했다. 그동안 Citroën은 de Casteljau가 낸 결과를 오랫동안 비밀에 부쳤다.같은 섹션. Bézier’s efforts were influenced by the knowledge of similar developments at Citroën, but he proceeded in an independent manner. / The result turned out to be identical to de Casteljau’s curves, only the mathematics involved was different. / Bézier’s work was widely published. / De Casteljau’s work was kept a secret by Citroën for a long time.
그럼 옆에 놓아둔 점이 어떻게 곡선을 만드는가.
선 위를 같은 비율로 세 번 걸으면 곡선이 나온다
점 네 개를 선으로 잇고 각 선에서 같은 비율 지점을 찍는다. 이것을 세 번 되풀이하면 점 하나가 남는데, 남은 점이 곡선 위의 점이다. 비율을 0에서 1까지 밀면 그 점이 지나간 자리가 곡선이 된다.
큐빅(cubic)은 세제곱, 곧 3차라는 뜻이다. 왜 하필 3차인지는 점을 세어 보면 알 수 있는데, 답은 아래를 다 따라간 뒤에 나온다.
먼저 두 점 사이의 30% 지점을 찍는 일부터 보자. 3에서 출발해 7로 가는 길에서 30% 지점은 3 + (7 - 3) × 0.3 = 4.2다. 시작값에 두 값의 차이 가운데 30%를 더한 것뿐이다. 이렇게 두 값 사이를 채워 넣는 계산을 보간(補間)이라고 한다. 기울 보에 사이 간이니, 사이를 메운다는 뜻이 이름에 그대로 들어 있다.
이제 점 네 개를 왼쪽 아래부터 차례로 P0, P1, P2, P3이라 부르자. 30% 지점 찍기를 세 번 되풀이하는데, 한 번 돌 때마다 점이 하나씩 줄어든다.
첫 번째. 네 점을 순서대로 이으면 선 세 개가 생기고, 선마다 30% 지점을 찍으면 점 세 개가 나온다.
두 번째. 방금 나온 점 세 개를 다시 순서대로 이으면 선 두 개가 생기고, 거기서 30% 지점을 찍으면 점 두 개가 나온다.
세 번째. 남은 점 두 개를 이으면 선 하나가 생기고, 거기서 30% 지점을 찍으면 점 하나가 나온다. 마지막에 남은 점 하나가 비율 0.3일 때 곡선이 지나는 자리다.
비율을 30%에 세워 두지 말고 0%부터 100%까지 천천히 밀면 남는 점도 따라 움직인다. 그 점이 지나가며 남긴 자국이 곡선이다. 아래 막대를 직접 밀어 보면 세 번 되풀이하는 과정이 한눈에 들어온다.
비율 0.30, 지금 점 (–, –)
밀어 보면 걸리는 데가 하나 있다.
디자이너: “가운데 점 두 개는 곡선에 닿지도 않는데 왜 있어요?”
개발자: “닿으라고 놓은 게 아니라서요.”
가운데 두 점은 곡선이 들르는 곳이 아니라 방향을 정해 주는 자리다. 곡선은 P0에서 나올 때 P1 쪽을 향해 뻗고, P3으로 들어갈 때 P2 쪽에서 들어간다. 방향만 정할 뿐 곡선 위에는 오지 않는다. 펜툴 핸들을 길게 빼면 선이 그 방향으로 더 멀리 끌려가는 것도 같은 이유다.
점이 네 개고 보간을 세 번 되풀이했으니 비율이 세 번 곱해진다. 큐빅이라는 이름이 그래서 붙었다. 계산식이 궁금하면 아래를 펴 보면 되고, 안 펴도 뒤 내용은 그대로 이어진다.
세 번 되풀이한 결과를 식 하나로 적으면
B(t) = (1-t)³P0 + 3(1-t)²t·P1 + 3(1-t)t²·P2 + t³P3
기호를 하나씩 풀면 이렇다.
- t는 걷는 비율이다. 0이면 출발선, 1이면 도착선, 0.3이면 위에서 찍은 30% 지점이다.
- (1-t)는 아직 안 걸은 비율, t는 이미 걸은 비율이다. 두 값을 더하면 언제나 1이다.
- P0부터 P3까지는 점 네 개의 자리이고, 각 점 앞에 붙은 값이 그 점이 결과에 내놓는 몫이다. 네 몫을 더하면 언제나 1이라 곡선은 점 네 개가 둘러싼 범위 안에 머문다.
- 3은 가운데 두 항에만 붙는다. 세 번 되풀이하는 동안 가운데 점은 세 갈래로 결과에 들어가고 양 끝 점은 한 갈래로만 들어가기 때문이다.
- 어느 항이든 (1-t)와 t의 지수를 더하면 3이다. 비율이 세 번 곱해진다는 뜻이고, 3차라는 이름의 근거가 여기다.
종이 위에서는 여기까지다. CSS로 넘어가면 같은 곡선의 두 축에 다른 이름이 붙는다.
CSS의 베지어에서 가로축은 위치가 아니라 시간이다
펜툴로 그리는 베지어가 종이 위의 모양이라면, CSS가 쓰는 베지어는 가로가 시간이고 세로가 진행률인 그래프다. 계산은 똑같고 두 축에 붙은 이름만 다르다.
가로축의 0부터 1까지는 애니메이션이 시작해서 끝날 때까지의 시간이고, 세로축의 0부터 1까지는 목적지까지 얼마나 갔느냐다. 0.3초짜리 이동이라면 가로 0.5는 0.15초가 지난 순간이고, 세로 0.5는 갈 길의 절반을 갔다는 뜻이다.
여기서 그래프를 화면으로 착각한다. 곡선이 위로 볼록하게 솟았다고 화면의 물건이 위로 뜨는 게 아니다. 솟았다는 것은 같은 시각에 이미 많이 갔다는 뜻일 뿐이고, 물건은 원래 가기로 한 방향으로만 간다.
모달이 화면 아래에서 올라오는 장면을 놓고 보면 어디서 헷갈리는지가 드러난다. 모달도 세로로 움직이고 그래프의 세로축도 세로다. 그런데 그래프의 세로는 화면의 위아래가 아니라 갈 길 중 얼마나 갔느냐다. 같은 모달을 옆으로 미끄러지게 바꿔도 그래프는 똑같이 생긴다.
그럼 왜 숫자가 네 개인가. 점은 네 개인데 CSS가 받는 값은 두 점의 좌표뿐이다. 시작점이 언제나 (0, 0)이고 끝점이 언제나 (1, 1)이기 때문이다. 0초에 0%에서 나와 주어진 시간을 다 쓰면 100%에 닿는다는 것은 어느 곡선에서도 바뀌지 않는다. 안 바뀌는 값이라 적을 필요가 없고, 남은 가운데 두 점의 좌표 네 개가 그대로 cubic-bezier(x1, y1, x2, y2)다.
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/에서 원문을 확인했다.
키워드를 쓰든 괄호에 숫자를 적든 그리는 것은 같은 곡선이다.
아래 슬라이더로 네 값을 직접 옮겨 보면 좌표와 곡선과 움직임이 한 화면에서 같이 바뀐다.
cubic-bezier(0.42, 0, 0.58, 1)
방금 민 슬라이더 네 개는 좌표이고, 앞의 위젯에서 민 막대는 선 위를 걷는 비율이었다.둘은 서로 다른 값이라, 비율을 0.5로 놓아도 가로 좌표가 0.5라는 보장이 없다. 곡선을 시각으로 읽으려면 지금 시각에 해당하는 비율을 거꾸로 찾은 다음 그 비율로 세로 좌표를 내야 한다.
가로축이 시간이라서 네 숫자에는 규칙이 하나 붙는다.
시간 좌표는 0과 1 사이에 갇히고 진행률 좌표는 넘어가도 된다
네 숫자 가운데 첫째와 셋째는 0과 1 사이를 벗어나면 값 자체가 무효인데, 둘째와 넷째는 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.4초에 지나온 자리를 0.3초에 또 지나게 되니 같은 시각의 진행률이 두 개가 되고, 그러면 그 순간에 무엇을 그려야 할지 정할 수가 없다.
시간이 한 방향으로만 간다는 것은 영상 재생 바에서도 마찬가지다. 재생 바의 손잡이는 왼쪽에서 오른쪽으로만 간다. 손잡이가 저절로 왼쪽으로 되돌아가는 재생은 없다. 이징 곡선의 가로축도 같은 줄이라, 그 위에서 뒤로 가는 구간이 생기면 브라우저가 그릴 그림을 하나로 고를 수 없다.
그래서 스펙은 되돌아가는 구간이 절대 안 생기는 범위를 잡아 x를 거기 묶어 뒀다. 0과 1 사이에 있기만 하면 어떤 값을 넣어도 안전하다.0과 1 사이를 잘게 나눠 x1과 x2의 조합 4만 쌍 남짓을 전부 훑어 봤더니 되돌아가는 구간이 한 번도 안 나왔다(2026년 7월, 직접 계산). 거꾸로 밖의 값이 전부 되돌아가는 것은 아니다. x1을 0 아래로 내리거나 x2를 1 위로 올리면 바로 나오지만, x1을 1 위로 올리는 정도로는 안 나오는 값도 있다. 스펙의 제한은 안 되는 값을 전부 골라낸 것이 아니라 언제나 되는 범위를 잡아 둔 것이다.
y는 사정이 다르다. y가 1을 넘으면 목적지를 지나쳤다가 되돌아오는 구간이 생긴다. 목적지를 지나쳤다 돌아오는 이 움직임을 모션에서 오버슛이라고 부른다. 서랍을 세게 밀면 끝까지 나갔다가 살짝 도로 들어오는데, 화면에서 같은 일을 일으키는 값이 1을 넘는 y다. 예를 들어 cubic-bezier(0.34, 1.56, 0.64, 1)은 둘째 숫자가 1.56이라 곡선이 목적지를 한 번 지나쳤다 돌아온다. 이 글이 예로 고른 값이다.둘째 숫자는 앞쪽 제어점의 세로 좌표다. 그 값이 1을 넘어서 오버슛이 나는데, 곡선 자체가 1.56까지 솟는 것은 아니다. 제어점은 곡선이 들르는 자리가 아니어서, 실제로 곡선이 닿는 가장 높은 값은 1.1에 조금 못 미친다.
반대로 y가 음수면 나가는 방향과 반대쪽으로 살짝 물러났다가 간다. 버튼이 눌리기 전에 잠깐 움츠리는 듯한 움직임이 이렇게 나온다. 진행률이 잠깐 0 아래로 내려간다는 뜻인데, 시간과 달리 진행률은 음수여도 그릴 그림이 하나로 정해진다. 0.1초에 어디 있는지만 답이 나오면 되고, 그 자리가 출발선 뒤여도 상관없다.
앞의 슬라이더에서 오버슛 프리셋을 눌러 보면 세로 슬라이더만 1 위로 올라가고 가로 슬라이더는 0과 1 사이를 안 벗어난다. 스펙이 건 제한이 슬라이더가 움직이는 범위로 그대로 드러나 있다.
정리: 네 숫자를 좌표 두 개로 읽기
네 숫자는 외울 값이 아니라 읽을 수 있는 자리다. 곡선 바깥에 찍힌 점 두 개의 위치이고, 곡선은 그 점을 지나가는 게 아니라 점이 가리킨 방향으로 나갔다가 들어온다.
- 곡선 옆의 점을 쥐는 방식은 도면에 그린 곡선을 기계에 넘길 방법이 없어서 나왔다.
- 같은 비율 지점 찍기를 세 번 되풀이하면 곡선이 나오고, 가운데 두 점은 곡선이 들르는 곳이 아니라 나가고 들어오는 방향이다.
- CSS로 넘어오면 가로가 시간이라, 그래프가 위로 부풀어도 물건이 위로 뜨지는 않는다.
- 시간 좌표만 갇혀 있는 것은 같은 순간에 진행률이 두 개일 수 없기 때문이다.
값을 어떻게 고를지는 모션 디자인 원칙: easing과 duration을 정하는 기준에서 다룬다.
다음에 핸드오프로 값을 받으면 네 숫자를 (x1, y1)과 (x2, y2) 두 좌표로 끊어 읽고, 두 점을 곡선 옆에 찍어 보면 된다. 0.4, 0, 0.2, 1이라면 (0.4, 0)과 (0.2, 1)에 점을 하나씩 놓았다는 뜻이고, 앞의 점이 나가는 방향을, 뒤의 점이 들어오는 방향을 정한다.
그 숫자 넷이 뭘 가리키느냐고 누가 다시 물으면, 이제 점 두 개의 자리로 답할 수 있다.
이 글, 어떠셨어요?
이 글에 오류가 있나요?
사실이 틀렸거나 오탈자, 깨진 링크를 발견하셨다면 알려주세요. 확인하고 고치겠습니다.