FastComments.com Blog

Fri Jan 31 2025
...

FastComments TypeScript 마이그레이션 완료

! 이 글에는 기술 용어가 포함되어 있습니다

변화된 점

FastComments에서는 정적 타입 언어를 중요하게 생각합니다. 보다 구체적으로, 빠른 컴파일러를 가진 적절한 타입 시스템을 좋아합니다. FastComments는 후자를 선택했습니다 - 또는 컴파일러가 없었습니다. 첫해에 최신 Java로 작성된 두 개의 서비스가 있었지만, 주요 백엔드와 프론트엔드 라이브러리는 Node에서 실행되는 CJS JS로 작성되었습니다.

다음 10년의 개발을 준비하기 위해, 가장 큰 FastComments 구성 요소를 TypeScript로 마이그레이션했습니다.

이는 1441개의 파일에 걸쳐 130,000줄 이상의 코드를 마이그레이션하고, 8,000개 이상의 컴파일 오류를 수정하는 것을 포함했습니다.

woooooo
GitHub 스크린샷

이는 2주에 걸쳐 진행되었습니다.

코드 동결 - 감사합니다

업그레이드를 완료하기 위해 2주 동안 코드 동결을 하는 동안, 버그 수정이나 기능 출시의 지연을 감수해 주신 고객님들께 감사의 말씀을 드립니다. 감사합니다!

수정된 버그

상상할 수 있듯이, 몇 가지 버그를 수정했습니다. 이들은 주로 스팸 감지와 캐싱과 관련된 것이었습니다.

Breaking Changes

  • 모든 API 엔드포인트는 이제 "failed"와 "failure"의 혼합 대신 status: 'failed'를 반환합니다. "success"는 변경되지 않았습니다.
  • 일치하는 항목이 없는 경우 첫 번째 위젯 구성을 기본값으로 설정하지 않으며, 대신 기본 시스템 구성을 반환합니다.

어떻게 진행되었나요?

예상대로, 이 작업을 도와줄 NPM 생태계의 많은 도구들이 잘 작동하지 않았습니다. 그래서 우리는 LLM을 사용하여 많은 작업을 수행하는 스크립트를 생성했습니다. 예를 들어, 우리는 JSDoc을 많이 사용했으므로, JSDoc을 가져와서 TypeScript 인터페이스 및 타입 정의로 변환하고, 함수 인수 및 반환 타입을 올바르게 주석 처리하는 스크립트를 작성할 수 있었습니다. 또한 CJS에서 ESM으로 마이그레이션하기 위해 이러한 스크립트를 사용했으며, 여기에는 import, export를 다시 작성하고 __dirname과 같은 일반적인 런타임 문제를 감지하는 것도 포함되었습니다.

런타임 문제에 대해 언급했나요?

2025년의 TypeScript는 어떤가요?

TypeScript는 비즈니스 로직을 작성하는 데 적합한 언어입니다. 그러나 Java는 여전히 더 나은 DevEx를 가지고 있습니다. Java, Go 또는 Rust가 컴파일되면, 대부분의 경우 작동할 것입니다. TypeScript로는 다음과 같은 작업을 할 수 있습니다:

console.log(__dirname);

... 그리고 이것은 컴파일됩니다.

하지만 현대 ES 모듈에서는 실행되지 않습니다. 당신의 IDE는 __dirname을 기꺼이 자동 완성해 줄 것이고, 그럼 런타임에서 오류가 발생할 것입니다. 이것은 Spring DI와 비슷해 보이지만, 더 나쁩니다.

또한 다음과 같은 작업도 할 수 있습니다:

context.someImportantMethodToCall;

이제 이것은 "문장"입니다. 유효한 "문장"입니다. 처음 보았을 때 someImportantMethodToCall을 호출하는 것처럼 보일 수 있지만, 사실 우리는 호출하고 있지 않습니다! 적어도 내 IDE는 이에 대해 경고하지 않으며, 컴파일러도 마찬가지입니다. 코드는 그냥 아무 것도 하지 않을 것입니다 (단, someImportantMethodToCall이 클래스 getter인 경우는 암시적으로 호출됩니다...).

