본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Refactoring; 리팩터링
외부에서 보이는 동작(결과)은 바꾸지 않고 내부 구조를 개선해 가독성을 높이고 유지보수를 쉽게 하는 작업
  • 리팩토링을 통해서 프로그램의 이해가 쉬워진다.
  • 리팩토링은 결함을 찾는 데 도움을 준다.
  • 리팩토링의 대상은 읽기 어려운 코드, 중복된 로직의 코드, 복잡한 조건문이 있는 코드 등이 대표적인 것이다.

리팩토링은 마틴 파울러(Martin Fowler)가 1999년 『Refactoring』에서 체계화했다. 기능 추가와 구조 개선을 한꺼번에 하지 않고, 작은 변경 → 테스트 → 작은 변경을 반복해 동작이 그대로임을 확인하면서 구조만 바꾸는 것이 핵심이다. 그래서 자동화된 단위 테스트와 회귀 테스트가 전제 조건이 된다. 쌓인 기술 부채를 갚는 수단이며, 테스트 주도 개발에서는 "실패하는 테스트 작성 → 통과 → 리팩토링" 주기의 마지막 단계다.

리팩토링의 대상은 코드에만 있지 않다. 데이터베이스 스키마에도 같은 개념을 적용한 것이 데이터베이스 리팩토링이다.

  • 소프트웨어 설계 개선 : 시간이 지나며 무너진 구조를 되살린다.
  • 이해하기 쉬운 코드 : 다른 사람(과 미래의 자신)이 읽기 쉽게 만든다.
  • 결함 발견 : 구조를 정리하다 보면 숨은 버그가 드러난다.
  • 개발 속도 유지 : 구조가 좋으면 기능 추가 비용이 늘지 않는다.

코드 스멜(code smell)은 리팩토링이 필요하다는 신호가 되는 코드의 징후다.

코드 스멜 징후 대표 리팩토링 기법
중복 코드 같은 구조의 코드가 여러 곳에 있음 메서드 추출(Extract Method), 상위 클래스로 올리기
긴 메서드 한 메서드가 지나치게 많은 일을 함 메서드 추출, 조건문 분해
큰 클래스 한 클래스에 필드·메서드가 과도함 클래스 추출(Extract Class)
긴 매개변수 목록 매개변수가 너무 많음 매개변수 객체 도입(Introduce Parameter Object)
산탄총 수술(Shotgun Surgery) 하나를 바꾸려면 여러 클래스를 고쳐야 함 메서드·필드 이동(Move Method/Field)
기능 편애(Feature Envy) 자기 데이터보다 다른 클래스 데이터를 더 많이 씀 메서드 이동
스위치 문 같은 조건 분기가 반복됨 조건문을 다형성으로 바꾸기
기본형 집착 의미 있는 값을 int·string으로만 다룸 값 객체로 바꾸기

데이터베이스 리팩토링

편집 원본 편집
Database Refactoring
데이터베이스 스키마에 대한 작은 변경으로, 동작 의미(behavioral semantics)와 정보 의미(informational semantics)를 모두 유지하면서 설계를 개선하는 것

스콧 앰블러(Scott W. Ambler)와 프라모드 사달라지(Pramod J. Sadalage)가 2006년 『Refactoring Databases: Evolutionary Database Design』에서 정리했다. 코드 리팩토링이 동작만 지키면 되는 데 비해, 데이터베이스 리팩토링은 이미 저장된 데이터의 의미까지 그대로 지켜야 한다. 또 하나의 데이터베이스를 여러 애플리케이션, 배치, 보고서, 외부 연계가 함께 쓰기 때문에 스키마를 한 번에 바꾸면 모르는 곳에서 장애가 난다. 그래서 옛 스키마와 새 스키마를 일정 기간 함께 운영하는 전환 기간(transition period)을 두는 것이 코드 리팩토링과 가장 크게 다르다.

DB 스멜(database smell)은 스키마에 리팩토링이 필요하다는 신호다.

DB 스멜 설명 대응 리팩토링 예
다목적 컬럼(Multipurpose column) 한 컬럼을 상황에 따라 다른 뜻으로 씀. 예: 고객이면 생년월일, 법인이면 설립일 컬럼 분리(Split Column)
다목적 테이블(Multipurpose table) 한 테이블에 성격이 다른 엔터티를 함께 저장. 예: 개인 고객과 법인 고객 테이블 분리(Split Table)
중복 데이터(Redundant data) 같은 정보를 여러 곳에 저장해 불일치가 생김 정규화, 컬럼 이동, 조회 테이블 추가
컬럼이 너무 많은 테이블 응집도가 낮아 여러 엔터티가 섞임 테이블 분리, 컬럼 이동
행이 너무 많은 테이블 성능 문제 수평 분할, 읽기 전용 테이블 추가, 인덱스 도입
스마트 컬럼(Smart column) 값의 위치마다 뜻을 담음. 예: 고객번호 앞 4자리가 지점 코드 컬럼 분리
변경에 대한 두려움(Fear of change) 영향 범위를 몰라 스키마를 못 바꿈. 가장 심각한 스멜 테스트 체계와 캡슐화(뷰·프로시저)부터 마련

