사전 스코프
용어함정

스코프

gabury1고친 사람 github-actions[bot]

스코프는 이름이나 권한이 미치는 범위에 선을 긋습니다. 그런데 무엇에 선을 긋느냐에 따라 다른 것을 가리킵니다. 프로그램 안에서는 짧은 이름을 어디서 찾을지 정하는 코드 구간을 가리킵니다. 접근을 위임할 때는 내준 권한이 어디까지 통하는지를 가리킵니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 이름이나 권한이 어디까지 미치는지 그어 두는 경계입니다. 함수 안에서만 쓰는 변수의 경계도 스코프이고, 앱에 내준 "읽기만" 권한의 경계도 스코프입니다. 이 둘은 이름만 같고 서로 이어지지 않습니다.

왜 이렇게 하나 — 이름은 여러 곳에서 같은 글자를 다시 쓰게 되므로 어디서 찾을지 정해 둬야 헷갈리지 않습니다. 권한은 내준 것보다 더 많은 일을 하게 두면 위험하므로 어디까지 되는지 못 박아야 합니다.

어떻게 도나

이름은: 1) 프로그램이 짧은 이름을 만나면 지금 도는 구간부터 바깥으로 훑어 그 이름을 찾습니다.

권한은: 1) 접근을 요청하는 쪽이 원하는 권한 목록을 스코프 값으로 적어 보내면, 2) 권한을 내주는 쪽이 그 목록의 전부 또는 일부만 골라 내줍니다.

언제 쓰고 언제 안 쓰나 — 이름의 스코프는 언어가 늘 강제하므로 켜고 끄는 선택이 아닙니다. 권한의 스코프는 접근을 위임하는 설계라면 언제나 정해야 하고, 좁게 잡을수록 안전합니다.

대가 — 이름의 스코프를 안 지키면 다른 함수의 변수를 실수로 건드리게 됩니다. 권한의 스코프를 너무 넓게 내주면 그 권한이 새어 나갔을 때 피해가 커집니다.

상세

이 절은 스코프가 가리키는 두 가지를 나란히 놓고 봅니다. 먼저 두 뜻을 표로 가릅니다. 그다음 프로그램 안의 스코프와 접근 위임의 스코프를 차례로 따라갑니다. 끝에서는 이름이 겹치는 다른 쓰임을 짧게 짚습니다.

스코프가 가리키는 두 범위

맥락 스코프가 긋는 범위 예
프로그램 언어 짧은 이름을 찾아볼 코드 구간 함수 본문 · 블록 · 파일 전체
접근 위임 내준 권한이 미치는 한도 "읽기만" · "쓰기까지"

백엔드 개발자가 코드를 짤 때 자주 만나는 것은 첫 줄입니다. API(Application Programming Interface, 응용 프로그래밍 인터페이스)를 설계하거나 붙일 때 자주 만나는 것은 둘째 줄입니다.

이름을 풀 때 — 코드 구간으로서의 스코프

프로그램은 같은 이름을 여러 군데서 다시 씁니다. 함수마다 total 이라는 변수를 두어도 서로 안 부딪히려면, 그 이름을 어느 구간 안에서 찾을지 정해야 합니다. 이 구간이 스코프입니다.

스코프는 겹쳐서 놓입니다. 함수 안에 또 함수를 두면 안쪽 스코프가 바깥 스코프 안에 놓입니다. 프로그램은 이름을 찾을 때 지금 도는 스코프부터 봅니다. 없으면 한 겹씩 바깥으로 나가며 찾습니다. 맨 바깥까지 가도 없으면 그제야 이름을 못 찾았다고 답합니다.

Python
x = 1          # 전역 스코프의 x
def f():
    x = 2      # 함수 f 스코프의 새 x
    print(x)   # 2
f()
print(x)       # 1

f 안에서 x = 2 를 쓰면 전역의 x 가 바뀌는 것이 아닙니다. f 스코프 안에 새 x 가 하나 더 생기는 것입니다. f 를 부르는 동안은 안쪽 x 가 보입니다. f 가 끝나면 그 x 는 사라집니다. 바깥의 x 는 손대지 않은 채 1로 남습니다.

flowchart TD
    subgraph G["전역 스코프"]
        GX["x = 1"]
        subgraph F["함수 f 의 스코프"]
            FZ["z 를 찾는다"]
        end
    end
    FZ -->|없으면 바깥으로| GX

함수 f 가 z 를 찾다가 못 찾으면 전역 스코프로 나갑니다. 이렇게 겹친 스코프를 따라 이름을 찾는 순서를 렉시컬 스코프라고 부릅니다. 어디서 불렸는지가 아니라 코드가 어디에 적혔는지로 순서가 정해지기 때문입니다.