해결책은 다음과 같습니다:

context.someImportantMethodToCall();

이런 것을 eslint와 "부작용이 없는 규칙"과 같은 것으로 감지할 수 있을 것이라고 생각하지만, 그러면 새로운 대규모 라이브러리를 유지 관리하기 위해 추가로 도입해야 하고, eslint는 매 빌드마다 전체 코드베이스를 파싱해야 하므로 도구가 느려집니다. 그래서 괜찮습니다. eslint와 같은 느린 도구를 다루는 것의 생산성 영향은 제 과거 직장에서 마주했던 것보다 더 컸습니다. 이로 인해 spacing 등의 사소한 것들을 수정하는 데서 얻었던 생산성 "증가"보다. 현재 더 빠른 대안들이 나오고 있어 좋습니다.

TypeScript는 Pick<User, 'username', 'email'>와 같은 언어 기능 때문에 정말 좋습니다. 이는 타입 추론과 결합되어, 각 객체의 형식에 대한 클래스를 정의할 필요 없이 더 큰 객체의 하위 집합에 대한 타입 안전한 쿼리 결과를 제공합니다. Pick은 Scala에 없는 것에 대해 놀랐습니다. 타입 유니온도 정말 좋습니다.

점진적 빌드도 꽤 잘 작동하며, CI에서 공유 라이브러리, 프론트엔드 및 백엔드를 빌드하는 데 평균적으로 빌드 시간이 약 5-10초 증가했습니다.

개발 타임라인

궁금한 분들을 위해, 우리의 진행 상황은 다음과 같았습니다:

  • 첫 번째 날: 362개의 파일에서 5564개의 오류를 발견했습니다.
  • 두 번째 날: 239개의 파일에서 4034개의 오류를 발견했습니다.
  • 세 번째 날: 191개의 파일에서 3784개의 오류를 발견했습니다.
  • 네 번째 날: 169개의 파일에서 2974개의 오류를 발견했습니다.
  • 다섯 번째 날: 171개의 파일에서 3000개의 오류를 발견했습니다.
  • 여섯 번째 날: 165개의 파일에서 2916개의 오류를 발견했습니다.
  • 일곱 번째 날: 157개의 파일에서 2618개의 오류를 발견했습니다.
  • 여덟 번째 날: 109개의 파일에서 2253개의 오류를 발견했습니다.
  • 아홉 번째 날: 69개의 파일에서 1605개의 오류를 발견했습니다.
  • 열 번째 날: 53개의 파일에서 686개의 오류를 발견했습니다.
  • 열한 번째 날: 백엔드 유닛 테스트 성공
  • 열두 번째 날: 프론트엔드 마이그레이션 시작, 3118개의 오류 발견.
  • 열세 번째 날: 2172개의 오류 발견.
  • 열네 번째 날: 1224개의 오류 발견.
  • 열다섯 번째 날: 498개의 오류 발견.
  • 열여섯 번째 날: 모든 컴파일 오류 수정.
  • 열일곱 번째 날: 출시. E2E 테스트 통과. 예기치 않은 런타임 문제로 30분 다운타임 발생. :)

미래

우리는 이 작업을 다음 10년간의 개발지원을 위해 수행했습니다. 시스템이 이제 충분히 커져서 타입 시스템으로 개발하는 것이 더 빠르다고 느낍니다.

우리의 TypeScript 라이브러리는 이미 개선되기 시작했으므로, NPM에서 계속 발전할 것으로 기대할 수 있습니다. 이제 서버와 클라이언트 코드에서 해당 라이브러리를 직접 사용하고 있습니다.

또한 서버 코드에서 생성된 클라이언트 SDK도 곧 출시할 예정입니다. 이는 이 작업의 주요 동기 중 하나였습니다.

결론

모든 주요 릴리스와 마찬가지로, 우리는 이러한 변경 사항을 최적화하고, 테스트하며, 적절하게 출시할 수 있어 기쁩니다. 문제가 발견되면 아래에 알려주세요.

감사합니다!