개발을 시작하는 이야기

접근제어는 왜 사용해야 할까? 본문

개발 이야기/Swift

접근제어는 왜 사용해야 할까?

Teiresias 2022. 4. 15. 18:31
접근제어가 있다는 건 알고 있지만, 이걸 사용하지 않아도 잘 작동하는데 굳이 왜 사용해야 하는지, 사용한다면 어떤 식으로 어느 정도 수준까지 사용해야 하는지 알아보고 내 앱에 적용하기 위해 작성함.

 

객체지향 프로그래밍 패러다임에서 캡슐화와 은닉화는 중요한 개념 중 하나이고, 이를 구현하기 위한 핵심 기능이 접근제어라고 한다. 캡슐화와 은닉화를 구현하는 이유는 외부에서 보거나 접근하면 안 되는 코드가 있기 때문이다. 불필요한 접근으로 의도치 않는 결과를 초래하거나 꼭 필요한 부분만을 제공해야 하는데 전체 코드가 노출될 가능성이 있을 때 접근제어를 이용한다. 

 

접근제어는 접근수준 키워드를 통해 구현할 수 있는데, 각 타입(클래스, 구조체, 열거형 등)에 특정 접근 수준을 부여할 수 있고, 타입 내부의 프로퍼티, 메서드, 이니셜 라이져, 서브 스크립트 각각에도 접근 수준을 지정할 수 있다. 접근 수준을 명시할 수 있는 키워드는 아래 다섯 가지가 있다. 각각의 기능들의 설명은 아래 접힌글에 정리되어있다.

 

이미지 출처 : https://samwize.com/2017/04/20/access-levels-in-swift

 

더보기

open

  • 가장 높은 접근수준으로, 클래스와 클래스의 멤버에서만 사용할 수 있다.
  • 클래스가 정의된 모듈 밖의 다른 모듈에서도 상속할 수 있으며, 재정의 할 수 있다.
  • 클래스를 open으로 명시하는 것은 그 클래스를 다른 모듈에서 부모클래스로 사용하겠다는 목적으로 설계했음을 의미한다.

Public

  • 주로 프레임워크에서 외부와 연결될 인터페이스를 구현하는데 많이 쓰인다.
  • 우리가 사용하는 Swift의 기본 요소는 대부분 Public으로 구현되어 있다.

Internal

  • 기본 접근 수준으로, 별도의 표기를 하지 않는 경우 기본적으로 지정되는 접근 수준이다.
  • 소스파일이 속해있는 모듈 어디에서든 사용할 수 있지만, 그 모듈을 가져다 사용하는 외부 모듈에서는 접근할 수 없다.

Fileprivate

  • 요소가 구현된 소스파일 내부에서만 사용할 수 있다.
  • 해당 소스파일 외부에서 값이 변경되거나 함수를 호출하면 부작용이 생길 수 있는 경우에 사용한다.

Private

  • 가장 한정적인 범위로, 그 기능을 정의하고 구현한 범위 내에서만 사용할 수 있다.
  • 같은 소스파일 안에 구현한 다른 타입이나 기능에서도 사용할 수 없다.

 

그럼 대체 왜 써야 하는지, 구체적으로 어떤 의미를 갖는지에 대해 이해하기 위해서는 객체지향 프로그래밍과 객체지향의 특징인 캡슐화와 은닉화에 대해서 알아야 한다.

OOP(Object-Oriented-Programming), 객체지향 프로그래밍

프로그래밍 패러다임으로 절차 지향과 객체지향 프로그래밍이 있다. 보통 절차 지향 언어로는 C언어, 객체지향 언어는 Java, Python, Swift 등등의 것이 있다고 하는데, 아주 틀린 말은 아니지만 어디까지나 '지향'하는 방식인 것이고 패러다임일 뿐 어떤 언어이건 상관없이 절차 지향적으로 작성할 수 있고, 반대로 C언어도 객체지향적으로 작성할 수는 있다. 'ㅇㅇ'지향이라는 것은 코딩의 방식 또는 방법론의 차이일 뿐이고, 특정 언어가 특정 방식만 지원하는 것은 아니다. 그렇기 때문에 절차 지향 프로그래밍의 반대 개념이 객 제지 향 프로그래밍이라고 오해하기 쉽지만 절대 아니다.

 

