- Global variables (전역 변수)
반복문 안에서 전역 변수를 바꾸면 바뀌어질까?
- def (함수) 안이 아닌 경우: 아무런 제약 없이 바로 바꿀 수 있다.
파이썬의
for나while문은 자신만의 ‘공간(Scope)‘을 따로 만들지 않기 때문.
score = 0 # 전역 변수
for i in range(5):
score += 10 # 그냥 바로 수정 가능
print(score) # 결과: 502-1) def (함수) 안 일반적인 경우:
global 키워드가 필요, 없으면 에러(UnboundLocalError) → 값을 주고받을 때 함수를 호출하는 것이 더욱 안정적
total = 0
def add_points():
global total # "이 변수는 밖에 있는 전역 변수 total을 쓸 거야"라고 선언
for _ in range(3):
total += 1
add_points()
print(total) # 결과: 3 (정상적으로 바뀜)2-2) def (함수) 안 변경 가능 (Mutable) 객체의 경우:
list, dict: global 없이 특정 함수 사용 (append(), pop() 등)할 수 있다.
#### 단, `cart = [1, 2]` 처럼 리스트 자체를 아예 통째로 갈아끼울 때는 `global`이 필요!
cart = [] # 리스트 (전역 변수)
def add_items():
items = ["사과", "배"]
for item in items:
cart.append(item) # global 키워드 없어도 내용 추가 가능
add_items()
print(cart) # 결과: ['사과', '배']2. 함수 호출하여 값 주고 받기
전역 변수(Global Variable) 대신 함수 호출(파라미터 전달, 리턴값, 또는 Getter/Setter)을 사용하라는 조언은 프로그램의 안정성과 유지보수성을 높이기 위한 가장 기초적이면서 중요한 원칙입니다.
이 둘의 관계는 **“데이터에 어떻게 접근하고, 데이터를 어떻게 관리할 것인가”**에 대한 차이에서 옵니다. 그 이유와 구체적인 차이점을 정리해 드립니다.
1. 전역 변수 vs 함수 호출: 무엇이 다른가요?
가장 큰 차이는 **데이터의 흐름이 눈에 보이는가(명시적인가)**입니다.
-
전역 변수 사용: “어디서든 문을 열고 들어와서 물건을 가져가거나 바꿀 수 있는 창고”와 같습니다. 누가 언제 물건을 바꿨는지 알기 어렵습니다.
-
함수 호출 사용: “창고지기에게 정식으로 요청서를 내고 물건을 받는 것”과 같습니다. 누가 요청했고, 무엇을 주었는지 기록(흐름)이 남습니다.
2. 왜 전역 변수 대신 함수 호출을 쓰라고 할까요?
전역 변수를 쓰면 편해 보이지만, 다음과 같은 심각한 문제가 발생합니다. 함수 호출(인자 전달)은 이 문제를 해결합니다.
① 추적의 어려움 (Side Effect)
-
전역 변수: 프로그램 내의 어떤 함수든 전역 변수 값을 바꿀 수 있습니다. 버그가 생겼을 때, 수십 개의 함수 중 누가 범인인지 찾기 매우 어렵습니다.
-
함수 호출: 데이터를 인자(Argument)로 넘겨주고 리턴값으로 받으면, 데이터가 변하는 과정이 함수 호출 흐름을 따라 명확하게 보입니다.
② 결합도(Coupling) 증가
-
전역 변수: 함수가 전역 변수에 의존하게 되면, 그 전역 변수가 없으면 함수가 작동하지 않습니다. 다른 프로젝트에 그 함수만 떼어가서 재사용하기가 불가능해집니다.
-
함수 호출: 함수가 필요한 데이터를 파라미터로만 받는다면, 그 함수는 독립적입니다. 어디든 쉽게 옮겨서 재사용할 수 있습니다.
③ 테스트의 어려움
-
전역 변수: 테스트를 할 때마다 전역 변수의 상태를 매번 초기화해줘야 합니다.
-
함수 호출: 단순히 입력값만 넣어주면 출력값이 나오는지 확인하면 되므로 테스트가 훨씬 쉽습니다.
3. 코드 비교: 전역 변수 vs 함수 호출
상황: 게임 점수를 올리는 기능을 만든다고 가정해 봅시다.
❌ 나쁜 예: 전역 변수 사용
데이터가 암묵적으로 연결되어 있어, update_score만 보면 total_score가 필요한지 알 수 없습니다.
Python
total_score = 0 # 전역 변수
def update_score():
global total_score
# 함수 내부에서 외부 변수를 몰래(?) 바꿈
total_score += 10
update_score()
print(total_score) # 10
✅ 좋은 예: 함수 호출 (파라미터와 리턴)
데이터가 명시적으로 들어오고 나갑니다. 이 함수는 외부 상황과 상관없이 입력이 들어오면 결과를 뱉을 뿐입니다.
Python
def calculate_new_score(current_score):
# 외부 변수 의존 없이, 입력받은 값만 가지고 계산
return current_score + 10
my_score = 0
# 함수를 '호출'해서 값을 주고 받음
my_score = calculate_new_score(my_score)
print(my_score) # 10
4. “전역 변수 대신 호출해서 써라”의 실질적 의미
조언해주신 분의 의도는 아마 다음 두 가지 중 하나일 것입니다.
-
파라미터로 넘겨라 (Dependency Injection):
- 변수를 전역에 두지 말고,
main함수나 상위 로직에서 변수를 만든 뒤 필요한 함수에 인자(Parameter)로 던져주세요.
- 변수를 전역에 두지 말고,
-
Getter/Setter를 써라 (Encapsulation):
- 변수를 어떤 클래스나 모듈 안에 숨겨두고(private), 값을 읽거나 바꿀 때는 반드시 함수(
get_data(),set_data())를 통해서만 접근하게 하세요. 이렇게 하면 잘못된 값이 들어오는 것을 함수 안에서 막을 수 있습니다.
- 변수를 어떤 클래스나 모듈 안에 숨겨두고(private), 값을 읽거나 바꿀 때는 반드시 함수(