Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 네임스페이스 오염을 피하는 방법 완벽 가이드

네임스페이스 오염(Namespace Pollution)이란?

JavaScript는 함수 오버로딩(function overloading)을 지원하지 않습니다. 따라서 같은 이름을 가진 두 개의 함수가 존재하면, 나중에 로드된 함수가 먼저 로드된 함수를 덮어쓰게(override) 됩니다. 이는 곧 JavaScript에 네임스페이스(namespace)라는 이름 구분 체계가 없다는 의미입니다.

다행히 객체(object)를 활용하면 직접 네임스페이스를 만들 수 있고, 이를 통해 함수나 변수 이름이 충돌하는 네임 충돌(name collision) 문제를 예방할 수 있습니다.

객체로 네임스페이스 만들기

가장 기본적인 패턴은 다음과 같습니다.

var Tutorix = Tutorix || {};

이 코드는 Tutorix 객체가 이미 존재하면 그대로 사용하고, 없으면 새로운 빈 객체를 생성하라는 의미입니다. 전역 스코프를 오염시키지 않으면서 하나의 진입점을 확보할 수 있는 안전한 방식입니다.

중첩 네임스페이스(Nested Namespace)

네임스페이스 안에 또 다른 네임스페이스를 중첩해서 만들 수도 있습니다.

var Tutorix = Tutorix || {};
Tutorix.TeamA1 = Tutorix.TeamA1 || {};

두 번째 줄은 TeamA1이 이미 존재하면 해당 객체를 사용하고, 그렇지 않으면 빈 TeamA1 객체를 생성합니다.

네임 충돌이 발생하는 문제 상황

아래 예제에서는 HTML 파일에서 단 2개의 매개변수만 전달했는데도 출력 결과에는 3개의 값이 나타납니다. 그 이유는 TeamA1과 TeamA2가 동일한 함수 이름 "student"를 공유하기 때문에 발생하는 네임스페이스 충돌 때문입니다.

TeamA1.js

<html>
<body>
<script>
    function student(Fname, Lname){
        this.Fname = Fname;
        this.Lname = Lname;
        this.getFullName = function(){
            return this.Fname + " " + this.Lname;
        }
    }
</script>
</body>
</html>

TeamA2.js

<html>
<body>
<script>
    function student(Fname, Mname, Lname){
        this.Fname = Fname;
        this.Mname = Mname;
        this.Lname = Lname;
        this.getFullName = function(){
            return this.Fname + " " + this.Mname + " " + this.Lname;
        }
    }
</script>
</body>
</html>

HTML 파일

<html>
<head>
<script type = "javascript" src = "TeamA1.js"></script>
<script type = "javascript" src = "TeamA2.js"></script>
</head>
<body>
<div id = "resultDiv"></div>
<script>
    document.getElementById("resultDiv").innerHTML =
    new student("Rajendra", "prasad").getFullName();
</script>
</body>
</html>

출력 결과

Rajendra prasad undefined

분명 TeamA1.js를 호출하기 위해 "Rajendra"와 "prasad"라는 2개의 인자만 전달했는데, 결과에는 "undefined"까지 포함되어 출력되었습니다. 그 이유는 매개변수가 3개인 TeamA2.js가 나중에 로드되면서 TeamA1.js의 student 함수를 덮어썼기 때문입니다. 이것이 바로 전역 스코프에서 발생하는 대표적인 네임 충돌 문제입니다.

네임스페이스로 문제 해결하기

이러한 이름 충돌을 피하려면 앞서 설명한 것처럼 객체를 사용해 네임스페이스를 생성해야 합니다.

TeamA1.js — Tutorix 네임스페이스 적용

아래 코드에서는 Tutorix라는 객체 아래에 TeamA1 네임스페이스를 만들어 student 함수를 격리했습니다.

<html>
<body>
<script>
    var Tutorix = Tutorix || {};
    Tutorix.TeamA1 = Tutorix.TeamA1 || {};
    Tutorix.TeamA1.student = function (Fname, Lname){
        this.Fname = Fname;
        this.Lname = Lname;
        this.getFullName = function(){
            return this.Fname + " " + this.Lname;
        }
        return this;
    }
</script>
</body>
</html>

TeamA2.js — Tutorix 네임스페이스 적용

마찬가지로 Tutorix 객체 아래에 별도의 TeamA2 네임스페이스를 만들어 충돌을 방지합니다.

<html>
<body>
<script>
    var Tutorix = Tutorix || {};
    Tutorix.TeamA2 = Tutorix.TeamA2 || {};
    Tutorix.TeamA2.student = function (Fname, Mname, Lname){
        this.Fname = Fname;
        this.Mname = Mname;
        this.Lname = Lname;
        this.getFullName = function(){
            return this.Fname + " " + this.Mname + " " + this.Lname;
        }
        return this;
    }
</script>
</body>
</html>

HTML 파일

두 개의 자바스크립트 파일(TeamA1.js와 TeamA2.js)을 모두 HTML 파일에 포함하고, 각각의 네임스페이스를 통해 함수를 호출합니다.

<html>
<head>
<script type = "javascript" src = "TeamA1.js"></script>
<script type = "javascript" src = "TeamA2.js"></script>
</head>
<body>
<script>
    document.write(window.Tutorix.TeamA1.student("Rajendra", "prasad").getFullName());
    document.write(window.Tutorix.TeamA2.student("Babu", "Rajendra", "prasad").getFullName());
</script>
</body>
</html>

출력 결과

Rajendra prasad
Babu Rajendra prasad

위 예제에서는 중첩 네임스페이스를 활용했습니다. 즉, Tutorix 네임스페이스 안에 TeamA1TeamA2를 각각 중첩시켜 네임 충돌을 완전히 피한 것입니다. 네임스페이스 충돌이 해소되었기 때문에 각 스크립트가 의도한 대로 정확한 결과를 출력하게 됩니다.

정리

  • JavaScript는 함수 오버로딩을 지원하지 않으므로, 같은 이름의 함수는 서로 덮어씁니다.
  • var ns = ns || {}; 패턴으로 전역 객체 하나만 노출시켜 네임스페이스를 만들 수 있습니다.
  • 중첩 네임스페이스를 사용하면 여러 모듈·팀의 코드를 안전하게 분리할 수 있습니다.
  • 현대 JavaScript에서는 ES 모듈(ESM)이나 IIFE, 클로저 등으로도 유사한 효과를 얻을 수 있습니다.