TypeScript 4.3의 override 키워드와 안전한 상속 구조
문제 상황
레거시 코드를 리팩토링하던 중 BaseService 클래스의 메서드명이 initialize에서 init으로 변경되었는데, 이를 상속받은 20여개의 서비스 클래스에서 오버라이드한 메서드들이 제대로 호출되지 않는 버그가 발생했다. 메서드명 변경 사실을 몰랐던 것이 원인이었다.
class BaseService {
init() { // initialize에서 변경됨
console.log('base init');
}
}
class UserService extends BaseService {
initialize() { // 오타인지 의도인지 알 수 없음
console.log('user init');
}
}
TypeScript 4.3의 override 키워드
5월에 릴리즈된 TypeScript 4.3에서 추가된 override 키워드가 이 문제를 해결해준다. --noImplicitOverride 플래그를 활성화하면 상속 메서드를 오버라이드할 때 명시적으로 키워드를 붙여야 한다.
class UserService extends BaseService {
override init() { // 부모 클래스에 실제로 존재하는지 검증
console.log('user init');
}
override initialize() { // Error: 부모에 없는 메서드
console.log('user init');
}
}
적용 결과
tsconfig.json에 옵션을 추가하고 기존 코드에 override 키워드를 붙이는 작업을 진행했다. 예상대로 여러 곳에서 오버라이드하지 못한 메서드들이 발견되었고, 런타임에서야 발견되었을 버그들을 사전에 제거할 수 있었다.
{
"compilerOptions": {
"noImplicitOverride": true
}
}
클래스 기반 아키텍처를 사용하는 프로젝트라면 충분히 도입 가치가 있는 기능이다. 다만 기존 코드베이스가 크다면 마이그레이션 비용을 고려해야 한다.