3.3.7 변수의 유효 범위 (Scope와 Global)

학습목표

본 장에서는 함수 내부 코드와 바깥세상을 엄격히 철창으로 가로막는 메모리 방화벽인 ‘변수의 유효 범위(Scope)’ 개념을 익힙니다. 굳게 닫힌 밀실 문을 부수고 전 지역을 통치하는 global 키워드의 작동 원리와 그 치명적인 위험성을 함께 파악합니다.


1. 지역 변수(Local)와 전역 변수(Global)의 격리 생태계

일반적으로 함수(def) 안에 선언된 변수들은 바깥의 세상(전역 공간)에 전혀 영향을 주지 않고 철저하게 고립되어 태어났다가 죽습니다.

  • 전역 변수 (Global Variable): 코드 파일 전체(함수 바깥)에 노출되어, 파일 내 어디서든(심지어 함수 안에서도 읽는 것은 가능하게) 볼 수 있는 광역 생태계 변수입니다.
  • 지역 변수 (Local Variable): 특정 함수라는 작고 좁은 ‘밀실 안에서만’ 잠시 만들어져 쓰이다가, 함수가 일이 끝나고 return으로 방을 폭파시킬 때 흔적도 없이 함께 소멸해 버리는 일회용 변수입니다.

Local vs Global Scope 웹툰

💡 웹툰 비유: 왼쪽 창밖에는 거대한 성(Global Scope) 안의 왕좌에 전역 변수 왕(x=100)이 군림하며 천하를 호령합니다. 반면 오른쪽에는 좁고 임시로 세운 텐트(Local Scope 함수 텐트) 안에서 동명이인의 일꾼 지역 변수(x=10)가 땀을 뻘뻘 흘립니다. 이 텐트 안의 일은 바깥 왕에게는 전혀 보이지 않고, 함수 호출이 끝나면 이 텐트와 일꾼은 흔적도 없이 파괴됩니다.

Local Scope 생명주기 애니메이션

💡 다이어그램: 메인 프로그램 실행 중에 함수가 호출되면, 잠시동안만 반짝하고 살아나는 파란색 ‘Local x:10’ 블록의 생명주기와 소멸(Garbage Collection) 과정을 보여주는 애니메이션입니다. 이 두 x는 이름만 같을 뿐 철저한 격리벽(X 다름 X)으로 차단되어 있습니다.

x = 100  # 이 녀석은 파일 전체를 호령하는 '전역 변수'입니다.

def secret_room():
    # 이 x는 바깥의 전역 변수 x와 이름만 우연히 똑같을 뿐, 
    # 완전히 별개의 메모리에서 태어난 동명이인 '지역 변수'입니다!
    x = 10 
    print(f"밀실 내부의 x: {x}")  # 10 출력

secret_room()
# 밀실이 터지면서 내부의 10은 허공으로 사라졌습니다.
print(f"바깥세상의 x: {x}") # 여전히 100 출력 (바깥쪽 x는 전혀 상처입지 않음)

이러한 격리(Isolation)는 프로그램이 거대해질 때, 내가 만든 함수의 내부 로직이 남이 만든 함수나 프로그램 전체의 변수를 실수로 덮어씌워 오염시키는 재앙을 완벽하게 막아주는 최고의 방어벽입니다.


2. 전역 변수를 강제로 조종하는 만능 열쇠, global 키워드

함수는 블랙박스처럼 바깥세상과 단절(격리)되는 것이 원칙이지만, 간혹 함수 안의 복잡한 로직을 타고 난 뒤 함수 바깥 스코프에 있는 전역 변수의 상태를 물리적으로 꼭 영구히 수정해야 하는 예외적인 요구 사항이 발생할 때가 있습니다. (예: 게임 진행도 누적 저장, 전체 시스템의 누적 방문자 수 카운트)

이럴 때는 함수 내부에서 global 키워드를 선언하여 “지금부터 내가 다룰 변수 x는, 밀실 내부에서 새로 탄생시키는 쪼렙 지역 변수가 아니라 저 바깥세상을 통치하는 진짜 전역 변수 x 본체를 직접 원격 조종하겠다!” 라고 파이썬에게 선포해야만 합니다.

Global Keyword 오버라이드 애니메이션

💡 다이어그램: 함수 내부에 global hp 선언을 하면 밀실의 철창 방어벽이 무너지고, 바깥세상의 hp 500 원본 데이터와 해킹 파이프 라인이 다이렉트로 연결(Direct Override)되어, 함수 내부의 데미지 연산 결과가 바깥세상의 원본 수치를 영구적으로 깎아버리는(430) 치명적 부작용(?)을 묘사한 애니메이션입니다.

monster_hp = 500 # 전역 변수

def power_attack():
    global monster_hp # 바깥세상의 monster_hp와 영혼을 동기화하는 만능 열쇠!
    
    damage = 70       # 이 damage는 밀실 안에서만 쓰이는 착한 지역 변수
    monster_hp -= damage
    print(f"⚔️ 쾅! 내부에서 타격. 남은 체력: {monster_hp}") 

power_attack()
power_attack()
print(f"바깥에서도 영구적으로 다쳐버린 몬스터 체력: {monster_hp}")

# [출력 결과]
# ⚔️ 쾅! 내부에서 타격. 남은 체력: 430
# ⚔️ 쾅! 내부에서 타격. 남은 체력: 360
# 바깥에서도 영구적으로 다쳐버린 몬스터 체력: 360

🚨 global의 치명적 위험성 (안티 패턴)

global을 남발하면 함수가 블랙박스로서의 무결성을 잃어버립니다. 함수 바깥의 변수 상태를 언제 어디서 몰래 찔러서 변형시켰는지 추적하기가 불가능해져서, 코드가 이른바 ‘스파게티 오염 코드’가 되어버립니다. 따라서 현대 프로그래밍에서는 global로 바깥 변수를 직접 훼손하기보다는, 깔끔하게 결과를 반환(return)받아서 바깥에서 변수를 덮어쓰는(재할당) 방식을 훨씬 안전하게 권장합니다.


🎧 Vibe Coding

🗣️ 학생 프롬프트 (AI에게 이렇게 명령해 보세요): “파이썬의 지역 변수(Local)와 전역 변수(Global)의 차이가 너무 헷갈려. 금고 안에 있는 돈(지역)과 은행에 있는 돈(전역)으로 비유해서, 왜 아무 조치 없이 함수 안에서 바깥에 있는 돈을 마음대로 수정하려고 하면 에러(UnboundLocalError)가 나는지 뼈저리게 느낄 수 있는 나쁜 예시 코드와, 그것을 global로 해결한 코드를 나란히 시뮬레이션해 줘.”


코딩 영단어 학습 📝

  • Scope: 시야, 범위, 영역. (저격총의 스코프처럼 ‘내 눈(메모리)이 닿아서 변수를 읽고 다룰 수 있는 유효 반경 범위’를 뜻하는 핵심 용어입니다.)
  • Global: 전 세계적인, 전반적인, 전역의. (프로그램 생태계 전체를 호령하는 범우주적인 바깥쪽 메모리 공간입니다.)
  • Local: 지역의, 현지의. (함수라는 작고 좁은 방구석 한정으로만 잠시 존재했다 소멸해버리는 찰나의 휘발성 메모리 공간입니다.)
  • Isolation: 고립, 격리. (병원에서 병균을 격리하듯, 함수 내부의 코드가 바깥 시스템을 오염시키지 않도록 철창에 가두는 훌륭한 공학적 기법입니다.)
서브목차