제목: Safety In Swift


스위프트는 일반적으로 "세이프한" 언어로 불린다. 실제로 swift.orgAbout 페이지에서 이렇게 말한다.
스위프트는 세이프티, 퍼포먼스, 소프트웨어 설계 패턴의 현대적인 방법 사용을 내장한 일반 목적 프로그래밍 언어이다.
그리고
  • 세이프. 코드를 작성하는 가장 명백한 방법은 안전한 방법으로 동작할 수 있다. 정의되지않은 동작은 세이프티의 적이고, 개발자 실수들은 스프트웨어가 제품으로 되기 전에 잡힌다. 가끔 세이프티를 선택하는것이 스의프트가 엄격하게 느껴질 것이나, 장기적으로 봤을땐 명쾌하게 시간을 절약해줄 것이라 믿는다.
  • 빠름. 스위프트는 C 기반 언어(C, C++, Objective-C)를 대체하려는 목적이 있다. 이것처럼! 스위프트는 많은 작업의 퍼포먼스에서 이런 언어들과 반드시 비교된다. 또한 퍼포먼스는 단지 나중에 깨끗하게 만들어야하는 짧은 폭발적인 빠름이 아니라, 예상가능하고 일관되어야한다. 진귀한 기능을 가진 많은 언어가 있다. 빠른것은 희귀하다.
  • 표현력. 스위프트는 개발자들이 기대하는 현재의 기능과 함께, 즐겁게 사용할 수 있는 문법을 제공하기위해 십여년에서 나온 컴퓨터 사이언스의 증진의 이점이 있다. 그러나 스위프트는 아직 끝난게 아니다. 우리는 언어 증진을 탐색하고 계속해서 어떤 일이 스위프트가 더 나아지게 만드는지 포용할 것이다.

예를들어 우리가 Optional 타입과같은 것과 작업할때, 스위프트가 세이프티를 끌어올리는 것은 명확하다. 이전에는 어떤 변수들이 null이 될 수 있는지 없는지 몰랐다. 이런 새로운 널러빌리티(nullability) 정보로, 우리는 명시적으로 null 경우를 다루게 되었다. 이런 "널러빌리티" 타입으로 작업할때, 우리는 크레쉬를 선택할 수 있고, 보통 느낌표(!)를 포함한 연산자를 사용한다. 여기서 세이프티에의한 의미는 명확하다. 여러분의 위험에대해, 여러분이 잠글지 말지 정할 수 있는 안전띠 역할을 하는 것이다.

그러나 다른 경우에, 세이프티가 부족해 보인다. 한 예제를 보자. 한 딕셔너리를 가지고 있다면, 주어진 키(key)로 값을 쥐는것은 옵셔널을 반환한다.
let person: [String: String] = //...
type(of: person["name"]) // => Optional<String>
그러나 비슷하게 배열에서 하면, 옵셔널을 받지 않는다.
let users: [User] = //...
type(of: users[0]) // => User

왜 그러지 않을까? 배열은 비어있을수도 있다. 만약 users 배열이 비어있다면 프로그램은 다른 실제 선택없이 크레쉬될 수 있다. 이것은 세이프하다고 보기 힘들다. 다시 환불받고싶다!

흠, 좋다. 스위프트는 오픈 개발 프로세스니, 아마도 스위프트 에볼루션 메일링리스트에 이 변경사항을 제안할 수 있다.

안된다. 어느쪽도 하지 못할것이다. 깃헙 저장소의 스위프트-레볼루션 페이지에있는 "일반적으로 거절된" 프로포절들는이런 변경을 받아드리지 않을것이라고 말했다.
  • Array<T> 서브스크립 접근을 T?T! 대신에 T를 반환하는 것으로 만든다. 범위를 넘는 배열 접은은 로직 에러라는 사실을 정확하게 반영하기 때문에, 현재 배열의 동작은 의도적이다. 현재 동작을 바꾸는 것은 수용될 수 없는 정도로 배열 접근을 느리게할 수 있다. 이 주제는 이전에도 여러번 나왔지만 매우 받아드려지지 않을것으로 보인다.

무엇을 주는가? 진술된 이유는 이 특정 상황은 속도가 매우 중요하기 때문이라 했다. 그러나 위의 About 패이지 링크로 돌아가보면, "세이프"는 "빠름" 이전에 언어의 표현으로 목록에 나와있다. 세이프티가 속도보다 중요하기라도 한걸까?

