📖 구조 노트 목차 Chapter 22 읽는 중

22. 리팩터링은 왜 가능한가

구조 노트 Chapter 22 2026. 07. 18.

예전에 이미 동작하고 있던 서비스 앞단에 프록시를 하나 끼워 넣은 적이 있다. 원본의 소스 코드는 볼 수 있었지만, 그것을 그대로 옮겨 적지는 않았다. 대신 원본이 어떤 요청에 어떤 응답을 내놓는지, 어떤 순서로 메시지를 주고받는지를 기준으로 새 서버를 다시 지었다. 언어도 달랐고 내부 구조도 원본과 전혀 다른 발상으로 짜였다. 원본 코드는 참고 자료였을 뿐, 새 서버가 지켜야 했던 것은 원본의 구현이 아니라 원본이 겉으로 내보이던 행동이었다.

프록시를 원본 자리에 끼워 넣던 날, 클라이언트 입장에서는 아무 일도 달라지지 않았다. 연결은 그대로 유지됐고, 요청은 평소와 같이 처리됐다. 확인할 수 있는 것은 여전히 같은 요청에 여전히 같은 응답이 돌아온다는 사실뿐이었고, 그것으로 충분했다.

이 경험이 이상한 이유는 새 서버의 내부가 원본과 닮은 구석이 거의 없었다는 데 있다. 자료구조도 달랐고, 동시성을 처리하는 방식도 달랐고, 에러를 다루는 코드는 아예 다른 철학으로 짜여 있었다. 두 서버를 나란히 열어 놓고 코드를 비교했다면 같은 서비스라고 우길 근거를 찾기 어려웠을 것이다. 그런데도 이 둘은 클라이언트 앞에서 같은 서비스였다. 이 판정은 코드를 열어 본 사람이 내린 것이 아니라, 코드를 한 번도 보지 못한 클라이언트가 내린 것이다. 클라이언트가 볼 수 있는 것은 오직 오가는 메시지, 즉 겉으로 드러난 행동뿐이었고, 그 판정 기준만으로 두 서버는 같은 것으로 취급되었다.

같은 원리는 훨씬 작은 규모에서도 매일 일어난다. 어떤 함수의 내부 로직을 통째로 새로 짜고도 기존 테스트가 그대로 통과할 때가 있다. 이때 벌어지는 일도 사실 프록시를 끼워 넣었을 때와 다르지 않다. 다만 규모가 작고, 새로 지은 사람과 원래 지은 사람이 같은 사람일 뿐이다. 리팩터링이 겁나지 않는 이유는 내부가 안 바뀌어서가 아니다. 내부는 완전히 바뀐다. 다만 우리가 지키기로 약속한 것은 처음부터 내부가 아니라 바깥에서 관찰되는 결과였고, 그 약속만 지켜지면 내부의 어떤 변화도 허용된다.

14장에서 조직도와 선수과목 체계도를 나란히 놓고, 이름을 다 지워도 화살표의 그물만 같으면 두 그림을 같다고 부를 수 있다는 이야기를 했다. 원본 서버와 프록시 서버도 마찬가지다. 내부의 이름도, 자료구조도, 심지어 짜여진 언어까지 다 지우고 나면 남는 것은 입력과 출력을 잇는 화살표들뿐이다. 그 화살표의 그물이 겹치는 한, 두 서버는 재질이 다른 같은 그림이다. 우리가 그날 프록시를 끼워 넣으며 실제로 지키고 있던 것은 코드 한 줄이 아니라 이 그물이었다.

그렇다면 다음 질문이 남는다. 이 그물 안에서도 어떤 화살표는 절대 지워지면 안 되고, 어떤 화살표는 지워져도 상관없다는 차이가 있을 것이다. 지켜야 할 것과 지키지 않아도 될 것을 가르는 기준은 무엇일까.