이름이 겹치는 경우도 있습니다. 안쪽 스코프에 바깥과 같은 이름을 새로 두면, 안쪽에 있는 동안은 안쪽 것만 보입니다. 이것을 섀도잉이라고 부릅니다. 바깥 이름을 지운 것이 아니라 잠깐 가린 것입니다. 안쪽 스코프를 벗어나면 바깥 이름이 다시 보입니다.

함수가 자기 스코프를 벗어난 뒤에도 그 스코프의 변수를 계속 붙들고 있는 경우가 있습니다. 이런 함수를 클로저라고 부릅니다. 스코프가 함수 호출이 끝나면 같이 사라진다는 규칙에 어긋나 보입니다. 하지만 그 변수를 아직 붙든 함수가 있는 동안은, 그 스코프도 살아 있는 것으로 봅니다.

네임스페이스와 헷갈리기 쉽습니다. 스코프는 짧은 이름을 어느 구간에서 풀지 정해 주는 코드 구간입니다. 네임스페이스는 그 구간이 뒤지는 이름 표입니다. 함수 본문이 스코프이면, 그 함수가 아는 이름들을 담은 표가 네임스페이스입니다. 둘은 겹쳐서 돌지만 서로를 대신하지 않습니다.

권한을 내줄 때 — 위임 범위로서의 스코프

시스템 하나가 다른 시스템에게 자기 자원을 만지도록 권한을 내줄 때가 있습니다. 이때 무엇까지 허락하는지 적은 목록이 스코프입니다. 권한을 요청하는 쪽은 클라이언트, 권한을 내주는 쪽은 인가 서버, 그 권한대로 자원을 지키는 쪽은 자원 서버입니다.

사진 앱에는 캘린더 읽기 권한만 내주고 싶습니다. 그런데 전체 계정 권한을 통째로 내주면, 그 앱이 뚫렸을 때 잃는 것이 계정 전체가 됩니다. 이렇게 필요한 만큼만 내주는 원칙이 최소 권한입니다. 스코프는 접근 제어에서 이 원칙을 실제로 구현하는 수단입니다.

sequenceDiagram
    participant 클라이언트
    participant 인가 서버
    participant 자원 서버
    클라이언트->>인가 서버: 읽기·쓰기 스코프를 요청한다
    Note over 인가 서버: 정책을 보고 일부만 내주기로 정한다
    인가 서버-->>클라이언트: 읽기 스코프만 담은 토큰
    클라이언트->>자원 서버: 그 토큰으로 읽기만 요청한다

요청하는 쪽은 원하는 스코프를 적어 보냅니다. 내주는 쪽이 그것을 전부 그대로 내줄 의무는 없습니다. 정책에 따라 일부만 내줍니다. 그리고 실제로 내준 스코프를 응답에 다시 적어 알려 줍니다. 받는 쪽은 요청한 것이 아니라 응답에 적힌 스코프만 믿고 움직여야 합니다.

내준 스코프는 토큰 안에 담겨 옮겨 다닙니다. 이 토큰이 액세스 토큰입니다. 자원 서버는 요청이 들어오면 그 토큰의 스코프를 봅니다. 하려는 일이 그 안에 있는지 확인하고, 범위 밖의 일을 시키면 거부합니다. 이런 방식으로 스코프를 쓰는 접근 위임 표준이 여럿 있습니다.

이름이 겹치는 다른 쓰임

관측 지표를 잴 때도 스코프라는 말을 씁니다. 서비스 수준 목표와 서비스 수준 지표 문서는 지표 하나를 클러스터 전체로 잴지, 이름 공간 하나로 좁혀 잴지를 스코프라고 부릅니다. 이 쓰임은 앞의 두 뜻과도 다시 다른 뜻입니다. 앞뒤 문맥을 보고 가려야 합니다.

어느 뜻인지 가르는 단서

함께 나오는 말 뜻
함수 · 변수 · 블록 · 이름을 못 찾는다 · 클로저 코드 구간
토큰 · 권한 · 인가 · OAuth · 읽기만 / 쓰기까지 위임 범위
클러스터 · 이름 공간 · 지표 관측 범위

관련 항목

이름 해석에 관여하는 개념

네임스페이스 · 클로저 · 전역 변수 · 지역 변수 · 섀도잉

접근 위임에 관여하는 개념

접근 제어 · 인가 · 권한 · 최소 권한 · OAuth 2.0

권한 위임을 주고받는 당사자

클라이언트 · 인가 서버 · 자원 서버 · 자원 소유자

스코프 값을 실어 나르는 토큰

액세스 토큰 · 토큰 · 리프레시 토큰

스코프와 이름이 겹치는 다른 개념

서비스 수준 목표 · 서비스 수준 지표 · 세션

다른 이름: scope