프로그래밍 초보자를 위한 친절한 안내서: Scope 완벽 정복 mymaster, 2024년 06월 30일 프로그램을 짜다 보면 변수가 어디서 나타났다 사라졌다 하는 것 같고, 똑같은 이름을 가진 변수가 여러 개 등장해서 혼란스러웠던 경험, 다들 있으시죠? 마치 미로 속을 헤매는 기분이 들기도 합니다. 이런 혼란을 막아주는 중요한 개념이 바로 ‘scope’입니다. Scope는 프로그래밍 언어가 변수의 유효 범위를 결정하는 규칙이라고 할 수 있습니다. 이 글에서는 scope가 무엇인지, 왜 중요한지, 그리고 어떻게 작동하는지 초보자도 이해하기 쉽게 자세히 알려드릴 것입니다. 이 글을 다 읽고 나면 변수 범위에 대한 걱정 없이 자신감 있게 코드를 작성할 수 있을 것입니다. 1. Scope란 무엇인가요? Scope는 한 마디로 “변수의 유효 범위”를 뜻합니다. 우리가 어떤 공간 안에 들어갈 수 있는 권한을 “출입 범위”라고 한다면, scope는 변수가 어떤 코드 영역에서 접근 및 사용 가능한지를 정의하는 “변수의 출입 범위”라고 할 수 있습니다. 예를 들어, 여러분이 아파트에 살고 있다고 가정해 보겠습니다. 여러분은 자신의 집 안에서는 자유롭게 행동할 수 있습니다. 거실에서 TV를 보거나 침실에서 잠을 잘 수도 있고, 부엌에서 요리를 할 수도 있죠. 하지만 다른 집에는 들어갈 수 없습니다. 다른 집은 여러분의 “출입 범위” 밖에 있기 때문입니다. 프로그래밍에서 변수도 마찬가지입니다. 각 변수는 자신이 선언된 위치를 기준으로 정해진 유효 범위를 가지며, 이 범위 안에서만 접근하고 사용할 수 있습니다. 만약 변수가 자신의 유효 범위 밖에서 사용하려고 한다면, 프로그램은 오류를 발생시킵니다. 마치 여러분이 다른 집에 들어가려다가 경비원에게 제지당하는 것과 같은 상황입니다. Scope는 프로그래밍 언어마다 조금씩 다르게 구현될 수 있지만, 기본적인 원리는 동일합니다. 즉, 변수가 어디서 선언되었는지에 따라 그 변수에 접근할 수 있는 코드 영역이 결정됩니다. 2. Scope가 중요한 이유는 무엇인가요? Scope는 프로그래밍에서 다음과 같은 중요한 역할을 합니다. 2.1 변수 이름 충돌 방지 프로그램을 작성하다 보면 동일한 이름을 가진 변수를 여러 개 사용해야 할 때가 있습니다. 예를 들어, 여러 함수에서 사용자의 이름을 저장하는 변수를 사용한다고 가정해 보겠습니다. 만약 scope가 없다면, 각 함수에서 사용자 이름 변수를 서로 다른 이름으로 선언해야 하는 불편함이 생깁니다. 하지만 scope를 사용하면 각 함수 내에서 동일한 이름의 변수를 선언하더라도 서로 다른 변수로 인식되기 때문에 변수 이름 충돌을 걱정하지 않아도 됩니다. 예를 들어, 아래와 같은 코드가 있다고 가정해 보겠습니다. def 함수1(): 이름 = "홍길동" print(이름) def 함수2(): 이름 = "김철수" print(이름) 함수1() # 출력: 홍길동 함수2() # 출력: 김철수 위 코드에서 함수1과 함수2는 각각 이름이라는 변수를 가지고 있지만, 서로 다른 scope에 속하기 때문에 변수 이름 충돌이 발생하지 않습니다. 2.2 메모리 관리 효율화 Scope는 메모리 관리에도 중요한 역할을 합니다. 변수는 메모리 공간을 차지하기 때문에, 필요하지 않은 변수를 메모리에 계속 저장해두면 메모리 낭비가 발생합니다. Scope는 변수의 유효 범위가 끝나면 해당 변수가 사용하는 메모리 공간을 자동으로 해제하여 메모리 관리를 효율적으로 수행합니다. 예를 들어, 아래와 같은 코드가 있다고 가정해 보겠습니다. def 함수(): 숫자 = 10 print(숫자) 함수() # 출력: 10 위 코드에서 숫자 변수는 함수() 내부에서만 사용됩니다. 따라서 함수()가 실행을 마치면 숫자 변수는 더 이상 필요하지 않게 되고, Python 인터프리터는 숫자 변수가 사용하던 메모리 공간을 자동으로 해제합니다. 2.3 코드 가독성 및 유지보수 향상 Scope는 코드의 가독성과 유지보수를 향상시키는 데에도 도움이 됩니다. 변수의 유효 범위가 명확하게 정의되어 있기 때문에, 다른 개발자들이 코드를 이해하고 수정하는 것이 더 쉬워집니다. 예를 들어, 아래와 같은 코드가 있다고 가정해 보겠습니다. def 계산하기(숫자1, 숫자2): 결과 = 숫자1 + 숫자2 return 결과 위 코드에서 결과 변수는 계산하기() 함수 내부에서만 사용되기 때문에, 계산하기() 함수 외부에서는 결과 변수에 접근할 수 없습니다. 이는 다른 개발자가 계산하기() 함수 외부에서 결과 변수를 변경하여 의도치 않은 오류를 발생시키는 것을 방지합니다. 3. 다양한 Scope의 종류 프로그래밍 언어마다 Scope의 종류와 세부적인 동작 방식이 조금씩 다를 수 있습니다. 하지만 대부분의 언어는 공통적으로 다음과 같은 Scope들을 지원합니다. 3.1 전역 Scope (Global Scope) 전역 scope는 프로그램 전체에서 접근 가능한 범위입니다. 전역 scope에 선언된 변수는 프로그램 어디에서든 사용할 수 있습니다. 전역 변수는 함수 외부에서 선언됩니다. 예를 들어, 아래와 같은 코드가 있다고 가정해 보겠습니다. 전역_변수 = 10 def 함수1(): print(전역_변수) def 함수2(): print(전역_변수) 함수1() # 출력: 10 함수2() # 출력: 10 위 코드에서 전역_변수는 전역 scope에 선언되었기 때문에 함수1과 함수2 모두 전역_변수에 접근하여 값을 출력할 수 있습니다. 하지만 전역 변수는 프로그램 어디에서든 수정될 수 있기 때문에, 예상치 못한 오류가 발생할 수 있다는 단점이 있습니다. 따라서 전역 변수는 최대한 사용을 자제하고, 불가피하게 사용해야 할 경우에는 변수 이름을 명확하게 지정하여 다른 변수와 구분되도록 하는 것이 좋습니다. 3.2 지역 Scope (Local Scope) 지역 scope는 함수 내부에서만 접근 가능한 범위입니다. 지역 scope에 선언된 변수는 해당 함수 내부에서만 사용할 수 있으며, 함수 외부에서는 접근할 수 없습니다. 지역 변수는 함수 내부에서 선언됩니다. 예를 들어, 아래와 같은 코드가 있다고 가정해 보겠습니다. def 함수(): 지역_변수 = 20 print(지역_변수) 함수() # 출력: 20 print(지역_변수) # 오류 발생: NameError: name '지역_변수' is not defined 위 코드에서 지역_변수는 함수() 내부에서 선언되었기 때문에 함수() 내부에서는 지역_변수에 접근하여 값을 출력할 수 있습니다. 하지만 함수() 외부에서 지역_변수에 접근하려고 하면 NameError가 발생합니다. 지역 변수는 해당 함수 내부에서만 사용되기 때문에 다른 함수의 변수와 이름이 충돌할 위험이 없고, 함수 실행이 끝나면 자동으로 메모리에서 해제되기 때문에 메모리 관리에도 효율적입니다. 3.3 비지역 Scope (Nonlocal Scope) 비지역 scope는 Python과 같은 일부 프로그래밍 언어에서 지원하는 특수한 scope입니다. 비지역 scope는 함수 내부에서 선언된 변수가 해당 함수를 포함하는 바깥쪽 함수의 지역 변수를 참조할 때 사용됩니다. 예를 들어, 아래와 같은 코드가 있다고 가정해 보겠습니다. def 바깥_함수(): 바깥_변수 = 10 def 안쪽_함수(): nonlocal 바깥_변수 바깥_변수 = 20 print("안쪽 함수:", 바깥_변수) 안쪽_함수() print("바깥 함수:", 바깥_변수) 바깥_함수() # 출력: 안쪽 함수: 20, 바깥 함수: 20 위 코드에서 안쪽_함수 내부에서 nonlocal 키워드를 사용하여 바깥_변수를 비지역 변수로 선언했습니다. 이는 안쪽_함수 내부에서 바깥_변수를 수정하면 바깥_함수의 지역 변수인 바깥_변수 값이 변경됨을 의미합니다. 비지역 scope는 중첩된 함수에서 변수를 공유하고 수정해야 할 때 유용하게 사용될 수 있습니다. 4. Scope 관련 추가 정보 4.1 LEGB 규칙 Python은 변수를 찾을 때 특정한 우선순위를 가지고 있습니다. 이를 LEGB 규칙이라고 부르며, 각각 Local, Enclosing function locals, Global, Built-in의 약자입니다. Local (지역): 현재 실행 중인 함수 내부에서 선언된 변수를 먼저 찾습니다. Enclosing function locals (비지역): 현재 함수를 감싸고 있는 바깥쪽 함수의 지역 변수들을 찾습니다. Global (전역): 현재 모듈의 전역 scope에서 선언된 변수를 찾습니다. Built-in (내장): Python에서 기본적으로 제공하는 내장 함수나 상수들을 찾습니다. Python 인터프리터는 위 순서대로 변수를 찾기 때문에, 동일한 이름의 변수가 여러 scope에 존재하는 경우 LEGB 규칙에 따라 가장 가까운 scope의 변수가 우선적으로 사용됩니다. 4.2 Scope 관련 주의사항 변수의 scope를 명확하게 이해하고 코드를 작성하는 것은 매우 중요합니다. 변수의 scope를 제대로 이해하지 못하면 예상치 못한 오류가 발생하거나 코드의 가독성이 떨어질 수 있습니다. 전역 변수는 프로그램 어디에서든 수정될 수 있기 때문에, 최대한 사용을 자제하고 불가피하게 사용해야 할 경우에는 변수 이름을 명확하게 지정하여 다른 변수와 구분되도록 하는 것이 좋습니다. 중첩된 함수에서 변수를 공유할 때는 nonlocal 키워드를 사용하여 변수의 scope를 명확하게 지정해 주어야 합니다. 5. 다양한 프로그래밍 언어에서의 Scope Scope는 프로그래밍 언어마다 조금씩 다른 방식으로 구현됩니다. 몇 가지 인기 있는 프로그래밍 언어에서 scope가 어떻게 구현되는지 간략하게 살펴보겠습니다. 5.1 Python Python은 앞에서 설명한 대로 LEGB 규칙을 사용하여 변수의 scope를 결정합니다. Python은 동적인 scope를 사용하기 때문에, 함수가 호출될 때가 아니라 함수가 정의될 때 변수의 scope가 결정됩니다. 5.2 JavaScript JavaScript는 var, let, const 키워드를 사용하여 변수를 선언하며, 각 키워드는 각기 다른 scope 규칙을 가집니다. var: 함수 scope를 가집니다. 함수 내에서 선언된 var 변수는 함수 내 어디에서든 접근 가능합니다. let과 const: 블록 scope를 가집니다. 블록 scope는 중괄호 {}로 둘러싸인 코드 블록 내부를 의미합니다. let이나 const로 선언된 변수는 해당 코드 블록 내부에서만 접근 가능합니다. 5.3 Java Java는 정적인 scope를 사용하며, 변수의 scope는 변수가 선언된 위치에 따라 컴파일 시점에 결정됩니다. Java는 블록 scope를 사용하기 때문에, let이나 const로 선언된 변수는 해당 코드 블록 내부에서만 접근 가능합니다. 결론 지금까지 프로그래밍에서 ‘scope’의 중요성과 다양한 측면에 대해 자세히 알아보았습니다. Scope는 변수의 유효 범위를 결정하는 중요한 개념이며, 이를 통해 변수 이름 충돌을 방지하고, 메모리를 효율적으로 관리하며, 코드의 가독성과 유지보수성을 향상시킬 수 있습니다. 프로그래밍 초보자들은 scope 개념을 정확히 이해하고, 코드 작성 시 이를 적용하여 안전하고 효율적인 프로그램을 개발할 수 있도록 노력해야 합니다. 목차 Toggle 1. Scope란 무엇인가요?2. Scope가 중요한 이유는 무엇인가요?2.1 변수 이름 충돌 방지2.2 메모리 관리 효율화2.3 코드 가독성 및 유지보수 향상3. 다양한 Scope의 종류3.1 전역 Scope (Global Scope)3.2 지역 Scope (Local Scope)3.3 비지역 Scope (Nonlocal Scope)4. Scope 관련 추가 정보4.1 LEGB 규칙4.2 Scope 관련 주의사항5. 다양한 프로그래밍 언어에서의 Scope5.1 Python5.2 JavaScript5.3 Java결론 post