diff --git a/contributions/66075.md b/contributions/66075.md new file mode 100644 index 00000000..6b885da2 --- /dev/null +++ b/contributions/66075.md @@ -0,0 +1,129 @@ +--- +pr-url: https://github.com/nodejs/node/pull/66075 +--- + +# worker: remove messageerror listeners on exit + +## 문제 내용 + +Worker 종료 시 등록되어 있던 `messageerror` listener가 정상적으로 제거되지 않는 문제를 수정했다. + +관련 코드를 확인한 결과, 실제 Event 이름은 `messageerror`인데 cleanup 과정에서는 `messageerrors`라는 잘못된 이름을 사용하고 있었다. + +```text +실제 Event 이름 +messageerror + +기존 cleanup 코드 +messageerrors +``` + +이 때문에 Worker가 종료돼도 `messageerror` listener가 남아 있을 수 있었다. + +관련 Issue: #65782 + +## 원인 분석 + +Worker 종료 과정에서는 여러 listener와 resource를 정리한다. + +관련 코드는 `lib/internal/worker.js`에 있었고, 기존에는 다음과 같이 작성되어 있었다. + +```js +this.removeAllListeners('message'); +this.removeAllListeners('messageerrors'); +``` + +하지만 등록되는 실제 Event 이름은 다음과 같다. + +```js +worker.on('messageerror', listener); +``` + +`removeAllListeners()`는 전달된 Event 이름이 정확히 일치해야 하므로 `messageerrors`로는 `messageerror` listener를 제거할 수 없었다. + +문제 흐름은 다음과 같았다. + +```text +messageerror listener 등록 +→ Worker 종료 +→ cleanup 실행 +→ messageerrors 제거 시도 +→ Event 이름 불일치 +→ messageerror listener가 남음 +``` + +## 해결 과정 + +잘못된 Event 이름을 실제 Event 이름으로 수정했다. + +```diff +- this.removeAllListeners('messageerrors'); ++ this.removeAllListeners('messageerror'); +``` + +코드 변경 자체는 한 줄이었지만, Worker 종료 시 listener가 실제로 정리되는지를 확인하기 위해 회귀 테스트도 함께 추가했다. + +## 테스트 및 검증 + +간단한 Worker를 생성하고 `message`와 `messageerror` Event에 listener를 등록했다. + +```js +const worker = new Worker('', { eval: true }); +const listener = () => {}; + +worker.on('message', listener); +worker.on('messageerror', listener); +``` + +Worker가 종료된 뒤 두 listener가 모두 제거되었는지 확인했다. + +```js +worker.on('exit', common.mustCall(() => { + assert.strictEqual(worker.listenerCount('message'), 0); + assert.strictEqual(worker.listenerCount('messageerror'), 0); +})); +``` + +로컬에서는 다음 테스트와 lint를 실행했다. + +```bash +python3 tools/test.py --mode=release parallel/test-worker-messageerror-listener-cleanup +make lint-js +``` + +두 검증 모두 통과했다. + +Codecov에서도 수정된 coverable line들이 테스트에 의해 실행되는 것을 확인했다. + +## 리뷰 및 CI + +PR을 올린 뒤 일정 시간이 지나 `@nodejs/workers` 팀에 follow-up을 남겼다. + +follow-up에서는 다음 내용을 다시 정리했다. + +```text +Issue #65782 해결 +→ messageerror listener cleanup 수정 +→ Regression Test 추가 +→ Target Test 통과 +→ make lint-js 통과 +``` + +이후 `jasnell`에게 Approved를 받았고, Node.js CI도 여러 차례 실행됐다. + +## 결과 + +PR #66075는 최종적으로 Node.js Core에 Merge되었다. + +```text +Status: Merged +Merge commit: d9208ccdccb1c6cd5bd0011df0775e860c5d2d1e +``` + +## 배운 점 + +이번 기여를 통해 코드 변경량이 작더라도 실제 API lifecycle에 영향을 줄 수 있다는 점을 배웠다. + +특히 EventEmitter에서는 Event 이름이 문자열로 정확히 일치해야 하므로 한 글자 오타도 listener cleanup 실패로 이어질 수 있었다. + +또한 작은 수정일수록 단순히 코드만 변경하는 것이 아니라, 같은 문제가 다시 발생하지 않도록 회귀 테스트를 함께 남기는 것이 중요하다는 점을 경험했다.