여기엔 근본적인 논쟁이 있고, 그 해결책은 "세이프"라는 단어의 정의를 잡아야한다. 일반적인 "세이프"의 이해는 정도의 차이가 있어도 "크레쉬가 나지 않음"인 반면, 스위프트 코어 맴버들은 종종 "의도치않게 틀린 메모리에 절때 접근하지 않는것"이라는 의미로 쓴다.

이 경우, 스위프트의 배열 서브스크립션은 "세이프"이다. 배열이 절때로 할당된 범위 넘어서 메모리에있는 데이터에 접근하지 않을것이다. 메모리에 무엇이있든, 포함하지 않는 메모리에 접근하려고 하기 전에 크레쉬를 낼것이다. 같은 방법에서, 옵셔널 타입은 현존하는것으로부터 모든 클래스와 버그들(null에 접근하려는것)을 막으며, 이런 동작은 현존하는것으로부터 다른 클래스와 버그들(버퍼 오버플로우)을 막는다.

Chris Lattner가 ATP와했던 그 인터뷰의 24:39에서이런 구별을 만든것을 들어볼 수 있다.
 커뮤니티에 혼란에서 비용이라는 관점에서 보면 이해할 수 있는 유일한 방법은 우리가 세이프한 프로그래밍 언어를 만들면이다. "버그가 없다"는 것의 "세이프"가 아니라, 높은 퍼포먼스를 제공하고 프로그래밍 모델 앞으로 가는동안 메모리 세이프티 관점에서의 "세이프"이다.

아마 "메모리-세이프"는 그냥 "세이프"라는 용어보다 더 낫다. 방법은 이렇다. 어던 어플리케이션 프로그래머가 옵셔널로 돌아가는걸 좋아하는것 대신에 범위밖의 배열 접근에 트랩을 거는것을 좋아하는 반면, 모두가 유요하지 않은 데이터를 담은 변수로 계속 하는것보다 그 프로그래을 크래쉬 내는 것을 더 좋아할 수 있다는 것에 동의할 수 있다. 한 변수는 잠재적으로 버퍼 오버플로우 공격에 이용될 수 있다.

이 두번째 등가교환(버퍼 오버플로우를 허용하는것 대신 크래쉬 나는것)은 당연해 보이지만, 몇 언어들은 이 보장을 하지 않는다. C에서는 배열의 범위밖을 접근하는것이 여러분에게 정의되지 않은 동작을 할 수 있게 해주고, 어떤일이든 일어날 수 있다는 뜻이며, 우리가 사용했던 컴파일러 구현에 의존한다. 특히 프로그래머가 실수를 만들었다고 빠르게 말할 수 있을때(배열의 범위 밖 접근 같은), 그들이 옵셔널을 반환하는것 대신에 결정적으로 정크 메모리를 반환하는것 대신에 수용되는 곳에 크래쉬를 내는것을 좋게 느낀다는 것을 스위프트팀은 봐왔다.

"세이프" 정의를 사용하는 것도 "언세이프"한 API가 무엇을위해 설계되었는지 분명하게 한다. 왜냐면 그들은 직접적으로 메모리를 더럽히고, 프로그래머가 절때 유효하지않은 메모리에 접근하지 않을거라는 보장의 특별한 신경을 쓰게 만든다. 이것은 극도로 힘들고, 전문가들도 틀릴 수 있다. 이 주제에대한 글에 흥미가 있다면, 세이프한 방법으로 C를 스위프트에 연결시키는 Matt Gallagher’의 글 확인해보자.

스위프트와 그 코어팀의 "세이프"의 정의는 여러분의 생각에 100% 맞춰지지 않을 것이나, 그들은 클래스의 버그를 막아주어서 여러분같은 프로그래머들이 매일매일 그것에대해 생각하지 않아도 된다. 그 의미를 이해할때, "세이프"를 "메모리 세이프"로 대체하여 사용하면 종종 도움이 뒬 수 있다.



이 블로그는 공부하고 공유하는 목적으로 운영되고 있습니다. 번역글에대한 피드백은 언제나 환영이며, 좋은글 추천도 함께 받고 있습니다. 피드백은 

으로 보내주시면 됩니다.




WRITTEN BY
tucan.dev
개인 iOS 개발, tucan9389

,