사실 우리가 처음 코딩을 시작할 때 작성하는 방식이 바로 절차 지향적이다. 절차 지향은 데이터를 중심으로 '함수'를 만들어 사용하는 편이고, 객체지향은 '데이터와 기능을 묶어 하나의 객체'로 만들어서 사용한다. 절차 지향은 말 그대로 절차적으로 진행되는 순서에 따라 코드를 구성하는 방식이고, 객체지향은 기능들을 묶어 객체로 만들어서 진행된다. 식당에서 음식을 주문하는 것을 예로 들어보자면 아래와 같다.

절차 지향의 방식

  1. 고객이 메뉴를 보고 음식을 주문한다.
  2. 테이블 번호를 확인하고 음식을 만든다.
  3. 음식이 제작되면 테이블 번호를 확인하고 서빙한다.
  4. 고객은 음식을 먹고 계산을 한다.

데이터에 대산 순서를 파악하고 필요한 기능을 함수로 만들어 절차적으로 진행하는 방식이다.

객체 지향의 방식

고객 식당
음식을 주문한다
음식을 받는다
계산을 한다.
테이블번호를 확인한다.
음식 주문을 받는다.
음식을 만든다.
테이블번호를 확인한다
음식을 준다.
테이블 번호를 확인한다
돈을 받는다.

고객이 할 수 있는 행위(기능)를 하나로 묶어 고객이라는 객체를 만들고, 식당에서 할 수 있는 행위들을 묶어 식당이라는 객체로 묶어서 각 객체의 메서드나 필드를 호출하면서 상호작용을 통해 알고리즘을 구성하는 방식인 것이다.

 

그러니까 지금까지 내가 접근제어를 작성하지 않음에도 크게 무리가 없었던 이유는 대부분의 코드를 절차 지향 프로그래밍으로 작성했기 때문이었고 이제 한 단계 더 업그레이드되기 위해서는 객체지향 프로그래밍을 이해하고 작성해야 한다는 것이다.

OOP의 특징

캡슐화(Encapsulation)

  • 실제로 구현되는 부분이 외부에 드러나지 않도록 캡슐로 감싸 이용방법만을 알려주는 것
  • 데이터 구조와 데이터를 다루는 방법들을 결합시켜 묶는 것. 변수와 함수를 하나로 묶는 것을 말한다.
  • 하지만 무작정 한대 묶으면 되는 것이 아니고 객체가 맡은 역할을 수행하기 위한 목적만 한데 묶는다.
  • 데이터를 절대로 외부에서 직접 접근을 하면 안 되고 오로지 함수를 통해서만 접근해야 하는데 이를 가능하게 해 주는 것이 캡슐화이다.
그런데 왜 캡슐화를 해서 묶어야 하는 걸까?

 먼저 묶음으로 인해 프로그램을 바라보는 단위가 커진다.

이전의 절차 지향에서는 프로그램을 함수 단위로 구조화할 수 있었으나, 프로그램의 소스가 커지면 이해하기 어렵고 관리 및 유지보수가 힘들어진다. (지금의 내 앱들이 그렇다.) 그렇지만 객체지향에서는 프로그램 소스를 클래스 단위로 볼 수 있게 됨으로써 좀 더 복잡하고 커다란 소스코드도 쉽게 이해할 수 있고 그로 인해 프로그램 관리가 좀 더 수월해진다. 왜냐하면 클래스 내부에 여러 함수를 내포할 수 있기 때문에 프로그램 소스 코드를 바라보는 단위가 커지는 것이다.

 

 둘째로, 내부를 숨김으로써 내부를 좀 더 자유롭게 변경할 수 있게 된다.

