본문 바로가기
IT/프로그래밍 노트

026 Scope , Global Scope 글로벌 스코프, Local Scope 로컬 스코프

by 33.0 2025. 3. 12.
728x90

scope

코드의 범위, 코드의 구역 을 나타내는 말

코드는 여러개의 구역으로 구분되어 있다. 

구역은 어디에서 인식하는지 어디에서 접근하는지 메모리에 저장한 값이 언제까지 유효한지 결정하는 역할을 한다.  

import UIKit

//1. Global Scope
let g1 = 123
// 이제 1번 안에서 g1 을 다시 선언할 수 없다.
// print(local1) 불가능
let g3 = M_LOG2E

class ViewController: UIViewController {
 // 6.
    override func viewDidLoad() {
        super.viewDidLoad()
        // 3. Local Scope
        let local1 = 123
                // print(local2)불가능
        print(g1) //가장 인접한 스코프는 밑에있는 선언이지만 아직 선언하기 전이니 글로브 스코프 값인 "123" 출력
        let g1 = 789
        
        print(g1) //가장 인접한 스코프인 "789" 출력
        
        if true {
            // 4. Local Scope, 하위 로컬 스코프
            let local3 = 789
            print(local1)
        }
        //5 3번과 같은 스코프
        let local2 = 456
    }
    //7
    func doSomething(value: Int?) {
        if let local1 = value {
            // 바인딩이 성공한 시점에 상수가 만들어지고 if 블록 안에서만 사용 가능 if 블록 실행이 끝나면 사라진다.
            print(local1)
        }
        // print(local1) 불가능
        guard let local2 = value else {
            print("nil")
            return
        }// guard let은 바인딩 성공하면 뒤쪽부터 가드문이 포함된 스코프의 마지막까지만 접근할 수 있음. if로 바인딩하는 경우와 스코프가 다름.
        print(local2)
        
        for num in 1 ... 100 {
            // 여기서 만들어진 루프상수는 for문 바디에서만 접근 가능함.
            // 반복할 때마다 루프상수가 새롭게 만들어짐 for문이 끝나면 메모리에 루프상수가 남지 않음. 바디에서만 사용 가능
        }
        guard let value else{
            return
        }
        
        print(value) //여기서 호출하고 있는 value는 guard문의 value이다. do Something의 파라미터인 value는 53번 라인까지만 사용가능 하고 guardlet {}이후에는 바인딩된 value라는 식별자로 사용된다.
        
    }

}

// 2. 1과 위치가 떨어져 있지만 1과 같은 스코프 , 여기서 g1을 선언하면 컴파일에러 발생. invalid redeclaration of 'g1' - 잘못된 재정의

let g2 = 456

Global Scope 전역범위

스코프 구분 기준은 {} 이다. 

하나밖에 없다. {} 밖에 있는 범위를 말한다. 

 

Local Scope 지역범위 

{} 안에 있는 범위 여러단계로 중첩이 가능해 여러개의 

블록스코프 펑션스코프 등 세분화 가능하다. 

 

Scope 사용 규칙 

스코프 사이에 규칙이 있다. 

 

1️⃣ 동일한 스코프에 접근할 수 있다.

2️⃣ 글로벌 스코프에서 선언한 값은 선언 순서에 상관없이 어느 위치에서나 접근 가능하다.

 

3️⃣ 로컬 스코프에서 상위 스코프나 글로벌 스코프에 접근할 수 있다.

 

클래스, 스트럭트, 이넘, 익스텐션, 프로토콜 같은 키워드 다음에 첫번째로 오는 스코프 안에는 속성, 메서드, 생성자등의 멤버 선언만 올 수 있다.

6번 위치의 스코프는 문법 규칙에 따라 값을 선언해야하는 스코프인데 print , present 같은 코드가 오면 실행되지 않는다.

6번과 같은 위치는 로컬스코프로 분류되지 않는다. 선언만 해야하는 스코프이다.  클래스 스코프라고 불리는데 선생님은 선언스코프나 타입스코프라고 부른다고 한다.

 

4️⃣ 글로벌 스코프가 아니라면 이미 선언되어 있는 요소에만 접근할 수 있다.

 print(local2) 를 5번위치에서 선언했다면 4번 위치에서 접근 불가능하다. 
 

5️⃣ 상위 스코프는 하위 스코프에 접근할 수 없다.

 글로벌 스코프에서 로컬 스코프에 접근 3번에서 선언된 상수에 접근하려면 불가능.

 

 4번이 하위 스코프이기 때문에 5번에서 print(local3) 안된다.

 4번 스코프의 {}이 끝나는 시점에서 메모리에 저장된 local3가 사라진다.

 시각적으로 하위스코프가 위에 있는 느낌이라 접근 할 수 있게 생겼는데 상위스코프에서 접근하고자 하면 안된다. 속으면 안된다. 

 

선언된 상수 등이 사라지는 시점을 잘 봐야한다. 

✔️ local1, local2 는 viewDidLoad 메서드의 실행이 끝나는 시점에 사라진다.

✔️ g1,g2같은 글로벌 스코프에서 선언된 값은 프로그램이 끝나면 사라진다.

✔️doSomething의 value 파라미터는 메서드가 호출되는 시점에 만들어졌다가 메소드의 실행이 끝나면 바로 사라진다.

✔️ if let 으로 바인딩한 상수는 if블록 안에서만 접근 가능, 바인딩이 성공한 시점에 상수가 만들어지고 if블록 안에서 사용, if 블록이 끝나면 사라진다. 

✔️ guard let은 바인딩에 실패하면 else블록이 실행되기 때문에 else 블록에서는 상수에 접근할 수 없다.

바인딩 성공하면 else블록 끝부터 가드문이 포함된 스코프(가드문의 상위스코프)의 마지막까지만 접근할 수 있음.

if로 바인딩하는 경우와 스코프가 다름.

✔️ for문에서 만들어진 루프상수는 for문 바디에서만 접근 가능
매 회차 반복할 때마다 루프상수가 새롭게 만들어진다. 회차의 반복이 끝나면 바로 사라진다. 새로운 회차가 시작되면 다시 만들어진다.

매번 for문이 끝나면 메모리에 루프상수가 남지 않아 for문의 바디에서만 사용 가능하다.

✔️

 

6️⃣ 서로 다른 스코프에 동일한 이름이 존재한다면 가장 가까운 (인접한) 스코프에 있는 이름을 사용한다.

동일한 스코프 내에서 식별자는 같을 수 없다.  스코프가 다르면 식별자가 달라도 문제 없다.

3번과 7번은 각자 독립적인 local1 이라 서로 접근 불가능, 같은 이름을 사용해도 문제 없음

단, 선언순서에 영향을 받는다. 선언하기 전에 식별자의 이름을 사용한다면 앞서 선언된 것들 중 가장 인접한 스코프의 식별자를 사용한다. 

 

 

7️⃣ 글로벌 스코프가 아닌 다른 모든 스코프는 시작과 끝이 명확해야 한다.

스코프를 복사, 붙여넣기를 할 때 꼭 {} 의 모양을 유지하면서 복사하는게 좋다. 

 

728x90