goongoguma's blog

Don’t modify objects you don’t own

제가 야후에 도착하고나서 처음한 연설은 유지가능한 자바스크립트에 관한것이었습니다. 제가 쓰고 말했던 대부분의 주제처럼 저는 이 내용이 그렇게 논란이 될 줄은 생각하지 못했습니다. 이 주제에서 말하고자 한것은 혼자 코드를 작성하는것과 회사 환경에서 코드를 작성하는것은 별개라는 이야기였습니다. 웹개발자들의 독특한 점은 누구도 학교에서 배우지 않았다는 겁니다.; 우리는 모두 어떤 방식으로든 취미생활로 시작했으며 대부분 스스로 공부했습니다.

Professionalization

직업으로 웹개발자를 하는것은 남들과는 다른 시작 때문에 어려운일이었습니다. 야후와 같은 큰 회사에서도 웹개발자들은 어쩔수 없이 혼자서 공부를 했습니다. 아마 당신은 작은 회사에서 “the web guy”였으며, 하고싶은 일이 있으면 마음껏 할 수 있었겠죠. 큰 회사들이 웹개발이라는 발견되지 않은 영역의 문을 두드릴때, 많은 웹개발자들은 제한이 있는 회사 환경에 들어왔습니다. 혼자서 배우고 방향을 결정하는 작은 전투에서의 용병이 팀과 일하는 방법을 찾아야 했죠. 제가 2007년에 했던 연설은 웹개발이라는 영역은 프론트엔드 엔지니어링으로 진화하고있고 사람들은 이런 변화에서 문제를 겪고있다는 것이었습니다. Nate Koechley와 같이 똑똑한 친구들은 프론트엔드 엔지니어링의 직업화와 우리 분야가 어떻게 진화하는지 이야기 했습니다. 저의 이야기는 같은 목적을 추구합니다: 코드를 최대한 유지 가능케하면서 프론트엔드 엔지니어들을 자바스크립트 개발 팀 환경에서 적응하도록 돕는것입니다.

Why can’t I modify objects I don’t own?

저는 아직도 유지가능한 자바스크립트에 관해 이메일과 댓글들을 아직도 받고있습니다. 그리고 가장 많이 받는 질문은, “왜 제가 소유하지 않은 객체를 수정하면 안되나요?”입니다. 자바스크립트는 물론 객체들과 객체의 멤버들을 추가하거나 제거할 수 있는 동적인 언어입니다. 많은 분들이 이 언어를 즐기는지에 대한 정확한 이유입니다: 해당 언어에 있어서 제약은 거의 없습니다. 그리고 저는 수정하지 말라고 말하죠. 왜일까요?

Dependability

간단하게 설명하자면 회사의 소프트웨어 제품들은 유지성을 위해 일괄적이고 의존할 수 있는 실행 환경이 필요합니다. 다른 언어들에서는, 이미 존재하고 개발을 위해 사용되는 객체들을 라이브러리들이라고 생각합니다. 자바스크립트에서 사람들은 이미 만들어져 있는 객체들을 하고싶은것을 다 해볼 수 있는 놀이터로 보고있습니다. 제가 말하고자 하는것은 이미 존재하는 자바스크립트 객체들을 유틸리티 라이브러리로 다루어야한다는 것이었습니다. 메서드를 재정의 하거나, 새로운 메서드를 추가하거나 이미 존재하는 메서드들을 지우지마세요.

만약 여러분이 프로젝트에서 일하는 유일한 사람이라면 소유하지않은 객체를 수정하지 말라는 규칙에서 쉽게 벗어날 수 있습니다. 왜냐하면 어떤 유형이 수정되었고 예상되는지 알 수 있기 때문입니다. 하지만 팀에 소속되어 있는 사람으로서 큰 프로젝트에 배정되었을때, 이 규칙을 따르지 않는다면 큰 혼란을 불러올 수 있고 많은 시간을 낭비하게 될겁니다. 저는 My Yahoo에서 일하고 있을때 발생했던 버그가 아직도 기억납니다. 왜냐하면 누군가 YAHOO.util.Event.stopEvent() 를 재정의했기 때문이었죠. 이 문제를 해결하기 위해 며칠이 걸렸습니다. 왜냐하면 모두가 생각하기에는 해당 메서드는 제대로 작동하고 있을거라고 추측했기 때문이었죠. 문제를 발견하고나서 또 다른 버그를 발견했습니다. 해당 메서드가 재정의 된 의도대로 사용되는 부분이 다른곳에 존재했기 때문이었죠… 물론, 이 부분은 의도한대로 동작하지 않았습니다. 이 문제를 푸는것은 엄청난 혼란이었으며 다른 엔지니어들이 이런 일을 겪지 않기를 바랬습니다.

Incompatible implementations

