- Global variables (전역 변수)

반복문 안에서 전역 변수를 바꾸면 바뀌어질까?

  1. def (함수) 안이 아닌 경우: 아무런 제약 없이 바로 바꿀 수 있다. 파이썬의 forwhile문은 자신만의 ‘공간(Scope)‘을 따로 만들지 않기 때문.
score = 0  # 전역 변수
 
for i in range(5):
    score += 10  # 그냥 바로 수정 가능
 
print(score)  # 결과: 50

2-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. “전역 변수 대신 호출해서 써라”의 실질적 의미

조언해주신 분의 의도는 아마 다음 두 가지 중 하나일 것입니다.

  1. 파라미터로 넘겨라 (Dependency Injection):

    • 변수를 전역에 두지 말고, main 함수나 상위 로직에서 변수를 만든 뒤 필요한 함수에 인자(Parameter)로 던져주세요.
  2. Getter/Setter를 써라 (Encapsulation):

    • 변수를 어떤 클래스나 모듈 안에 숨겨두고(private), 값을 읽거나 바꿀 때는 반드시 함수(get_data(), set_data())를 통해서만 접근하게 하세요. 이렇게 하면 잘못된 값이 들어오는 것을 함수 안에서 막을 수 있습니다.