[코딩] 초보 코더 탈출을 위한 꿀팁, 최소 가시성

@codemaru · July 02, 2025 · 5 min read

코드를 머지하려고 보면 참 기분 좋은 경우가 있는가 하면, "이게 뭐지?!" 하는 생각이 절로 드는 경우도 있다. 내가 코드를 보면서 초보와 초보가 아님을 가르는 가장 큰 기준 중 하나가 바로 '가시성(Visibility)', 즉 '스코프(Scope)'다.

스코프란 프로그램 전체에서 해당 변수나 함수가 어디까지 노출될지를 결정하는 거라고 보면 된다. 이런 설정이 잘 된 코드는 일단 기본기가 탄탄하다는 느낌을 주지만, 이게 엉망인 코드는 보는 내내 불안감과 의문을 던져준다.

#0

요즘 많이 쓰는 파이썬 코드로 시작해보자.

global_variable = 1           # 1. 전역 변수

class OneBigBeautifulClass:
  class_variable = 2          # 2. 클래스 변수

  def __init__(self):
    self.member_variable = 3  # 3. 인스턴스 변수

  def plus(self, a, b):
    local_variable = a + b    # 4. 지역 변수
    return local_variable

여기엔 크게 4가지 변수가 있다. global_variable, class_variable, member_variable, local_variable이 그것이다. 순서대로 스코프 범위가 넓다.

  • 전역 변수: 이 코드 전체, 어디서든 참조할 수 있다.
  • 클래스 변수: 인스턴스와 관계없이 해당 클래스 전체에서 참조된다.
  • 인스턴스 변수: 생성된 인스턴스로 범위가 제한된다. (self.)
  • 지역 변수: plus 함수 내에서만 목숨이 붙어있다.

#1

이 코드를 보면 간단한 원리를 발견할 수 있다. 대체로 넓은 범위의 변수는 좁은 범위의 변수 기능을 대체할 수 있다는 점이다. 즉, 전역 변수로 지역 변수가 할 일을 시켜도 코드는 일단 돌아간다.

# [예시 1] 일단은 문제 없이 동작한다
global_variable2 = 0

class OneBigBeautifulClass:
  def plus(self, a, b):
    global global_variable2
    global_variable2 = a + b
    return global_variable2

하지만 그 반대는 안 된다. 지역 변수가 전역 변수를 대체할 수는 없다.

# [예시 2] 당연히 동작하지 않는다
class OneBigBeautifulClass:
  def plus(self, a, b):
    local_variable = a + b
    return local_variable

print(local_variable) # 에러 발생

넓은 범위로 확장이 가능하기에, 초보 코더가 작성한 코드를 보면 필요 이상으로 스코프를 크게 잡는 문제가 생긴다. 지역 변수로 써도 될 것을 굳이 멤버 변수로, 클래스 변수로, 심지어 전역 변수로 쓰는 것이다.

"돌아가면 장땡 아니냐?" 할 수 있다. 하지만 변수든 함수든 범위가 넓다는 건 그만큼 조심해야 할 게 많다는 의미다. 집 안에서는 알몸으로 돌아다녀도 뭐라 할 사람이 없지만, 집 밖으로 나올 때는 주의해야 하는 거랑 같은 원리다. 스코프가 넓은 변수는 여기저기서 의도치 않게 건드려질 수 있는 위험에 항상 노출된다.

#2

초보 티를 벗기 위해 명심해야 할 한 가지는 최소 가시성 원칙이다. 내가 만들 변수나 함수의 가시성은 '최소한'이 되도록 설정하면 대체로 그게 맞다는 말이다.

전역 변수를 썼는데 생각해보니 지역 변수로도 될 것 같다? 그럼 지역 변수로 바꾸는 게 맞다. 멤버 변수(self.변수)로 썼는데, 한 함수 안에서만 쓰고 만다? 그럼 지역 변수로 하는 게 맞다.

아래 코드를 보자. self.member_variable은 오직 plus 함수 안에서만 사용된다.

class OneBigBeautifulClass:
  def __init__(self):
    self.member_variable = 0

  def plus(self, a, b):
    self.member_variable = a + b
    return self.member_variable

이럴 땐 굳이 인스턴스 전체가 공유하는 멤버 변수로 둘 필요가 없다. 아래처럼 바꾸는 것이 훨씬 안정적이고 좋은 코드다.

# [더 좋은 코드]
class OneBigBeautifulClass:
  def __init__(self):
    pass

  def plus(self, a, b):
    local_variable = a + b # plus 함수에서만 쓸 변수이므로 지역 변수로
    return local_variable

이처럼 변수의 스코프를 필요한 만큼만 최소한으로 부여하는 습관, 이것만으로도 코드의 품질은 훨씬 좋아진다.

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중