회귀
고친 사람 github-actions[bot]
회귀는 분야마다 다른 일을 가리키는 말입니다. 소프트웨어 개발에서는 코드를 바꾼 뒤에 전부터 되던 기능이 안 되는 일을 말합니다. 통계와 머신러닝에서는 입력을 보고 집값 같은 숫자를 맞히는 일을 말합니다. 두 뜻은 이름만 같습니다.
쉽고 빠른 이해
무엇을 가리키나 — 개발 쪽 회귀는 고친 뒤에 멀쩡하던 것이 깨지는 일입니다. 배송비 계산을 손봤더니 3만 원 주문의 무료 배송이 사라졌다면 회귀가 난 것입니다. 머신러닝 쪽 회귀는 방 크기를 보고 집값을 숫자로 맞히는 일입니다.
왜 갈라 알아야 하나 — 같은 낱말이 개발 회의와 데이터 회의에서 전혀 다른 뜻으로 오갑니다. 「회귀가 났다」는 결함 이야기입니다. 「회귀로 푼다」는 예측 방법 이야기입니다. 뜻을 잘못 고르면 대화가 엇갈립니다.
어떻게 가르나
- 「회귀가 났다 · 회귀를 막는다」처럼 일어난 일로 쓰이면 개발 쪽입니다
- 「회귀 문제 · 회귀 모델」처럼 문제나 방법의 이름으로 쓰이면 머신러닝 쪽입니다
- 「로지스틱 회귀」는 이름과 달리 스팸/정상처럼 미리 정해 둔 갈래 가운데 하나를 고르는 일에 씁니다
대가 — 개발 쪽 회귀를 막으려면 옛 테스트를 코드를 바꿀 때마다 다시 돌려야 합니다. 머신러닝 쪽 회귀는 답이 숫자라서 맞았나 틀렸나가 아니라 얼마나 벗어났나로 잽니다.
상세
이 절은 먼저 두 뜻을 표 하나로 가릅니다. 그다음 개발 쪽 뜻은 배송비 함수 하나로, 머신러닝 쪽 뜻은 집값 예측 하나로 따라갑니다. 마지막에 두 뜻이 한 문장에 겹치는 경우를 봅니다.
회귀가 가리키는 두 가지
| 맥락 | 회귀가 뜻하는 것 | 함께 나오는 말 |
|---|---|---|
| 소프트웨어 개발 | 코드를 바꾼 뒤에 전에 되던 동작이 안 되는 결함 | 회귀 테스트 · 성능 회귀 |
| 통계 · 머신러닝 | 입력으로 연속된 숫자 하나를 맞히는 문제와 그 방법 | 회귀 모델 · 선형 회귀 |
두 뜻 모두 영어 regression 을 옮긴 말입니다. 이 영어 낱말은 「뒤로 물러남」이라는 뜻입니다. 개발 쪽은 이 뜻을 거의 손대지 않고 씁니다. 소프트웨어가 되던 상태에서 뒤로 물러났다는 것입니다.
통계 쪽 이름은 평균으로의 회귀라는 현상에서 왔습니다. 유난히 큰 값 다음에는 평균에 더 가까운 값이 나오기 쉽다는 관찰입니다. 키가 아주 큰 부모의 자식은 대개 부모보다 평균에 가까운 키를 갖습니다. 값이 평균 쪽으로 물러난다는 뜻에서 회귀라는 이름이 붙었습니다.
이 현상을 재려고 부모 키를 넣으면 자식 키를 내는 직선을 긋는 계산법이 쓰였습니다. 이 계산법도 회귀라고 불렸습니다. 그 뒤 이 이름이 입력으로 숫자를 맞히는 방법 전체로 넓어졌습니다. 지금 머신러닝에서 회귀라고 하면 평균 쪽으로 물러나는 현상과 상관없이 숫자를 맞히는 일을 뜻합니다.
문장에서 회귀가 어떻게 쓰였는지 보면 대개 갈립니다. 「회귀가 났다」·「회귀를 냈다」처럼 일어난 일로 쓰이면 개발 쪽입니다. 「회귀 문제」·「회귀 모델」처럼 문제나 방법의 이름 앞에 붙으면 머신러닝 쪽입니다.
소프트웨어의 회귀
개발에서 회귀는 결함의 한 종류입니다. 버그 가운데 「전에는 됐다」는 증거가 있는 것을 따로 회귀라고 합니다. 새 기능이 처음부터 틀렸다면 그것은 그냥 버그입니다.
배송비를 계산하는 함수로 보겠습니다. 규칙은 「3만 원 이상이면 배송비가 0원」입니다. 처음 짠 fee_old 는 이 규칙대로 잘 돌았습니다. 누군가 코드를 정리하다가 부등호를 하나 바꿔 fee_new 를 만들었습니다.
def fee_old(total):
return 0 if total >= 30000 else 3000
def fee_new(total):
return 0 if total > 30000 else 3000
fee_old(30000) # 0
fee_new(30000) # 3000 ← 회귀
fee_new(50000) # 0
바꾼 함수도 5만 원 주문에는 여전히 0원을 냅니다. 딱 3만 원인 주문에서만 3000원을 받습니다. 고친 사람이 5만 원 주문으로만 확인했다면 이 회귀를 못 보고 넘어갑니다.
회귀는 고친 곳과 깨진 곳이 다를 때가 많습니다. 배송비 함수를 장바구니 화면과 주문서 화면이 함께 부른다고 해 봅시다. 주문서 화면만 보고 함수를 고친 사람은 장바구니 화면이 깨진 것을 못 봅니다.
회귀를 막는 회귀 테스트
회귀 테스트는 한 번 통과시킨 테스트를 버리지 않고 모아 두는 일입니다. 코드를 바꿀 때마다 모아 둔 테스트를 다시 돌립니다. 위 예라면 「3만 원 주문은 0원」을 확인하는 테스트 한 줄이 이 회귀를 바로 잡습니다.
이 일은 대개 사람 대신 서버가 맡습니다. 커밋은 코드 변경 한 묶음을 저장소에 기록한 것입니다. 개발자는 자기 커밋을 팀이 함께 쓰는 코드에 합쳐 넣습니다.
지속적 통합은 커밋을 올릴 때마다 서버가 빌드와 테스트를 자동으로 돌리는 방식입니다. 테스트를 통과한 커밋만 합치기로 정해 두면 회귀를 낸 커밋은 합쳐지기 전에 걸러집니다.
회귀를 낸 커밋 찾기
회귀에는 「되던 버전」이 있습니다. 그래서 되던 버전과 안 되는 버전 사이로 범위가 정해집니다. 그 사이 커밋 가운데 하나가 회귀를 냈습니다.
범위의 가운데 커밋을 골라 회귀가 난 기능을 돌려 봅니다. 기능이 되면 회귀는 그보다 뒤에서 났습니다. 안 되면 그 커밋이나 그보다 앞에서 났습니다. 어느 쪽이든 범위가 반으로 줄어듭니다.
이 확인을 되풀이해 커밋 하나를 짚는 방법이 이분 탐색 디버깅입니다. 커밋이 천 개여도 열 번 남짓 확인하면 하나로 좁혀집니다. Git 에는 이 일을 돕는 git bisect 명령이 있습니다.
flowchart TD
A["되던 버전과 안 되는 버전 사이의 커밋들"] --> B["가운데 커밋을 돌려 본다"]
B -->|기능이 된다| C["뒤쪽 반만 남긴다"]
B -->|기능이 안 된다| D["앞쪽 반만 남긴다"]
C --> E{"커밋이 하나 남았나"}
D --> E
E -->|아니다| B
E -->|그렇다| F["그 커밋이 회귀를 냈다"]
성능 회귀
회귀는 기능만의 일이 아닙니다. 답은 맞아도 전보다 느려지면 성능 회귀라고 합니다. 배송비 함수가 같은 값을 내면서 한 번 부를 때 걸리는 시간만 열 배로 늘었다면 성능 회귀입니다.
테스트가 결과 값만 확인하면 성능 회귀는 통과한 채로 배포됩니다. 그래서 바꾸기 전에 재 둔 응답 시간과 견줘야 드러납니다.
바깥에 내놓은 동작이 바뀔 때
라이브러리는 다른 프로그램이 가져다 쓰는 코드 묶음입니다. 날짜를 "2026-10-16" 같은 문자열로 돌려주던 라이브러리 함수가 있습니다. 새 버전에서 이 함수가 숫자를 돌려주게 바뀌면 그 라이브러리를 쓰던 서비스는 버전을 올리는 순간 깨집니다. 만든 쪽은 버그를 고쳤다고 여겨도 쓰는 쪽에서는 되던 것이 안 됩니다.
쓰는 쪽에서 보면 이것도 회귀입니다. 새 버전이 옛 버전을 쓰던 코드를 깨지 않는 성질을 하위 호환이라고 합니다. 하위 호환은 이런 회귀를 내지 않겠다는 약속입니다.
통계와 머신러닝의 회귀
이 소절부터는 다른 뜻입니다. 집값을 맞히는 예 하나로 회귀 문제가 무엇인지와 가장 단순한 풀이를 봅니다.
머신러닝은 정답이 붙은 예시 데이터에서 규칙을 찾아 새 입력의 답을 내는 방법입니다. 회귀는 그 답이 연속된 숫자인 문제입니다. 방 크기를 받아 집값을 맞히는 것이 회귀입니다. 내일 서버에 들어올 요청 수를 맞히는 것도 회귀입니다.
답을 미리 정해 둔 갈래 가운데서 고르면 분류입니다. 갈래는 「스팸 · 정상」처럼 나올 수 있는 답을 미리 적어 둔 목록입니다. 메일이 스팸인지 아닌지, 회원이 떠날지 남을지를 고르는 것이 분류입니다.
| 분류 | 회귀 | |
|---|---|---|
| 답의 모양 | 정해 둔 갈래 가운데 하나 | 연속된 숫자 |
| 예 | 스팸인가 아닌가 | 집값 · 내일 요청 수 |
| 틀린 정도를 재는 법 | 맞았나 틀렸나 | 얼마나 벗어났나 |
두 문제를 다룰 때 가장 크게 달라지는 것은 틀린 정도를 재는 법입니다. 집값을 1원까지 맞히는 일은 없습니다. 그래서 회귀에서는 「맞았다」 대신 「얼마나 가깝나」를 따집니다.
회귀를 푸는 모델은 입력을 받아 숫자를 내는 함수입니다. 이 함수 안에는 아직 정하지 않은 숫자가 몇 개 들어 있습니다. 그 숫자는 정답이 붙은 예시에 맞게 정합니다. 다음 소절의 a 와 b 가 그 숫자입니다.
선형 회귀
선형 회귀는 회귀를 푸는 가장 단순한 방법입니다. 입력과 답 사이에 직선 하나를 긋습니다. 방 크기가 x 평이면 집값을 a × x + b 로 맞힙니다.
예시 집들에 가장 잘 맞는 a 와 b 를 찾는 과정을 훈련이라고 합니다. 아래는 훈련이 끝나 a 와 b 를 얻은 뒤의 모습입니다. 값의 단위는 만 원입니다.
a, b = 1000, 5000 # 훈련으로 얻은 값
def price(x): # x 는 방 크기(평)
return a * x + b
price(20) # 25000
price(30) # 35000
30평 집이 38000, 곧 3억 8천만 원에 팔렸다고 합시다. 모델은 3000, 곧 3천만 원 낮게 맞혔습니다. 이렇게 실제 값과 맞힌 값의 차이를 잔차라고 부릅니다.
훈련은 모든 예시 집의 잔차를 제곱해 더한 값이 가장 작아지는 a 와 b 를 고릅니다. 이 방법이 최소 제곱법입니다. 제곱을 하면 낮게 맞힌 차이와 높게 맞힌 차이가 서로 지워지지 않습니다. 크게 벗어난 예시는 더 무겁게 셈에 들어갑니다.
회귀는 문제의 이름
회귀는 문제의 이름이지 한 가지 방법의 이름이 아닙니다. 선형 회귀는 그 문제를 푸는 방법 가운데 하나입니다. 데이터를 질문 여러 개로 갈라 답을 내는 결정 트리도 분류와 회귀를 둘 다 풉니다. 신경망도 답을 숫자로 내게 만들면 회귀를 풉니다.
이름이 거꾸로 붙은 경우도 있습니다. 로지스틱 회귀는 이름에 회귀가 들어 있지만 주로 분류에 씁니다. 이 모델은 0과 1 사이의 숫자를 냅니다. 그 숫자를 어느 갈래에 속할 확률로 읽습니다. 확률이 정해 둔 기준을 넘으면 한 갈래로, 못 넘으면 다른 갈래로 고릅니다.
두 뜻이 한 문장에 겹칠 때
머신러닝 팀에서는 두 뜻이 같이 나옵니다. 집값 회귀 모델을 새로 훈련했습니다. 그런데 옛 버전보다 더 크게 틀린다고 합시다. 이것도 회귀라고 부릅니다.
앞의 회귀는 문제의 종류입니다. 뒤의 회귀는 「전보다 나빠졌다」는 개발 쪽 뜻입니다.
그래서 모델을 바꿀 때도 옛 버전과 견주는 시험을 둡니다. 훈련에 쓰지 않고 따로 떼어 둔 평가용 데이터를 테스트 세트라고 부릅니다. 새 모델이 테스트 세트에서 옛 모델보다 크게 벗어나면 배포를 멈춥니다. 소프트웨어의 회귀 테스트와 같은 생각입니다.
관련 항목
소프트웨어 회귀를 찾고 막는 수단
회귀 테스트 · 이분 탐색 디버깅 · git bisect · 지속적 통합 · 단위 테스트 · 테스트 스위트 · 테스트 커버리지 · 롤백
소프트웨어 회귀의 하위 종류
성능 회귀 · 기능 회귀 · 시각적 회귀
소프트웨어 회귀를 막으려고 지키는 호환성 약속
하위 호환 · 하위 비호환 변경 · 브레이킹 체인지 · 시맨틱 버저닝 · 라이브러리
회귀를 낸 변경을 추적하고 되돌리는 작업
커밋 · 커밋 메시지 · 체리픽 · 핫픽스 · 장애 사후 분석 · 버그
통계·머신러닝 회귀를 푸는 모델
선형 회귀 · 다항 회귀 · 결정 트리 · 회귀 트리 · 신경망 · 최근접 이웃
회귀 모델을 맞추고 평가하는 기준
잔차 · 최소 제곱법 · 평균 제곱 오차 · 평균 절대 오차 · 결정 계수 · 손실 함수 · 과적합 · 테스트 세트
회귀와 나란히 서는 머신러닝 문제
분류 · 군집화 · 이상 탐지 · 지도학습 · 머신러닝 · 모델 · 훈련
이름이나 모양 때문에 회귀와 헷갈리는 이웃 개념
로지스틱 회귀 · 평균으로의 회귀 · 보간 · 외삽 · 곡선 맞춤 · 상관관계
다른 이름: regression · 리그레션