이전의 절차 지향적인 프로그래밍에서는 내부에서 데이터가 어디서 어떻게 변경되는지 파악하기가 어려웠고, 그로 인해 유지 보수가 힘들었기 때문에 자료 중심으로 함수가 종속되는 구조가 되기도 했다. 객체지향에서는 클래스 내부의 데이터를 외부에서 참조하지 못하도록 차단하여 이러한 폐단을 없앨 수 있다. 이렇게 내부의 데이터나 함수를 외부에서 참조하지 못하도록 차단하는 개념을 정보 은닉(Information Hiding)이라고 하며 이것이 캡슐화라는 개념이다.

은닉화(Hiding)

  • 은닉이란 내부 데이터, 내부 연산을 외부에서 접근하지 못하도록 은닉(hiding) 혹은 격리(isolation) 시키는 것.
  • 변수에 접근 지정자를 Private로 지정한다.
  • setter, getter를 사용해 변수의 접근을 제어한다

은닉화는 캡슐화의 한 개념으로 비교적 구체적인 개념이다. 객체 외부에서 내부 자료로의 접근을 제한하고 데이터를 수정, 조작하는 동작은 내부에 두고 접근(getter), 설정(setter)하는 메서드로 결과만 받는 것이다. 이렇게 되면 외부에서는 내부적인 움직임을 알 수 없기에 데이터에 어떤 값이 있는지 또는 어떤 변화가 일어나는지 알 수 없다. 단지 데이터의 접근을 메서드(getter, setter)를 통해 결과만 받을 뿐이다. 이러한 것을 은닉화라 한다.

 

흔히 캡슐화와 은닉화를 혼용해서 이해하게 된다. 캡슐화의 과정에서 public으로 공개할지, private로 숨길지, portected로 자손에게만 알려줄지를 서술하기 마련이기 때문이지만, 은닉화의 개념은 캡슐화와 다르다. 

은닉화는 중요사항이 (변수이던 메서드던간에) 밖으로 드러나지 않도록 꼭꼭 감추는 것

캡슐화는 중요사항을 감춘 상태에서 외부에서 그것을 사용할 수 있는 방법을 설정하고 외부와 직접적으로 의사소통을 의미한다.


[객체지향 프로그래밍의 구조 예시]

class Person {
  private var location = "서울"

  private func doSomething1() {
    print("잠시 휴게소에 들려서 군것질하기")
  }
  private func doSomething2() {
    print("졸음쉼터에서 쉬다가기")
  }

  func currentLocation() {
    print("현재 위치 :", location) }

  func goToBusan() {
    print("서울을 출발합니다.")
    doSomething1()
    doSomething2()
    print("부산에 도착했습니다.")
    location = "부산"
  }
}

let A = Person()
A.currentLocation()
A.goToBusan()
A.currentLocation()

goToBusan()을 실행했을 때, 내부적으로 작업을 실행해서 location 속성을 변경한다.

currentLocation()과 goToBusan() 메서드 외에는 외부로 노출되지 않는다.

즉, 요청자는 무엇을 할지만 알면 되고, 어떻게 되는지는 몰라도 된다.


참고자료 : 

https://velog.io/@zooneon/Swift-%EC%A0%91%EA%B7%BC%EC%A0%9C%EC%96%B4%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

 

[Swift] 접근제어에 대해 알아보자!

본 내용은 '스위프트 프로그래밍' 책을 학습한 후 이를 바탕으로 작성한 글입니다. Swift에서 쓰이는 접근제어의 개념에 대해 알아봅시다.

velog.io

https://seungchan.tistory.com/entry/Swift-private-%EC%A0%91%EA%B7%BC%EC%A0%9C%EC%96%B4-%EC%BA%A1%EC%8A%90%ED%99%94-%EC%9D%80%EB%8B%89%ED%99%94

 

[Swift] private, 접근제어, 캡슐화, 은닉화

요즘 들어 제가 사용하는 코드들에 대한 의미를 알고 쓰는 것이 맞는지, 왜 쓰는 것인지 에 대한 의문이 듭니다.. 그 중 하나가 private 키워드인데요. 프로젝트를 진행하면서 private 키워드를 붙여

seungchan.tistory.com