전역스코프 동적스코프 정적스코프


일반적으로 스코프를 사용하여 이름의 유효범위를 지정 해야한다. 스코프는 어떻게 동작하는지 알아보자.



동적스코프

전역에 x라는 변수가 있다고 하자. 그리고 지역함수에도 x라는 변수가 있다고 하자.

지역함수에 들어오면 전역에 위치한 x가 어떤 값을 가지고 있더라고 지역함수 내의 x는 지역함수 내에서 만큼은 값을 보장받을 수 있다. 즉 지역함수 내에서는 갓이 유효하다.

이는 전역의 변수의 값을 다른 곳에 저장한 후 지역함수를 빠져나갈때 값을 되돌리기 때문이다. 이를 수행해 주는것이 동적스코프이다. 참고로 perl 4(1991년) 부터는 변수를 local이라는 키워드로 선언하면 이를 알아서 해준다. 



Perl


$x = "global";


sub yobu {

local $x = "yobu";

&yobareru();

}


sub yobureru {

print "$x\n";    # yobu 라고 출력됨

}


&yobu();


이 예제에서는 yobu() 함수의 지역변수 x가 sub함수 yobareru()까지 영향을 미친다.

동적 스코프는 변경값이 호출되는 곳에 파급되기 때문에 어떤 값이 될지 코드를 보지 않고서는 알 수 없다. 코드의 양이 많아지면 정말 귀찮은 일이 될것이다.


변수들의 데이터를 다른 곳에 저장하는 대신 대웅표라는 것을 만들어 관리한다. 

동적 스코프와 전역 스코프는 이 대응표를 프로그램 전체에 결쳐서 몇 개의 함수가 공유하고 있다. 


함수에 들어가면 새로운 대응표가 만들어진다

해당 함수 안에서의 내용은 대응표에 기록되지고 사용된다.

해당 함수를 벗어날 대 이 대응표를 제거한다.


그리고 변수를 참조할 때에는 가까운 곳에서 부터 순서대로 읽는다.
이것이 위의 예제에서 결과가 yobu인 이유이며, 만약 지역에 변수가 없다면 전역변수의 값이 출력될 것이라고 짐작할 수 있겠다.

 여러 함수에서 대응표를 공유하기때문에 문제가 발생한다면 함수별로 대응표를 나눠볼 수 있을 것이다. 이것이 정적스코프가 동작하는 개념이다.


함수에 들어가면 해당 함수 전용의 새로운 대응표를 준비한다.

함수내에서의 내용은 해당 대응표에 기록되고 사용된다

함수를 빠져나갈때 해당 대응표를 제거한다.


정적스코프라고 가정하에 다시 예제를 보자.


Perl


$x = "global";


sub yobu {

my $x = "yobu";

&yobareru();

}


sub yobureru {

print "$x\n";    # global 라고 출력됨

}


&yobu();



yobareru에서 x를 참고할 때 해당 함수의 대응표에는 x가 없다. 그러므로 yobu함수의 대응표가 아닌 바로 전역을 읽는다. 

우리는 이 방식이 일반적인 것이라고 생각한다. 그렇다. 현재 많은 언어가 정적 스코프를 도입하고 있기 때문이다. 


JavaScript에서도 var를 붙이지 않으면 전역스코프이고 var를 붙이면 정적스코프이다. 

몇몇 언어들은 스코프방식이 변하기도 했다.


Python은 처음부터 정적 스코프였다. 

Python2.0 에는 스코프가 3가지가 있다.


지역, 전역, 빌트인

빌트인은 프로그램의 어디에서든 참조할 수 있는 스코프이며 여기에는 문자열화 함수stir이나 Runtime(실행 시)  Error등이 있다.

이는 언어에 기본 탑재되어 있는 함수나 예외이므로 빌트인이라고 한다. 



python2.0에서 전역 스코프는 파일 단위로 존재한다. 따라서 파일 스코프라도고 한다. 


 


python은 대입과 함께 변수를 만드는 언어이다. 함수안에서 대입을 하면 아무것도 선언하지 않더라도 지역변수가 된다.

이는 두가지 문제를 만들 수 있다.



이제 파이썬에서 발생할 수 있는 스코프 문제를 살펴보자


첫번째, 





실제로 2.0 버전에서는 함수 bar()의 지역 스코프에서 이름 x를 발견하지 못하면 전역스코프를 보러 가는 설계로 되어있다(그림7.9의 1번). 

결국 수정할 필요가 있는 문제점이라고 인식되어 2001년에 공개된 Python2.1에서는 그림7.9의 1번처럼 동작하도록 수정되었다.




두번째, 


대입과 함께 변수를 만들기 때문에, 함수에 지역변수가 없으면 바로 지역스코프 변수로 생성한다.

처음에는 JavaScript처럼 var변수를 이용해서 해결하고자 했지만, 과거 코드와 호환성이 없어서 채택되지 않았고


2006년 3.0버전에서 nonlocal이라는 키워드로 선언하여 사용하도록 채택되었다.




이런 스코프 개념은 언어마나 한가지로 정의되지는 않는다.


자바의 경우 정적스코프의 언어이지만 java의 클래스는 소스코드 어디서든 참조할 수 있다. 

즉 클래스는 전역 스코프를 사용하는 것이다. 클래스는 이름이 계층적으로 이루어져있고, 임포트하지 않으면 사용할 수 없어서 전역변수가 가지고 있던 충돌 문제를 피한다. 

그리고 잘 알고있는 static 변수도 전역스코프의 변수이므로 소스코드 어디든지 바꿀 수 있다. 

하지만 static변수를 사용할 때 주의를 해야하는 이유는 남용하게되면 이해하기 어려운 코드가 되기 때문이다.






출처. 코딩을 지탱하는 기술

'Development > Etc.' 카테고리의 다른 글

type(형)  (0) 2016.02.06
언어별로 문자열 처리  (0) 2016.02.06
상속이 is-a 관계여야 하는이유와 delegation  (0) 2016.02.06
언어별 클래스의 의미  (0) 2016.02.06
이벤트기반과 메세지기반 아키텍처의 차이  (0) 2016.02.06

+ Recent posts