DB 리팩토링 유형

편집 원본 편집
유형 목적 대표 리팩토링
구조(Structural) 테이블·컬럼·뷰의 구조 개선 컬럼 이름 변경, 컬럼 분리·병합, 테이블 분리·병합, 컬럼 이동, 대리 키 도입
데이터 품질(Data Quality) 데이터 일관성과 품질 향상 조회 테이블 추가, 표준 코드 적용, 컬럼 제약조건·기본값 도입, NOT NULL 지정
참조 무결성(Referential Integrity) 참조 관계를 보장 외래 키 제약 추가, 연쇄 삭제 도입, 이력용 트리거 도입
아키텍처(Architectural) 외부 프로그램과 데이터베이스의 상호작용 개선 테이블을 뷰로 캡슐화, 계산 메서드 도입, 읽기 전용 테이블 추가, 인덱스 도입
메서드(Method) 저장 프로시저·함수·트리거 코드 개선 메서드 이름 변경, 매개변수 추가, 조건식 통합(코드 리팩토링과 동일)

테이블·컬럼 삽입, 뷰 추가처럼 스키마의 의미를 바꾸는 변경은 리팩토링이 아니라 변환(transformation)으로 구분한다.

DB 리팩토링 절차

편집 원본 편집
  1. 적절성 확인 : 정말 필요한지, 지금 할 만한지, 다른 팀 데이터베이스에 영향은 없는지 판단한다.
  2. 리팩토링 선택 : 스멜에 맞는 리팩토링 하나를 고른다. 한 번에 하나씩, 작게 한다.
  3. 원래 스키마 폐기 예정 표시(deprecate) : 바뀔 컬럼·테이블에 폐기 예정일을 정하고 공지한다.
  4. 테스트 작성 : 변경 전·중·후에 스키마, 데이터 이관 결과, 접근 프로그램을 검증하는 테스트를 만든다.
  5. 스키마 변경 : 새 구조를 추가하고, 전환 기간 동안 옛 구조와 새 구조를 동기화할 스캐폴딩 코드(대개 트리거)를 둔다.
  6. 원천 데이터 이관 : 옛 구조의 데이터를 새 구조로 옮기고 정제한다.
  7. 접근 프로그램 수정 : 새 구조를 쓰도록 애플리케이션, 배치, 보고서를 고친다.
  8. 회귀 테스트 : 전체 테스트를 돌려 동작과 데이터 의미가 유지됐는지 확인한다.
  9. 버전 관리 : 스키마 변경 스크립트, 이관 스크립트, 테스트를 형상 관리에 넣는다.
  10. 공지 : 변경 내용과 전환 기간을 데이터베이스를 쓰는 모든 팀에 알린다.
  11. 전환 기간 종료 : 모든 접근 프로그램이 옮겨 오면 옛 컬럼·테이블과 스캐폴딩 코드를 제거한다.

예를 들어 고객.이름을 성과 이름으로 나누는 컬럼 분리라면, 새 컬럼 두 개를 추가하고 기존 데이터를 나눠 옮긴 뒤 트리거로 어느 쪽에 써도 양쪽이 맞춰지게 한다. 전환 기간이 끝나면 옛 컬럼과 트리거를 지운다.

코드 리팩토링과 비교

편집 원본 편집
구분 코드 리팩토링 데이터베이스 리팩토링
유지할 것 동작 의미 동작 의미 + 정보 의미(저장된 데이터)
영향 범위 대개 한 애플리케이션 데이터베이스를 공유하는 모든 시스템
배포 새 버전으로 교체 옛 스키마와 새 스키마를 병행하는 전환 기간 필요
데이터 처리 없음 데이터 이관·정제 필요
되돌리기 이전 코드로 되돌리면 됨 이관된 데이터까지 되돌려야 해서 어려움
도구 IDE 자동 리팩토링 스키마 마이그레이션 도구, 데이터베이스 단위 테스트
  • Martin Fowler, 『Refactoring: Improving the Design of Existing Code』, Addison-Wesley, 1999(2판 2018).
  • Scott W. Ambler, Pramod J. Sadalage, 『Refactoring Databases: Evolutionary Database Design』, Addison-Wesley, 2006.