하지만 개발자들이 겪는 혼란이 유일한 문제는 아닙니다. 자기자신이 소유하지 않은 객체를 수정함으로써 발생할 수 있는 다른 문제는 이름 충돌과 호환이 되지 않는 구현입니다. 자바스크립트의 라이브러리인 Prototype에서 교훈을 얻을 수 있습니다. John Resig가 얼마전에 이 문제에 대해 작성했습니다만, 정리를 해보자면 Prototype의 1.6버전 이전에 라이브러리 자체에서 document.getElementsByClassName() 메소드를 HTML5에 포함되고 브라우저 자체적으로 구현되기 이전에 지원했다고 합니다. 거기다가, Prototype 또한 Array 객체에서 each() 메서드를 추가했습니다. 그래서 해당 라이브러리를 사용하는 개발자들은 아래와 같은 코드를 사용했습니다.

document.getElementsByClassName("myclass").each(doSomething);

위의 코드는 document.getElementsByClassName() 메서드가 자바스크립트 자체내에 추가되기전까지는 문제가 되지 않았습니다. Prototype 버전이 Array 인스턴스를 리턴하는거와 다르게 자체적으로 구현된 메서드는 NodeList 객체를 리턴했습니다. NodeList에서는 each() 메소드가 없다보니 위의 코드 패턴은 브라우저를 실행시킬때 자체적으로 만들어진 document.getElementsByClassName() 자바스크립트 에러를 발생시겼습니다. 결국에는 Prototype을 사용하고 있던 유저들은 라이브러이와 코드, 두개를 모드 업그레이드 해야 했으며 유지보수에 있어서 악몽이 되었습니다.

What if everyone did it?

몇개의 예시는 건드리지 말아야할 객체를 수정할때 발생하는 유지보수의 문제를 다 보여주지는 않습니다. 이 문제를 이해하기 위해서, 한발짝 뒤로 물러서서 도덕 철학을 잠시 보았으면 합니다. 도덕 철학이란 행동이 도덕적인지 판단하는 것입니다. 많은 학교들이 이 주제에 대해 많이 생각해보고 있지만 저는 제가 가장 좋아하는 철학자인 임마뉴엘 칸트에 대해 말해보고 싶습니다.

도덕 철학에 대해 깊이 들어가 철학적 토론을 벌이고 싶지는 않지만, 칸트는 ‘보편법’을 도덕적 행위의 기초로 규정하려고 노력한 것으로 유명합니다. 보편법을 간단하게 말하자면, 만약 모두가 이 행동을 하면 무슨일이 발생할까?라고 물어보고 행동을 결정하는겁니다. 예를 들어, 만약 모두가 시험에서 부정행위를 하면 어떻게 될까? 이런 경우에는 시험은 소용없어지고, 결국에는 도덕적 행동이 아니겠죠.

위에서 말한 철학을 해당 주제에 적용해보도록 하겠습니다. 만약 당신의 팀 모두가 팀에서 소유하고 있지 않는 객체를 수정하기 시작한다면? 만약 document를 수정하고 다른 팀원들도 그렇게 했다면? 만약 팀의 모든 사람들이 자신만에 전역 변수를 생성했다면? 이러한 행동들이 팀 개발 환경에 있어 얼마나 해로운지 알고 계셨으면 좋겠습니다.

간단하게 설명드리자면: 만약 팀의 모든 사람들이 소유하지 않은 객체들을 수정한다면, 당신은 이름 충돌과 호환이 되지 않는 구현 그리고 끔찍한 유지보수를 경험할 것입니다.

여담으로, 저는 칸트의 질문이 확장해야하는 어떤 시스템과 관련있다는 것을 발견했습니다. “만약 모두가 한다면?”이라는 질문은 기술적인 부분을 설계할때 문제를 줄여줄 수 있습니다.

Conclusion

유지 가능한 코드는 브라우저가 바뀌더라도 수정할 필요가 없는 코드를 말합니다. 브라우저를 개발하는 개발자가 현재의 브라우저를 얼마만큼 발전시킬지 그리고 언제 발전시킬지는 알 수 없습니다. 여러분이 작성한 코드는 미래의 브라우저와 자바스크립트 라이브러리에서 수정 없이도 계속 작동되어야 하며 여러분이 객체를 수정할때 해당 객체가 여러분이 소유하지 않은 객체라는 것을 확신할 수 없습니다. 여러분이 확신할 수 있는 코드는 여러분이 직접 작성한 코드 입니다.

이 부분을 강조하고 싶습니다: 여러분이 생성하지 않은 객체에서 수정이 필요한 경우에는 여러분의 코드는 유지보수하기 어렵습니다. 그 길을 선택하게 되면 유지보수에 있어서 악몽을 겪을 것 입니다.

추신.만약 여러분이 더 많은 배움을 원하신다면 해당 발표를 확인해보세요.

원문: Maintainable JavaScript: Don’t modify objects you don’t own by Nicholas C. Zakas