💡1.5 하위 호환성과 상위 호환성
JS를 지탱하는 기본 원칙은 하위 호환성 보장이다. (상위 호환성 개념과 혼동하기 쉽다.)
하위 호환성
단 한 번이라도 유효한 JS 문법이라고 인정되면 명세서가 변겨오디더라도 그 유효성이 깨지지 않는다는 의미이다. → 1995년에 작성한 코드가 시간이 흘러도 무조건 작동한다는 걸 보장받는다.
JS가 하위 호환성을 보장하므로 개발자는 브라우저 버전이 업데이트 되더라도 코드가 깨지지 않을 거라는 자신감을 가지고 작업할 수 있다.
하위 호환성을 '보장'하며 언어를 유지 보수하는 것은 매우 어렵다. IT 분야에서 이 정도 하위 호환성을 지키면서 무언가를 유지보수 해 온 사례는 거의 없다. 하위 호환성이라는 원칙을 고수하는 데 드는 비용도 매우 크다. JS 명세서에 한 번이라도 들어간 내용을 삭제하면 기존 프로그램이 작동하지 않기 때문에 절대 제거 하면 안 된다.
예외
TC39에서 하위 호환성을 깨는 결정을 하기도 한다. 이 때, 브라우저로 수집한 데이터를 이용해 결정에 따른 부수 효과가 어느 정도일지 추정하고, 명세서 변경에 따른 부정적인 부수 효과가 개선에 따른 이점에 비해 작으면 명세를 변경한다.
매우 드물게 일어나며, 사용자가 눈치채지 못할 부분에만 영향을 준다.
상위 호환성
JS가 상위 호환성을 준수하는 언어라면, 새로운 명세서에 추가된 문법으로 코드를 작성했을 때 이전 명세서를 준수하는 구형 JS 엔진에서 문제가 발생하지 않아야 한다. JS는 상위 호환성을 보장하지 않는다.
HTML, CSS는 상위 호환성을 보장하며 하위 호환성을 보장하지 않는다. → 1995년에 작성된 코드가 오늘 날에 작동하지 않을 수 있다.
하지만, 2010년에 만들어진 브라우저에서 2019년에 추가된 기능을 사용할 때 웹 페이지가 망가지지는 않는다. 브라우저는 인식이 불가능한 HTML/CSS는 건너뛰고, 인식 가능한 HTML/CSS는 명세서에 따라 처리하기 때문이다.
프로그래밍 언어를 설계할 때 상위 호환성을 보장하도록 하며 설계한다는 건 비현실적이다. 마크업(HTML), 스타일링(CSS)은 본절상 선언적이므로 인식되지 않는 선언은 인식 가능한 선언에 최소한의 영향을 미치면서 건너뛰는 게 훨씬 쉽다.
하지만, 프로그래밍 언어를 처리하는 엔진이 이해할 수 없는 구문이나 표현식을 선택적으로 건너뛰면 프로그램에 문제가 생긴다. → JS는 상위 호환성을 보장하지 않고, 보장할 수도 없다.
개발자는 JS가 하위 호환성을 보장하며 이에 따르는 이점, 제약, 어려움을 알고 있어야 한다.
☄️ 1.5.1 간극을 줄이기 위한 노력
신규 문법을 구 버전 엔진에서 실행하면 프로그램은 컴파일과 실행에 실패하고, 구문 오류가 발생한다. 명세서에 새롭게 추가되었지만 구 엔진과 호환되지 않는 문법은 트랜스파일을 통해 호환성 문제를 해결할 수 있다.
✓ 트랜스파일
JS 커뮤니티에서 만든 용어로, 한 형태에서 다른 형태로 소스 코드를 변환해주는 것을 의미. 변환 후 산출물은 코드이다. 상위 호환성으로 인해 발생하는 문제 대부분은 트랜스파일러를 사용하면 해결된다. 트랜스 파일러는 새로운 JS 문법을 오래된 문법으로 바꿔주며 주로 바벨(Babel)을 사용한다.
트랜스파일러 작동 예시
let으로 정의한 변수는 변수의 유효 범위가 블록 수준으로 한정되기 때문에 두 변수를 서로 간섭받지 않는다. var로 선언한 변수는 유효 범위가 블록 수준이 아니므로 이를 보완하기 위해 트랜스파일 결과에 두 개의 별도 변수가 새로 생긴 것이다.
그냥 옛날 문법 쓰면 되지 않나?
최신 JS를 쓰는 것이 코드가 깔끔해지고 의도하는 바를 효과적으로 전달할 수 있어 강하게 권유한다. 개발자는 새로운 문법을 활용해 클린한 코드를 짜는데 집중해야 한다. 상위 호환성과 관련된 문제는 도구에 맡기자.
☄️ 1.5.2 간극을 메우기 위한 방법 찾기
상위 호환성 문제가 아직 지원하지 않는 API 메서드(새로운 문법X, 근래에 추가) 때문에 발생했다면, 메서드 정의를 추가해 이미 이 메서드가 오래된 환경에도 있었던 것처럼 해주는 방법이 가장 일반적이다. 이런 패턴을 폴리필(polyfill, 심shim) 이라고 한다.
폴리필 패턴 예시
ES2019의 프로미스 프로토타입에 추가된 finally() 메서드를 사용한다. ES2019를 지원하지 않는 환경에서 실행하면 오류가 발생한다. finally()를 사용하기 위해 다음과 같은 폴리필이 필요하다.
프로덕션 환경에서는 ES-Shim과 같은 공신력이 있는 폴리필을 사용하자.
JS 엔진에 finally 메서드가 구현되어 있다면 if 문에서 막혀 폴리필이 작동하지 않는다. 새로운 실행 환경에서는 if 문을 뛰어넘고, 오래된 실행 환경에서는 새롭게 정의된 폴리필이 작동한다.
트랜스파일러(바벨)은 개발자가 작성한 코드 중 폴리필이 필요한 코드를 찾아 자동으로 폴리필을 추가한다. 개발자가 명시적으로 폴리필을 추가해야 할 때는 예시와 유사하게 작성하면 된다.
코드를 작성할 때는 항상 구현 의도를 효과적으로 전달해야 한다. 그에 걸맞은 적절한 문법을 사용하면 된다.
가장 최신의 안정된 JS를 사용하여 우리가 원하는 바를 달성하자. 실행환경에서 지원하지 않는 문법이나 API를 수동으로 조정해 코드 가독성이 떨어지지 않게 하고, 이 시점에서 바벨과 같은 트랜스파일러를 사용하자.
트랜스 파일러와 폴리필은 오래된 환경이나 애플리케이션, JS 최신 기능 둘 사이의 간극을 메꾼다. 간극은 절대 사라지지 않을 것이다. 따라서 저자는 JS 기반으로 프로젝트를 만들 때 트랜스파일이나 폴리필 사용이 표준으로 자리 잡아야 한다고 생각한다고 한다.
Last updated