메소드, 클래스와 같은 개념들이 등장한 배경은 프로그램을 만드는 데 사용하는 코드의 양이 기하급수적으로 증가하면서 직면하게 되는 막장을 극복하기 위한 것이었다. 거대해진 코드를 효율적으로 제어하지 못한다면 웅장한 소프트웨어를 만드는 것은 점점 불가능한 일이 될 것이다. 유효범위라는 것도 그러한 맥락에서 등장한 개념이다. 하지만 유효범위는 메소드나 클래스처럼 특별한 문법적인 규칙을 가지고 있는 것은 아니다. 오히려 메소드나 클래스 안에 포함되어서 이러한 기능들의 부품으로서의 가치를 높여주는 역할을 한다고 할 수 있다.
아래의 코드를 보자.
package org.opentutorials.javatutorials.scope;
public class ScopeDemo {
static void a() {
int i = 0;
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
a();
System.out.println(i);
}
}
}
10행에는 변수 i의 값을 기준으로 동작하는 반복문이 있다. 11행에는 메소드 a를 호출하고 있는데 메소드 a의 내부에는 변수 i의 값이 0으로 지정되고 있다. 위의 코드를 실행시킨 결과는 아래와 같다.
0
1
2
3
4
그런데 만약 메소드 a가 실행될 때 메소드 내부의 변수 i의 값이 반복문의 변수 i의 값을 덮어쓰게 된다면 어떻게 될까? 반복문이 호출될 때마다 변수 i의 값이 0이 되기 때문에 이 반복문은 무한 반복에 빠지게 된다. 이런 상황을 해결하기 위해서는 메소드 a의 내부변수 i의 이름이나 반복문의 변수 i의 이름을 다르게 로직을 고쳐야 할 것이다.
만약 로직이 매우 복잡하거나, 메소드 a가 타인이 만든 것을 사용하는 것이라면 이것은 쉽지 않은 일이 된다. 이러한 문제는 부품으로서의 가치를 저하시킨다. 부품이란 조작 방법만 알면 내부의 동작 원리를 모르고도 사용할 수 있어야 한다. 또한, 부품 내부의 상태로 인해서 그 부품을 사용하는 외부의 동작 방법에 영향을 준다면 이 또한 좋은 부품이라고 할 수 없을 것이다.
실행결과를 보면 알겠지만, 내부 변수의 값이 그 외부에 영향을 미치지 않는다는 것을 알 수 있다. 처음 언어를 배우는 입장에서는 이것을 그러려니 하기 쉽겠지만 그렇지 않다. 이러한 동작방법은 수 많은 시행착오를 통해서 조율된 결과라고 할 수 있다. 과거의 프로그래밍 언어는 메소드 내에서의 변수가 외부의 변수에도 영향을 미쳤기 때문에 변수나 메소드의 이름을 사무실 칠판에 적어가면서 코딩을 해야 했던 시절도 있었다. 또는 변수명을 길게 하도록 권장하거나, 심지어 변수명에 프로그래머의 이름을 적는 경우도 있었다!
이런 문제를 해결하기 위해서 다양한 시도들이 있었는데 그 노력의 결과 중의 하나가 유효범위라고 할 수 있다.