SwiftFest Boston 2019 발표 및 참석 후기 - 컨퍼런스가 아닌 커뮤니티

2019년 7월 29일~30일 이틀간 진행되는 SwiftFest라는 iOS 개발자 컨퍼런스에 스피커로 참여할 기회를 얻어서 보스턴을 다녀왔다. 단순히 영어 발표 경험 뿐 아니라 오래 기억에 남을 일들과 여러 잡다한 생각거리를 얻고 돌아왔다.

스피커로 선정되다

해외 컨퍼런스에서 발표를 해보고 싶어서 몇 달 전부터 준비를 했다. 무슨 주제로 어떤 컨퍼런스에서 발표를 할지를 정해야했다. 얼마 전 사이드 프로젝트로 개발한 Notable Me라는 앱을 출시했는데 거의 6개월간 삽질을 해가며 배운 것들을 발표 주제로 선정했고, #ARKit #CoreML #TuriCreate 등이 키워드라서 흥미를 끌 만 하다고 생각했다. 그리고서 스위프트 | iOS | 모바일 관련 컨퍼런스를 검색해봤는데 당연하게도 정말 다양한 나라에서 컨퍼런스들이 계획되어 있었다. 그 중 컨셉이 내 주제와 맞고 Call For Papers가 열려 있던 곳에는 거의 다 지원서를 냈다. 지원서는 구글 폼으로 받는 곳도 있었고 웹사이트에서 직접 입력하는 곳도 있었는데 대체적으로 주제와 내용을 필수로 써내야했다. 다만 얼만큼 자세하고 길게 써내야 하는지 정도의 차이는 있었다. 이미 한차례 사내 컨퍼런스인 네이버 엔지니어링 데이에서 발표를 한 적이 있어서 만들었던 자료를 토대로 내용을 채우는 것은 오래 걸리지 않았다. 모든 곳이 여행 경비 지원이 필요한지를 물었는데 뽑힐 확률을 조금이라도 높여주지 않을까 싶어 속으로 회사에서 지원해주기를 바라며 No로 답했고, 불러만 준다면 기필코 사비로라도 가겠다 생각했다. 그리고 과거 발표 영상을 첨부해야 하거나 심지어 필수로 요구하는 곳도 있었다. 그런 컨퍼런스들은 수백명 규모에 2~3일 동안 진행되고 참가비도 최소 30~50만원 정도 하는 곳들이었다. 마침 작년 레츠스위프트 발표 영상이 유튜브에 공개되어 있어서 첨부하여 지원할 수 있었다. 한국어로 발표한거지만 어차피 내용보다는 발표 모습이나 경험을 보고자 하는 것이겠거니 싶어 참고자료로는 문제없을 것이라 생각했고 발표자로 선정된 것을 보면 맞았던 것 같다.

스피커 선정은 발표 날짜가 정해진 것이 아니라 지원서를 왕창 제출하고서는 잊고 살았다. 사실 돌이켜보니 쿨하지 못하게 종종 웹사이트에 들어가서 혹시 다른 발표자들이 추가됐나 확인해봤다. 그러던 어느날 메일 하나를 받았다.

대입이던 취업이던 불합격 메일을 받아본 사람은 공감할 것이다. 메일을 여는 순간 죄송스럽게도unfortunately 같은 단어가 정말 도드라져 보인다. 지원을 하면서도 정말 선정이 될까 긴가민가하고 큰 기대를 하진 않았지만 막상 탈락 메일을 받으니 힘이 많이 빠졌다. 더욱 마음을 비웠다. 생각날 때마다 웹사이트에 들어가서 발표자가 추가됐나 확인하던 스토킹도 지쳐서 그만뒀다. 그러다가 어느 날, 출근 전 집에서 아침밥을 먹다가 메일함을 열어봤는데 보스턴에서 열리는 SwiftFest에서 발표해줬으면 좋겠다고 빠르게 확답을 달라는 메일이 와있었다.

정말 믿기지 않아서 두번 세번 다시 읽어봤다. SwiftFest는 이름에서도 알 수 있다시피 스위프트와 iOS에 집중된 컨퍼런스라서 해외 iOS 개발자가 많이 참석할 것이라는 점과 미국 동부로 가게 되는 것이 개인적으로 매우 좋았다. 아무튼 이렇게 흥분되는 메일을 받고서 부랴부랴 여권과 비자를 재발급받았다(6월 미국 출장 때 호텔 로비에서 백팩을 통째로 도난맞음ㅜ). 그리고 마침 네이버 테크콘서트에서 해당 주제로 한번 더 발표해달라고 요청을 받아 자료 업데이트도 하고 발표 경험도 더 쌓았다. 팀원분 왈, 발표는 사골과 같아서 하면 할수록 진국이 우러나죠 핵공감😆!

사람들을 만나다

보스턴 로건 공항에 도착하니 태극기가 반겨주었다.

컨퍼런스가 월,화 이틀 동안 진행되는 일정이라 일요일 오후에 보스턴에 도착했다. 일요일 저녁에는 컨퍼런스장 근처 호텔에서 VIP 오프닝 디너가 열렸다. VIP 디너는 스피커, 자원봉사자, 스폰서사의 개발자들이 모이는 자리이다. 사실 네트워킹 보다는 장소가 호텔이라 스테이크 같은 코스 식사를 주는줄 알고 응원차 미국 중부에서 날라온 여자친구까지 꼬드겨서 같이 갔다. 그런데 예상을 완전히 뒤엎고 크래커와 치즈, 덤플링 같은 핑거푸드만 세팅되어 있었고 음료는 한잔만 공짜로 제공하는 형식이었다. 당황했지만 배가 많이 고팠기 때문에 조금이라도 배를 채우고 돌아가기로 했다. 그나마 몇 개 없던 테이블에 자리를 잡아서 먹고있는데 갓 대학 졸업한 것으로 보이는 어린 동양계 남자아이와 남미계의 여성이 합류하여 인사를 나눴다. 남자아이는 자신의 회사가 스폰서라서 초대받아 왔고 여성분은 캐나다에서 QA 엔지니어로 일하고 있다며 남편이 자원봉사자 총괄인데 사람이 부족하다고해서 도와주러왔다고 했다. 여자친구가 자원봉사에 관심을 보이니까 바로 남편을 부르더니 안그래도 몇 명 펑크나서 사람이 필요한데 내일 아침 일곱시반까지 나오라고 했다. (역시 미국 취업은 referral인가) 이렇게 예정에 없던 자원봉사 일을 얻고 돌아와서 나는 시차 적응을 위해 억지로 눈을 감았다.

덕분에 여러 자원봉사자들과 친해질 수 있었다. 남편을 따라 자원봉사자로 왔다던 데니는 도미니카 공화국 출신으로 몬트리올에서 QA 엔지니어로 일하며 최근에는 파이썬과 스위프트를 공부하기 시작했다고 했다. 이틀 내내 프런트 데스크를 지키며 참가자들을 맞이하며 즐기는 모습이었다. 보스턴에 있는 한 회사에서 14년간 근무한, 베트남 출신 아내와 결혼한 마이클 아저씨는 너무 친절했고 로컬답게 차이나타운에 있는 매운 음식을 파는 식당을 알려주었다. 우리한테는 안맵겠지만 자기한테는 너무 매운데도 맛있어서 자주 간다는 말을 하는 모습이 귀여우셨다.

데니와 나

오거나이저이면서 연사면서 자원봉사자였던 앨리시아 카는 처음 만난 순간부터 격하게 반겨주었다. 한국인 친구가 있다면서 페이스북 친구를 꼭 맺자고 난리 법석을 피웠다. 처음엔 단순히 외국인에 관심 많은 사람이겠거니 했는데 앨리시아와 얘기를 나누고 컨퍼런스 내내 지켜보면서 커뮤니티에 다양성을 증대시키고 좋은 영향력을 미치는 사람이라는 걸 알게되어 점점 존경하게 되었다. 50대 흑인 개발자 여성은 미국 기준으로도 소수 중의 소수인데 더 대단한건 불과 몇 년 전 애플 스토어에 아이패드를 사러갔다가 유튜브로 개발을 배워서 앱을 출시한 고등학생 얘기를 듣고는 충격을 받아 회사를 그만두고 독학해서 iOS 개발자가 되었다고 한다.

앨리시아가 오프닝을 하면서 모두를 춤추게 만들어서 그런지 이틀 내내 컨퍼런스장 내부에는 들뜨고 신나는 바이브가 유지되었던 것 같다. 테크 업계의 Inclusion에 관한 키노트 중에는 업계에 여성 개발자가 너무 적다는 것에 동의를 하며, 여전히 차별과 편견이 만연하기 때문에 다같이 노력해야한다고 목소리를 높였다.

SwiftFest에서 만난 사람들 중 가장 인상깊었던 분은 로버트 C. 마틴(a.k.a. 엉클밥)이다. 내가 스피커로 선정될때만해도 리스트에 없었는데 몇 일 뒤에 웹사이트에 등장하셨다. 사실 직접 만나기 전까지는 그저 클린 코드의 저자, 업력이 엄청난 개발자 정도로만 생각하고 있었다. 그리고 멘토님이 사인을 받아달라고 부탁하셔서 어떻게든 붙잡고 사인을 받아야할 인물 정도로 생각했다. 엉클밥은 첫번째 날 마지막 시간에 클린 애자일을 주제로 키노트를 하게 되어있었다. 그래서 오후부터 찾아나섰다. 연사 대기실에도 기웃거려보고 컨퍼런스장을 돌아다녀 봤지만 찾지 못했고, 오거나이저인 Giorgio에게 물어보니 아직 도착하지 않았다고 했다. 하지만 키노트 시간이 되어가는데도 보이지 않아 정말 혹시나 낚인건가 싶기도 했다. 하지만 비행기가 연착되어 늦는 것이라는 소식을 들었다. 30분이 지난 후에야 도착하셨고 문 앞에서 기다리고 있었지만 황급히 들어가는 모습을 뒤에서 바라봤다.

프사는 너무 카리스마 넘쳐서 날카롭고 매서운 할아버지일거라 생각했지만 완전히 틀렸다. 친절하고 재밌고 영감을 주는 분이셨다.

엉클밥은 클린 애자일을 주제로 프로그래머가 어떻게 소프트웨어를 개발해야 하는지에 대한 얘기를 했는데 시작 5분만에 유머와 친근함과 카리스마에 푹 빠져버렸다. 이제 소프트웨어 없이는 아무 것도 할 수 없는 세상이 되었다. 소프트웨어가 우리의 일상에 깊숙히, 구석구석 스며들었기 때문에 잘못 만들어진 소프트웨어는 엄청난 위험을 내포하고 있다. 사기를 치는데 활용되기도 하고 사람의 목숨을 앗아가기도 한다. 2015년 폭스바겐은 디젤게이트로 논란을 일으켰는데 주행 환경을 인지해 테스트 상황일때만 배기가스 저감장치를 작동시키는 조작 소프트웨어를 장착했던 것으로 밝혀졌다. 그리고 조작 소프트웨어를 직접 개발한 프로그래머도 유죄 선고를 받았다. 최근에는 보잉 737-Max 항공기가 5달 간격으로 두 번이나 추락해 346명이 죽었는데 소프트웨어 결함이 원인으로 밝혀졌다. 보잉사는 해당 기종의 생산을 중단하고 비행을 금지하는 초유의 조치를 가했다. 프로그래머는 자신이 만드는 소프트웨어에 책임감을 가져야한다. 소프트웨어의 결함 때문에 만 명 단위의 사람 목숨이 위태로워지는 사건이 가까운 미래에 벌어질 수도 있다. 따라서 높은 기준을 두고 결함없는 소프트웨어를 배포해야 한다. 어떻게 그렇게 할 수 있을까? 엉클밥은 클린 애자일을 주창한다.

애자일 방법론에 관해서는 엉클밥이 쓴 책에 더 자세히 나와있겠지만 나는 그 책을 읽지 않았기 때문에 발표 내용으로만 간략히 요약을 하자면,

  • 소프트웨어는 매주 배포 가능해야한다.
  • 배포 가능하다는 말은 테스트를 마쳐서 기능이 문제없이 돌아간다는 뜻이다.
  • 따라서 테스트 자동화가 중요하다.
  • 실제로 배포 할지 말지는 사업적인 기준으로 결정을 내린다.
  • 스프린트는 1~2주 단위가 좋다. 이 기간 안에 뭔가 심각하게 잘못될 일은 없기 때문이다. 한달은 좀 길다.
  • 생산성은 ’포인트’로 관리한다.
  • 매 스프린트마다 포인트가 증가하는게 좋은건 아니다. 생산성이 올라간다는 의미가 절대 아니다. 일정하게 유지되는 것이 좋다.
  • 포인트가 낮아지기 시작하면 코드가 썩어서(rot) 개발 속도가 저하되고 있다는 신호이다.
  • 그러면 리팩토링을 해서 코드를 다시 깨끗하게 만들어야 한다.
  • 리팩토링을 제대로/잘/자신있게 하려면 테스트가 정말 잘 짜여있어야 하고 코드는 반드시 테스트하고 배포해야한다.

한줄 요약을 하자면 테스트를 잘 짜고, 코드는 반드시 테스트를 거치고, 테스트 결과를 기준으로 리팩토링을 주기적으로 하여 생산성이 떨어지지 않게 해야 한다는 말이었다. 엉클밥은 TDD를 전파한다. 테스트를 통과하지 않은 코드를 배포하는 것은 말도 안된다고 한다. 그 외에도 인상 깊었던 말은 버그를 당연하게 생각하지 말라, 소프트웨어 테스트를 QA에게 떠넘기지 말고 자신의 코드는 본인이 책임지고 테스트해라 등이 있다. 머리가 하얗게 샌 분으로부터 이런 열정적인 발표를 들으니 후배(감히?) 프로그래머로서 어떤 마음가짐으로 코드를 짜고 소프트웨어를 만들고 배포할지에 대한 고민이 안 들 수가 없었다.

대망의 발표

발표는 무난히 마쳤다. 나보다 앞서 발표했던 분이 말이 굉장히 빠르고 청중을 빵빵 터뜨리셔서 갑자기 긴장이 되기도 했지만 단상에 올라가니 이미 친해진 사람들의 얼굴도 보이고 앱 데모 영상에서 예상보다 반응이 좋아서 긴장이 많이 풀렸다. 덕분에 차분하게 하고 싶은 말은 다하고 내려와서 아쉬운 점은 없다.

2015년 WWDC 가서 애플 뽕 + 개발자 뽕을 실컷 맞고는 ‘와 개발자하길 정말 잘했다’는 생각을 했었다. 개발자가 이런 일을 하는구나, 이런 변화를 가져오고 있구나, 앞으로 재밌는 일도 많고 여러 가능성이 열려있구나 싶었다. 그리고 이번 SwiftFest Boston에서 새로운 사람들(특히 엉클밥)을 만나고 색다른 경험을 하고나서는 ‘앞으로는 이런 마음가짐으로 프로그래밍을 하고 새로운 것을 경험해야겠다’는 생각을 하며 돌아왔다.

이 외에도 정말 재밌는 이야기를 들려준 연사분들, 내 발표가 끝난 후 스테이지 밑으로 찾아와 나에게 질문을 하셨던 분, 몇 달 전 내 블로그를 읽고 메일을 보낸적 있었던 학생, 대기실에서 인사를 나눈 틴더의 한국인 개발자 등등 좋은 사람들을 많이 만날 수 있었던 컨퍼런스였다.

커뮤니티에 참여하다

SwiftFest를 있게 해준 모든 사람들

돌이켜보니 SwiftFest는 이틀짜리 컨퍼런스가 아니었다. 한 달 전 발표자 슬랙에 초대 됐을 때부터 마지막날 일정까지, 그리고 이후까지 컨퍼런스 참여자들은 새로운 사람을 만나고 새로운 아이디어를 얻고 대화를 하기 위해 오는 것이었다. 컨퍼런스도 이런 목적에 부합하도록 설계되고 진행되었다.

발표자로 선정된 후 웹사이트에 게재할 간략한 자기 소개와 소셜미디어 링크를 요청받았다. 이미 사이트에 올라가 있던 발표자들의 프로필을 둘러봤는데 개개인의 트위터와 링크드인 프로필 링크가 있던 것이 놀라웠다. 트위터 계정이 없던 나는 링크드인 프로필만 게재를 했다. 그래도 궁금해서 발표자들과 컨퍼런스 공식 트위터 계정을 구경 가보니 이미 컨퍼런스에 대해 얘기를 나누고 있었다. 공식적인 만남이 시작되기 전부터 사실상 온라인에서는 컨퍼런스가 시작한것이나 다름 없는 것처럼 보였다. 그래서 나도 트위터 계정을 만들어서 발표자들 팔로우도 하고 SwiftFest 해시태그를 써서 트윗을 해봤다. 컨퍼런스 전부터 발표자들의 링크드인과 소셜계정을 알게되니 발표자에 대해 미리 알아 볼수 있어서 좋았다. 발표에 대한 기대감도 커졌다. 평소 활동이나 관심사를 알아보고나서 컨퍼런스 당일에 만나면 둘 다 관심있는 주제로 대화를 할수도 있을 것이다. 그리고 컨퍼런스가 끝난 후에도 인상 깊었던 발표자의 활동을 계속 지켜볼수도 있고 원하면 대화를 할 수 도 있다. 반면 우리나라 컨퍼런스는 웹사이트에서 발표자의 소셜 계정이나 블로그, 브런치 등의 링크를 제공하는 곳이 거의 없다. 발표자보다는 발표 내용에 초점이 있는 것이 아닐까 싶다. 발표 주제가 흥미있으면 발표자의 업적이나, 커리어에 대해서 더 알고 싶어지기 마련인데 이런 점은 예전부터 아쉬웠던 점이다.

첫날 오프닝을 맡은 MC는 몇 년 전 컨퍼런스에서 만났던 인연으로 지금 회사로 이직을 했고 SwiftFest의 오거나이저와도 친분을 쌓아 이번에 자신의 회사가 공식 스폰서를 맡게 되어 기쁘다고 했다. 그러면서 이 자리에 있는 누군가가 당신의 인생을 바꿀지 모르니 사람들을 만나고 좋은 시간을 보내라고 당부했다. 일요일 저녁에는 VIP 오프닝 디너, 월요일 저녁에는 오후 7시반부터 크루즈 네트워킹 파티, 화요일 오후 5시부터 8시까지 라운지에서 캐주얼한 모임을 했다. 매일 네트워킹 시간과 장소를 제공했다. 그런데 꼭 네트워킹 시간이 아니더라도 세션이 진행될 때도 컨퍼런스장 곳곳에서, 스폰서 부스 앞에서 사람들끼리 대화를 하고 서로를 소개하는 모습을 봤다.

키노트 발표는 이런식으로 한 분이 무대 위에서 실시간으로 그림을 그려가며 요약을 했다. 처음보는 광경이어서 이걸 뭐라고 불러야할지 모르겠지만 흥미로웠다.

기술적인 내용이 아닌 흥미로운 키노트들을 통해서도 컨퍼런스가 일방적으로 발표를 듣는게 아니라 커뮤니티 모임이라는 인상을 받았고 소속감 마저 들게 했다. 첫날 오프닝 키노트는 Ish Shabazz가 맡았는데 Programming with Purpose라는 주제로 자신의 인생 얘기를 했다. 중학생 시절 자신이 컴퓨터에 관심을 보이자 선생님이 사비로 애플 II 컴퓨터를 사오셔서 사용법을 가르쳐주셨는데 이 순간이 인생을 바꾸는 순간이었다고 고백했다. Ish가 프로그래밍하는 목적은 매일매일 사소한 방법으로 남을 돕기 위해서라고 한다. 두번째 키노트는 위에 자세히 쓴 엉클밥의 클린 애자일이었다. 그리고 둘째날 오프닝 키노트는 Make room for all, not war!: Inclusion means all y’all 란 제목으로 Diana Rodriguez가 발표했다. 테크 업계가 더욱 다양성을 넓히고 소수자들을 포용해야 한다는 내용이었다. 많은 사람들의 예상과는 다르게 여성, 소수자들이 느끼는 차별과 편견은 최근에도 딱히 나아지지 않았고 새로운 세대 개발자들의 진입을 가로막는 요인이 된다고 했다. 이런 키노트를 통해서 커뮤니티 구성원의 인간적인 이야기를 듣고, 소프트웨어의 퀄리티나 다양성 이슈와 같이 더 크고 어려운 문제에 대해 모여서 얘기를 나누는 모습이 처음에는 생소했다. 키노트 후 트위터에서 한 참석자가 Diana에게 다음달에 자신이 주최하는 모임에서도 키노트를 해줄 수 있냐고 요청하고 기꺼이 가겠다고 하는 모습을 보며 이런 식으로 컨퍼런스를 통해 사람들 사이에 다양한 아이디어가 퍼지는거구나 싶었다. 그리고 공감하는 사람들이 많아질수록 서서히 변화를 가져올 것이다.

컨퍼런스를 구경한게 아니고 커뮤니티에 속하게 되었다.

국내에서 참석해봤던 컨퍼런스들과는 분위기가 달랐다. 여러 날에 걸쳐 진행한다던지, 참가비가 몇 십 만원이라던지 하는 겉으로 드러나는 규모적인 측면 만을 얘기하는게 아니다. 행사 주최자, 스폰서, 자원봉사자, 참가자, 발표자 이렇게 각 역할의 사람들이 명확히 구분되어 누구는 행사를 계획하는 공급자고 누구는 돈을 지불하여 서비스를 받고 이런게 아니라 모두가 함께 즐기는 페스티벌의 느낌이 강했다. 미국에는 포트럭Potluck 파티(네이버 사전)가 매우 흔하다. 파티를 여는 사람이 자신의 집으로 지인들을 초대하되 초대 받은 사람들이 각자 음식이나 술을 가져와서 다같이 나눠먹는 것이다. SwiftFest는 모두가 기여하고 함께 누리는 포트럭 파티 같은 컨퍼런스였다.

이 글의 초안을 읽어준 조소현, 안성용에게 고마움을 전합니다.

Tags: SwiftFest, speaking, Swift, conference, UncleBob, Boston  

스티브 잡스 생전 마지막 인터뷰 어록 @D8 Conference 2010

2010년 5월에 열렸던 All Things Digital: D8 컨퍼런스에서 월트 모스버그(Walt Mossberg)와 카라 스위셔(Kara Swisher)가 100분 가량 스티브 잡스와 했던 인터뷰에서 발췌한 내용입니다. (유튜브 영상)

내 피가 무지개색이기 때문이다

“Because I bleed in six colors”

이 말은 스티브 잡스가 직접 한 말은 아니고, 애플 직원이 잡스가 던진 질문에 대한 답으로 한 말이다. 애플에서 쫓겨났던 잡스는 12년 만인 1997년 다시 CEO로 복귀한다. 하지만 애플의 상황은 그의 예상보다 훨씬 좋지 않았고 파산까지 약 90일이 남은 상태였다고 한다. 그러나 그는 아이맥, 맥북, 아이팟, 아이폰, 아이패드 등을 성공시키며 사망 직전이었던 애플을 세계 최고의 기업으로 일궈낸다. 그리고 인터뷰 바로 몇일 전 애플의 시가총액이 사상 처음으로 마이크로소프트를 넘어선다. 카라 스위셔는 이에 대한 소감을 묻는 것으로 인터뷰를 시작한다.

“우리 업계에 오래있었던 사람이라면 공감하겠지만, 정말 꿈만 같은 일이다. 하지만 상관 없다. 중요한 것이 아니다. 시가총액은 우리가 아침에 눈을 떠서 회사에 오게 하는 이유도 아니고 고객이 우리 제품을 사는 이유는 더더욱 아니다.”

원문 보기 For those of us that have been in the industry long time, it’s surreal. But it doesn’t matter very much. It’s not what’s important. It’s not, you know, what makes you come to work in the morning. And it’s not why any of our customers buy our products.


애플로 복귀한 잡스는 애플의 상태가 생각보다 더 심각하다는 것을 깨닫는다. 하지만 그를 놀라게 한 것은 그게 다가 아니었다. 당연히 떠났을 거라 여겼던 뛰어난 사람들이 아직도 애플에 남아있었다. 기적과 같은 상황에서 잡스는 ‘대체 당신이 왜 아직도 여기 남아있는건가요?’ 라고 물었다.

“내 피가 무지개색이기 때문이다. 이 회사가 퍼뜨리고 싶어하는 가치를 사랑한다. 그래서 우리는 그 가치를 지키기 위해서 지금까지 힘들게 일할 수 있었다.”

원문 보기 They said ‘Because I bleed in six colors, which was the cold six-colored Apple logo. And that was code for ‘Because I love what this place stands for’. And that just made all of us want to work that much harder to have it survived, have that value survived and bring it back.



(초창기 애플의 6색 로고)

어떤 말을 타야 미래로 빨리 갈 수 있을 것인지 기술적인 관점에서 잘 선택해야한다.

“Choosing what horses to ride, technically”

잡스는 2010년 4월, Flash에 대하여(Thoughts on Flash)라는 공개 서한을 썼다. 얼마 전부터 애플은 아이팟, 아이폰, 아이패드에서 더이상 플래시를 지원하지 않기 시작했고 이 때문에 플래시의 개발사인 어도비는 연일 언론에서 애플을 비판하고 있던 터였다. 참다못한 잡스는 이 공개 서한에서 왜 플래시를 버려야했는지, 왜 이 결정이 애플 플랫폼의 개발자들과 소비자들에게 좋은 결정인지 설명한다. 모스버그는 잡스가 공개 서한에 쓴 말이 다 맞다 하더라도 이런 급작스러운 결정이 과연 소비자에게도 득이 되는 일인지 반문한다. 다음은 잡스의 답변이다.

“애플은 그 어느 회사와 마찬가지로 이 세상의 모든 자원을 가지고 있지 않다. 이런 상황에서 우리는 기술적인 관점에서 어떤 말을 탈지 신중하게 선택했고 그로 인해 성공을 거뒀다. 기술은 각자의 삶의 주기가 있다. 우리는 태동기에 있는 기술을 선택한다. 그러면 정말 많은 시간을 아낄수 있다. 그 아낀 시간으로 유망한 기술이 우리 제품에서 끝내주게 작동할 수 있게 만들 수 있다. 너무 많은걸 넣으려다보면 그저그런 제품 밖엔 안된다. 애플은 여지껏 그래왔다. 지구상에서 처음으로 5인치 플로피 디스켓을 3.5인치로 교체했다. 소니가 발명하긴 했지만 우리가 처음으로 상용화했다. 1998년에 출시한 아이맥 1세대에서는 플로피 디스크를 아예 제거해버렸다. 직렬, 병렬 포트도 없앴다. 인텔이 발명한 USB도 우리가 아이맥에 처음으로 도입했다. 맥북에어에서는 옵티컬 드라이브(CD)를 제거 했다. 우리는 지금까지 많은 것들을 제거해 왔고, 그럴때마다 미쳤다는 소리를 들었다. 선택을 내려야할 때가 있다. 더 멀리 가기 위해 올바른 말로 갈아타야할 때가 온다. 우리가 보기에 플래시는 지는 별이었다. HTML5가 태동하고 있었다. 플래시를 지원하려면 너무 많은 노력이 들어가야했다.”

원문 보기 Apple is a company that doesn't have the resources of everybody in the World. The way we've succeeded is by choosing what horses to ride really carefully, technically. We try to look for these technical vectors that have a future, and that are headed up. Different pieces of technology go in cycles. they have their springs, summer, and autumns, then they go to the graveyard of technology. So we try to pick things that are in their springs. If you choose wisely, you can save yourself an enormous amount of work versus trying to do everything. And you can really put energy into making those new merging technology be great on your platform, rather than just okay because you're spreading yourself too thin. So we have a history of doing that. As an example, we went from the five inch floppy disk to the 3 1/2 inch floppy disk with the mac. We were the first to do that. we made the 3 1/2 inch disk popular. Sony invented it, and we put it first in the products. We got rid of the floppy disk altogether in 1998 with the first iMac. We also got rid of serial and parallel ports. We were first to adopt USB even though Intel had invented it. You first saw it in mass on iMacs. And so, we have gotten rid of things. We were one of the first to get rid of optical drives, with the MacBook Air. I think things are moving in that direction as well. And sometimes when we get rid of things like the floppy disk drive on the original iMac people call us crazy. But sometimes you have to pick the things that look like they are gonna be the right horses to ride going forward. and Flash looks like a technology that had its day but it's really on its waning, and HTML5 looks like the technology that's really on the ascendency right now. And to incorporate Flash into the system is a lot of work, there's no smartphone shipping with Flash on it now as you know. ... But more importantly, HTML5 is starting to emerge.


그럼에도 모스버그는 이런 파격적인 결정의 대가가 소비자들에게 전가되어 불편함을 초래하고 선택권을 제한하는 것이지 않느냐는 질문으로 집요하게 파고 든다. 웹의 많은 컨텐츠와 수많은 화려한 사이트들이 플래시로 제작되어 있기 때문에 이런 사이트를 이용하는 사용자들은 어떡하냐는 정당한 지적이었다. 이에 잡스는 10초 간 곰곰이 생각을 한 후 다음과 같은 답변을 한다.

제품은 우리가 강조하고 싶은 것들의 모음집이다.

“Things are packages of emphasis”

“제품에서 어떤 기능은 굉장히 강조되어 있다. 어떤 기능은 별로 쓸만하지 않다. 심지어 아예 들어가지 않은 기능들도 있다. 서로 다른 사람들은 제각각의 선택을 하면서 살아간다. 만약 많은 사람들이 우리가 잘못된 결정을 내렸다고 말한다면 우리는 시장의 목소리를 존중한다. 우리도 그냥 회사를 운영하는 사람일 뿐이다. 단지 고객들을 위해 최고의 제품을 만들고 싶을 뿐이다. 그래도 우린 최소한 ‘이러이러한 것들은 최고의 제품에 어울리지 않는다’고 말할 정도의 용기와 신념이 있는 것이다. 일부 사람들은 이런 결정을 좋아하지 않을 수도 있다. 특정 회사의 이익에 반하는 결정일 수도 있다. 하지만 우리는 최고의 제품을 만들기 위해서 그 정도 비난과 논란을 받아드릴 준비가 되어있다. 우리는 시간과 노력을 올바른 기술에 투자해야한다. 고객들은 그런 결정을 우리에게 위임하기 위해 우리의 제품을 사고 우리에게 기꺼이 돈을 지불하는 것이다. 우리가 성공하면 우리의 제품은 잘 팔릴 것이고, 실패하면 안 팔릴 것이다. 그렇게해서 모든 것들은 균형을 찾아간다. 지금까지의 결과를 보건데 사람들은 아이패드를 매우 좋아하는 것 같다. 출시 이후 3초에 1대씩 팔리고 있다.”

원문 보기 Things are packages of emphasis. Some things are emphasized in a product, some things are not done as well in a product, some things are chosen not to be done at all at a product. And so different people make different choices. If the market tells us we're making the wrong choices, we listen to the market. We're just people running this company. We're trying to make great products for people. We have at least the courage of our conviction to say we don't think this is part of what makes a great product and we're going to leave it out. Some people are not gonna like that, some people are gonna call us names, it's not gonna be in certain company's best of interest but we're going to take the heat because we want to make the best product in the world for customers! We're gonna instead focus our energy on these technology which we think are on their ascendencies and we think we're gonna be the right technology for the customers, and you know what? They're paying us to make those choices. That's what a lot of customers pay us to do. If we succeed, they'll buy them! If we don't, they won't. And it will all work itself out. So far I have to say, people seem to be liking iPads! We've sold one every three seconds since we launched it.


애플의 제품을 오랫동안 써보면서 느끼는 것은 빼는 것의 중요성이다. 애플에 대한 높은 충성심은 고객을 위해 어려운 결정을 잘 내려주고 있다는 믿음에 기반한 게 아닐까 싶다. 애플이 아이폰에서 3.5mm 이어폰 잭을 빼버렸을 때도 정말 많은 논란이 있었고 조롱도 받았다. 불과 3년도 안 된 지금 길거리에 나가보면 유선 이어폰을 끼고 있는 사람은 찾아보기 어렵다. 꼭 에어팟이 아니더라도 각종 무선 이어폰이 유선 이어폰의 자리를 점령했다.

기능을 빼는 것은 추가하는 것보다 최소 수 배, 수십 배는 어렵다. 왜냐? 욕 먹을 각오를 해야하니까. 기능을 잘못 빼면 욕만 엄청 먹고 다시 되돌려야하고, 기능을 잘 빼도 처음에는 욕을 약간 먹고 시간이 지나야 잠잠해 진다. 잡스 말처럼 비난을 감수하려면 결정에 대한 믿음이 있어야 한다. 그런 믿음이 없는 사람이나 조직이 굳이 욕먹을 각오를 하고 기능을 빼는 행동을 할 이유가 없다. 일반적인 회사에서는 기능을 추가하고 그 기능의 사용자가 많거나 매출을 일으키면 그 기능을 만든 사람들이 성과를 인정 받는다. 하지만 기능이 누적될수록 서비스는 비대해지고 사용성은 복잡해진다. 새로 들어온 사용자는 오랜 시간 축적된 기능 더미 속에서 헤매게 된다. 며칠 전 대화를 나눴던 개발자 지인 한명은 대규모 코드 리팩토링을 하거나 메이저 기능을 개발하게 될때면 일부 작은 기능을 슬쩍 뺀다는 것이다. 누군가는 안좋게 생각할수도 있겠다. 하지만 누군가는 해야하지만 아무도 하지 않는 어려운 일을 지인이 하고 있다고 생각한다. 기능을 추가하는 것만큼이나 빼는 것을 중요하게 여기고, 훨씬 어렵고 위험한 일임에도 그 필요성을 느끼는 팀이나 회사가 있다면 그런 곳에서 정말 일해보고 싶다.

삶은 영원하지 않다

“Life is fragile”

잡스는 2003년 췌장암 선고를 받았다. 그나마 수술을 통한 치료 가능성이 있는 희귀한 종류의 췌장암으로 판명이 되고, 종양을 제거하는 수술을 한다. 그 후 2005년 스탠포드 졸업식 연설에서 잡스는 암이 완치됐다고 밝혔지만 2008년 암은 재발하고 2011년 세상을 떠난다. 인터뷰에서도 정말 많이 야윈 잡스의 모습을 볼 수 있다. 정식 인터뷰가 끝나고 공개 질의 세션에서 한 남성이 질문했다. 스탠포드 졸업식에서 연설을 하고 몇 년이 지났는데 혹시 덧붙이고 싶은 것이 생겼느냐고.

“음.. 잘 모르겠다. 아마도 그때 했던 말을 한번 더 강조하고 싶다. 왜냐면 지난 몇 년 간 난 인간의 삶이 영원하지 않다는 걸 더욱 뼈저리게 느꼈기 때문이다.”

원문 보기 “Oh I have no idea. I have no idea. Probably I would just turn up the volume on it because last few years have reminded me that life is fragile.”


Tags: Steve Jobs, All Things Digital D8, interview  

스위프트로 다시보는 객체지향 프로그래밍: 피해야할 코딩 습관

배경

컴퓨터와 회화(painting)를 전공했고 꽤 성공한 누군가가 프로그래머는 과학자보다 화가와 공통점이 더 많다고 했다. 정말로, 프로그래밍을 잘하려는 노력을 하다보면 과학보다는 경험적으로 실력을 쌓아야하는 운동이나 미술과 비슷하다고 느껴진다.

좋은 그림을 알아보는 능력과 그림을 잘 그리는 것이 별개이듯 코드를 보고 좋다 나쁘다를 판단할 줄 아는 것과 좋은 코드를 짜는 실력은 안타깝게도 붙어오지 않는다. 코드를 많이 보게 되고 많이 짜보고 남이 짠 코드를 유지보수 해보면서 경험적으로 판별하는 후각이 조금은 탑재된 것 같다. 하지만 내가 키보드를 두들기기 시작하면 답답함이 찾아온다. 이렇게 짜면 안된다는.. 본능적인? 경험적인? 느낌은 마구 들지만, 그렇다면 이렇게 말고 어떻게 다르게, 좋게 짜야하는지에 대한 명쾌한 답은 없는 그런 상태이다. 학창 시절에 시험을 치다보면 자신있게 답을 고르는 경우도 있지만 확실히 아닌 답을 제거한 후에 남아있는 것 중에서 고르는 경우도 있다. 확실히 아닌 것을 배제하고 나면 남아 있는 선택지에 더 많은 고민을 투자할 수 있고, 답을 선택할 확률이 높아진다. 프로그래밍으로 다시 돌아와보면, 잘못된 패턴이나 유지보수에 좋지 않은 코드의 모습을 알고 이를 피하면 좀 더 나은 코드를 쓰게 되지 않을까 하는 생각을 하게 됐다.

작년, 회사에서 함수형 스위프트 프로그래밍 스터디를 했었다. 스터디를 시작하던 날, 공부 방향을 잡기 위해 가이드를 받고자 사내에서 함수형 스위프트 강의를 하셨던 멘토님을 초빙해 조언을 부탁했다. 그 자리에서 멘토님은 지금까지 약 1년간 내 프로그래밍 공부의 방향이 된 말을 하셨다. “함수형 프로그래밍이 얼마나 어떻게 좋은지 비교하려면 잘 짠 함수형 코드와 잘 짠 객제 지향형 코드를 비교해야하는데 아직도 내가 객체 지향으로 잘 짠다고 할 수 없어서 비교가 어렵다.” 아.. ‘OOP식’으로 매일 코딩을 한다고해서, 할 줄 아는 것이 OOP 밖에 없다고 내가 OOP를 하고 있는거구나 라고 여겼었던 내 무의식적인 생각이 뿌리부터 흔들렸다. 그래서 다시 기본부터 잘해야겠다고 생각했고 이 글은 지난 몇 개월 간 습득한 지식의 요약이다.

스위프트와 SOLID

SOLID는 로버트 마틴이라는 사람이 명명한 객체 지향 프로그램 및 설계의 기본 원칙 다섯 개이다. 스위프트는 멀티패러다임 언어이지만 Foundation, UIKit 등 코코아 터치 프레임워크들은 기본적으로 OOP에 근간을 두고 있다. SOLID 원칙들과 iOS를 연관지어서 살펴보니 내가 쓰고 있는 많은 클래스들이 왜 그런식으로 만들어졌는지 알 수 있었고, 또 내가 어떻게 이 원칙들을 녹여낼 수 있는지 좀 더 와닿게 이해할 수 있었다. 본문에서는 각 원칙에 따라 만들어진(혹은 위반하고 있는) iOS 프레임워크의 예시와 함께 이 원칙을 잘 지키기 위해서 어떻게 코딩을 해야하는지, 특히 이 원칙을 어긴 것은 어떤 형태인지 중점적으로 정리했다. 앞서 말했듯, 처음부터 코드를 잘 짤 순 없으니 최소한 잘못된 코드가 어떤건지는 알고 피해가자는 컨셉이다. 그러면 어려운 이야기를 전부 이해하지 못했더라도 어떻게든 그 방향으로는 나아갈 수 있다고 생각하기 때문이다.

다만 이 글에서는 마지막 두 원칙을 제외한 SOL(쏠?)까지만을 다룬다. 그 이유는 여러가지가 있는데, 아직 뒷 부분은 설명을 할 수 있을 만큼 이해를 다 하지 못했고 또 ID는 이 글의 컨셉에 맞춰 해당 원칙이 위반된 상황을 판단하려고 하는 것이 훨씬 어렵고 미묘하기 때문이다. 하지만 SOL만으로도 내 코드의 개선 사항을 수두룩 빡빡하게 찾는데는 전혀 부족함이 없었고 끝이 안보인다!

Single Responsibility Principle

단일책임 원칙은 모든 클래스는 하나의 책임만 가져야 한다는 원칙이다. 로버트 마틴은 책임을 변경하려는 이유로 정의했다. SRP의 가장 대표적인 위반 사례는 Massive View Controller 현상이다. 이런 MVC의 문제를 해결하기 위해 여러 다른 패턴들이 생겨나고 시도되고 있는데, 그것들의 공통점은 너무 많은 역할을 하고 있는 뷰컨트롤러를 쪼개서 단일 책임만을 가지는 여러 클래스를 만들려고 하는 것이다.

SRP를 지키기 위해 당장 시도해볼 수 있는 것은 클래스를 작게 만드는 것이다. 클래스가 작다는 것이 SRP의 충분 조건은 아니지만 필요 조건이다. 이 목표를 달성하기 위해서 멘토님이 제시한 10-200룰을 기준으로 코딩해보고 있다. 10-200룰이란 함수는 10줄 이내, 클래스는 200줄 이내로 만드는 것이다. 하지만 이를 엄격하게 지키기는 쉽지 않고, 아직은 이상향으로 여기는 수준이다. 현실적으로는 200줄이 넘어가면 혼자 머리 속에서 경보를 발령하고 더이상 안 늘어나게 노력하거나 리팩토링을 시도한다. 10-200룰은 실제로 시도해보면 정말 많은 고민을 하게하고 나를 불편하게 만드는 규칙이다. 하지만 그런 불편함을 극복해나가면서 배움이 생기는 것 같다.

우선 ‘함수는 10줄’ 룰을 지키려면 함수는 하나의 작업만 해야한다라는 대원칙을 지킬 수 밖에 없고 또 추상화 레벨에 대해 고민을 하게 된다. 추상화 레벨이란 얼만큼의 정보를 해당 함수에서 노출할 것인가 하는 것이다. 신라면 봉지 뒷면에 써있는 조리법을 살펴보자. 물 550ml를 끓인다, 면과 스프, 후레이크를 넣는다, 4분 30초 더 끓인다로 되어있다. 세 단계의 추상화 레벨이 비슷하다. 물을 끓이는 단계는 더 쪼개면 냄비를 꺼낸다, 정수기를 튼다, 물을 담는다, 가스렌지에 올린다, 불을 지핀다 등등이 있을 것이다. 하지만 이걸 라면 끓이는 법에 포함시키진 않는다. 왜냐면 그것들은 물 550ml를 끓인다라는 단계(함수)로 묶어서 표현했기 때문이다. 이런 식으로 작업(함수)을 어느 수준까지 쪼개서 설명(추상화)할 것인지에 대해 고민을 하게 만들어 준다.

‘클래스는 200줄’ 룰을 지키려면 프로퍼티나 함수, 메서드를 그냥 손이 가는 곳 아무데나 만들어서 쓸 수 없다. 꼭 얘가 이 곳에 있어야 하는 이유를 찾아야 한다. 해당 클래스에 있을 이유가 없으면 SRP 위반이다. 가장 쉽게 판단할 수 있는 방법 하나는, 함수나 메서드 내부에서 self의 프로퍼티나 메서드를 얼마나 쓰고 있는지 보는 것이다. 만약 하나도 쓰고 있지 않다면 그 클래스 안에 있을 이유가 전혀 없는 것이다. 또는 self의 호출 빈도가 적을수록 클래스와 연관성이 떨어지는 것이니 나중에 클래스를 리팩토링 하거나 다이어트 시켜야 할 상황이 오면 우선적으로 내쫓을 후보가 되는 것이다.

SRP를 모든 패턴의 시작이라고 한다. SRP를 제대로 지키지 못한 채로 코딩을 하면 그 어떤 패턴을 도입해보려고 해도 잘 안될 가능성이 높다고 한다. 클래스는 하나의 역할만 해야한다는 것, 객체지향을 배우면서 가장 먼저 배우는 원칙임에도 정말 지키기 쉽지 않은 것 같다.

Open-Closed Principle

개방폐쇄 원칙은 확장에는 열려 있으나 변경에는 닫혀있어야 한다는 원칙이다. 열려 있다는 것은 기능 추가나 변경을 할 수 있어야 한다는 것이고 닫혀있다는 것은 기능 추가를 할 때 그 모듈을 쓰고 있는 코드들을 줄줄이 수정하지 않아야 한다는 것이다. OCP 위반의 대표적인 예는 어떤 타입에 대한 반복적인 분기문이다. 즉, 하나의 enum에 대해 여러 군데에서 반복적으로 if/switch문을 쓰고 있다면 고민을 해봐야한다. 왜냐하면 이런 경우, 기능 추가는 case를 한줄 추가하는 것만큼이나 쉽지만 그렇게 하는 순간 해당 enum을 스위칭하고 있는 모-오든 코드를 찾아서 수정해줘야 한다. exhaustive하게 짰다면 그나마 컴파일러의 도움을 받을 수도 있겠지만 default문을 추가했다면 그것도 여의치 않다.

OCP는 if/switch를 최대한 안 쓰는 방법을 통해 연습할 수 있다. 모든 분기문을 없애는 것은 아니고(불가능하고) enum 같이 타입을 분기하는 지점에 대해서. 처음에 이 얘기를 들었을때는 말도 안된다고 생각했다. if문은 프로그래밍의 가장 기본 아닌가? 어떻게 if/switch 없이 분기를 할 수 있지? 처음엔 너무 어색하고 답답했지만 시도해보면서 어떤식으로 내 코드에 도움이 되는지 조금씩 느끼고 있다. 앞서 언급한 10-200룰과도 상호보완적이다. 분기문을 없애는 것 만으로도 함수 및 클래스의 길이를 많이 줄일 수 있다.

그러면 if/switch문을 대체할 수 있는 방법 두 가지를 소개한다. 첫번째로 protocol(혹은 class)을 만들고 상속받아 쓰는 방법이다. 이 방법이 직접적으로 OCP를 지키는 구조다. 더 자세한 내용은 이 블로그에 있는 내용을 참고하면 되겠다. 또 한가지 간단한 방법은 딕셔너리를 활용하는 것이다. 다만 이 방법은 OCP를 지키는 구조는 아니다. 얘는 default절이 있는 switch문과 동일한 약점이 있기 때문에 case가 자주 변경될 것 같을 때는 피해야하고, 분기문을 없애고 싶을 때 제한적으로 사용하면 좋을 것 같다.

기존 switch문 코드

switch reason {
  case .initializing:
    self.instructionMessage = "Move your phone".localized
  case .excessiveMotion:
    self.instructionMessage = "Slow down".localized
  case .insufficientFeatures:
    self.instructionMessage = "Keep moving your phone".localized
  case .relocalizing:
    self.instructionMessage = "Move your phone".localized
}

딕셔너리 활용하여 분기문을 없앤 코드

//적절한 곳에 딕셔너리 생성
let trackingStateMessages: [TrackingState.Reason : String] 
                         = [.initializing.        : "Move your phone".localized,
                            .excessiveMotion      : "Slow down".localized,
                            .insufficientFeatures : "Keep moving your phone".localized,
                            .relocalizing         : "Move your phone".localized]

//switch문 대체
self.instructionMessage = trackingStateMessages[reason]

Liskov Subtitution Principle

마지막(?)으로 리스코프 치환 원칙은 상위 타입(수퍼클래스)을 하위 타입(서브클래스)의 인스턴스로 바꿔도 프로그램의 동작을 해치지 않아야 한다는 원칙이다. 정의는 어렵지만 이를 지키기 위한 방법은 의외로 간단하다. 자식이 부모의 동작을 제한해서는 안된다. 전형적인 위반 사례로는 직사각형을 상속받아서 만든 정사각형 클래스를 생각하면 된다. 정사각형은 너비와 높이가 같아야 하기 때문에 너비와 높이를 자유롭게 바꿀 수 있는 직사각형 부모 클래스의 동작을 제한해야만 원하는 동작을 만들 수 있다. 이런 경우가 LSP의 위반이다. LSP를 지키기 위해서는 직사각형이 정사각형을 상속받거나, 아니면 너비와 높이를 아예 let으로 만들어버리면 된다. (값을 바꾸는 동작 자체를 없애버리면 제한할 동작이 없기 때문에)

iOS 프레임워크에서도 LSP 위반 사례를 찾아 볼 수 있는데,

var label = UILabel(frame: .zero)
var button = UIButton(frame: .zero)
var segmentedControl = UISegmentedControl(frame: .zero)
var textField = UITextField(frame: .zero)
var slider = UISlider(frame: .zero)
var switchButton = UISwitch(frame: .zero)
var activityIndicator = UIActivityIndicatorView(frame: .zero)
var progressView = UIProgressView(frame: .zero)
var stepper = UIStepper(frame: .zero)
var imageView = UIImageView(frame: .zero)

let views: [UIView] = [...] //위 뷰들을 UIView 어레이에 저장

views.forEach { $0.frame.size.height = 30 } //뷰들의 height를 30으로 변경

let height = views.reduce(0) { $0 + $1.frame.height } 
print(height) //과연 결과는?

10개의 UIView subclass들의 높이를 30으로 바꿨으니 300이 되길 예상할수도 있지만 실제 결과는 272다. 왜냐하면 일부 뷰들은 intrinsicSize를 마음대로 바꿀수 없게 되어 있기 때문이다. 이렇게 UIView(부모 타입)의 동작(높이를 바꾸는 것)을 제한하는 일부 뷰들(UIProgressView, UISwitch 등)이 바로 LSP 위반이다.

또한 iOS 개발을 하다보면 아래의 코드를 본 적이 있고 만들어낸 적도 있을 것이다. 이처럼 부모의 함수를 오버라이드해서 퇴화시켜 버리는 함수는 만들면 LSP 위반이다.

required init?(coder aDecoder: NSCoder) {
  fatalError("init(coder:) has not been implemented")
}

LSP를 절대 어기지 않고 프로그래밍을 하는 것은 어렵다. 하지만 너무 많은 곳에서 LSP를 어긴다면 문제가 생긴다. 상위 클래스를 기준으로 코딩할 수 없어지고, 그렇게되면 상속 자체가 의미가 없어지고 OCP조차 지킬수 없게 된다. 예를 들어 UITableView는 UITableViewCell을 기준으로 만들어져 있기 때문에 우리가 만든 커스텀 셀이 LSP를 지키지 않는다면 테이블뷰도 제대로 동작하지 않을 것이다. 또한 protocol를 만드는 이유도 추상화된 인터페이스를 기준으로 코드를 작성하기 위해서인데 상속받은 타입이 protocol의 메서드를 퇴화시켜버리면 프로토콜을 기준으로 작성된 코드들이 줄줄이 망가질 수 밖에 없다.

상속은 객체 지향 프로그래밍의 중요한 부분이고 잘 쓰면 유용하지만 잘못된 상속을 만들면 문제가 발생할 수 있다. 반면 때에 따라서는 LSP를 위반함으로써 편리함과 단순함을 얻게 될 수도 있다. 결론적으로, LSP를 모든 곳에서 지키려고만 하면 비효율적이고 너무 자주 위반하면 예상하지 못한 결과들 때문에 안정성을 해치게 된다. 그러므로 상속을 만들때는 LSP 위반인지 아닌지를 숙지하고 사용하는 것이 좋겠다.

결론

이 글의 목표는 SOLID 대원칙을 완벽히 이해하려는 것이 아니다. 게다가 모든 원칙을 철저히 다 지키는 코드만 짜려고 하는 것은 비효율적이라고 볼 수도 있다. 예를 들어 모든 것을 OCP로만 짜려고 하면 너어무 불편하다. 분기문을 쓰지 않으려고 매번 프로토콜을 만들고 상속을 해야한다면 개발하는 시간도 오래걸리고 불필요한 복잡성만 증가하는 꼴이다. 따라서 적절한 트레이드 오프가 필요하다. 다섯 가지 원칙 중에서 SRP와 OCP는 이해는 되지만 가장 지키기 어렵고 끊임없이 노력해야하는 부분인 것 같다. 무엇이 정답인지 모르고 헷갈릴때 확실히 정답이 아닌 것을 지워내는 것처럼, 위 원칙을 어기는 코드 습관을 파악해서 일단 그것부터 제거하고 개선해보려고 한다.

끝.

같이 보면 좋은 자료(코드 예제): OOD Principles in Swift, Design Patterns in Swift

이 글의 초안을 읽어준 김형중, 김찬희, 김창기님에게 고마움을 전합니다.

Tags: Objected Oriented Programming, SOLID, Swift, iOS  

스위프트 API 디자인 가이드라인 초초초-요약본

https://swift.org 에서 스위프트 API 디자인 가이드라인의 존재 이유를 다음과 같이 설명하고 있다.

스위프트 3.0의 출시 목표는 프로그래머에게 일관된 사용자 경험을 제공하기 위한 표준을 세우는 것이고, API에 등장하는 이름과 표현법을 통해 이를 달성하고 있다. 이 가이드라인은 여러분의 코드가 더 큰 스위프트 생태계의 일부인 것처럼 느껴지게 하는 방법을 설명하고 있다.

‘프로그래머의 사용자 경험’이라는 단어를 썼다는 것이 어색하기도 하고 놀랍기도 하고 한편으론 정말 애플스럽다. 그런데 왠지 익숙한 표현법 아닌가?

애플 플랫폼과 매끄럽게 어우러지는 훌륭한 앱을 디자인 하기 위한 … (후략)

잘 알려진 아이콘, 텍스트 스타일, 통일성 있는 용어, 시스템이 제공하는 인터페이스 요소들을 활용하여 유저에게 일관된 경험을 제공 … (후략)

Human Interface Guidelines에 등장하는 문장들이다. 최종 사용자들에게 좋은 사용자경험을 주는 애플 플랫폼 앱을 만들기 위해 따라야하는 것이 ‘휴먼 인터페이스 가이드라인’이라면, 스위프트 개발자에게 좋은 사용자경험을 주는 코드를 만들기 위해 따라야하는 것은 ‘스위프트 API 디자인 가이드라인’인 셈이다.

가이드라인에는 꽤 많은 내용이 담겨 있다. 그렇다고 문서가 눈에 쏙쏙 들어오는 편도 아니고 누구나 들었을때 ‘음 그렇지’라고 고개가 끄덕여지는 그런 내용도 아니다. 이런 이유로 가이드라인에 무슨 내용이 담겨 있는지, 어디서부터 시작해야될지 잘 모르겠는 분들이 많은 것 같다. 약 일 년 정도 API 디자인 가이드라인과 애플 개발자 문서를 옆구리에 끼고, 아니 모니터에 띄워놓고 개발했던 경험을 토대로 내 마음속 중요도 순으로 추리고 요약해봤다. 그룹핑도 적용 상황을 기준으로 내 마음대로 재구성했다.

⚠️ 가이드라인의 모든 내용을 담고 있지 않다. 한 20% 정도? 하지만 적용되는 빈도로 따지면 아래 내용들을 합치면 전체 케이스의 50%는 넘는 것 같다.

함수 및 프로퍼티 이름

  • 메서드나 함수는 사이드 이펙트의 유무에 따라 이름 짓는다.

    • 사이드 이펙트 없는 함수는 명사구로 읽혀야한다.

    ⛔️ 잘못된 예

      x.getDistance(to: y) //"y까지의 거리를 가져와라"
    

    ✅ 올바른 예

      x.distance(to: y) //"y까지의 거리"
    

    사이드 이펙트 없이 값을 리턴하는 메서드(일명 “getter”)에 get을 붙이는 것이 대표적인 가이드라인 위배이다. 코코아터치 프레임워크에서 get, fetch, request로 시작하는 메서드는 전부 completion handler를 받는 비동기 작업 뿐이다.

    참고 : Swift 개발자처럼 변수 이름 짓기

    • 사이드 이펙트가 있는 함수는 명령형 동사구로 읽혀야한다. (명령형이라는 것은 동사원형을 쓴다는 것이다.)
      print(x)
      x.sort()
      x.append(y)
    

    위 함수들은 모두 함수 스코프 밖에까지 영향을 미친다(사이드 이펙트). print는 콘솔에 찍히고 sort와 append는 x의 값을 바꿔버린다.

  • mutating과 nonmutating 메서드 쌍은 일관성있게 이름 짓는다. 보통 mutating 함수는 명령형 동사로 쓰고 nonmutating은 “ed”나 “ing”를 뒤에 붙여서 사용한다.

Mutating Nonmutating
x.sort() z = x.sorted()
x.append(y) z = x.appending(y)
  • Bool 메서드나 프로퍼티 이름은 인스턴스에 대한 평서문처럼 읽혀야한다.

    e.g. x.isEmpty, line1.intersects(line2)

    참고 : Bool 변수 이름 제대로 짓기 위한 최소한의 영어 문법

  • 대소문자 규칙을 따른다.

    • 타입이나 프로토콜은 UpperCamelCase를 따르고 그 외에는 lowerCamelCase를 따른다.
    • 대문자 약어는 낙타표기법에 따라 전체 대문자 혹은 소문자로 통일한다.
      var utf8Bytes: [UTF8.CodeUnit]
      var isRepresentableAsASCII = true
      var userSMTPServer: SecureSMTPServer
    

    우리가 많이 쓰는 대문자 약어 중에 URL이 이 조건에 해당될 것이다. 규칙을 따르려면 아래처럼 사용해야 한다.

      let urlString = "https://soojin.ro"
      let blogURL = URL(string: urlString)
    

파라미터명(Parameter Names)

파라미터 명명 규칙은 좀 더 세부적으로 생성자일 때와 메서드일 때로 나뉜다.

생성자

  • 생성자의 첫번째 파라미터명은 타입 이름과 구(phrase)를 이뤄서는 안된다. 다시 말해 생성자의 파라미터명에는 아래처럼 전치사나 접속사 등을 써서 문장처럼 이어지게 만들지 말라는 말이다.

    ⛔️ 잘못된 예

      let foreground = Color(havingRGBValuesRed: 32, green: 64, andBlue: 128)
      let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)
      let ref = Link(to: destination)
    

    대신 아래처럼 having, and, to, with 등의 단어들을 제거한다.

    ✅ 올바른 예

      let foreground = Color(red: 32, green: 64, blue: 128)
      let newPart = factory.makeWidget(gears: 42, spindles: 14)
      let ref = Link(target: destination)
    
  • 무손실 타입 변환(value preserving type conversion)을 하는 생성자는 첫번째 파라미터명을 생략한다. 추가적으로, 손실이 일어나는 타입 변환이라면 어떤 손실이 일어나는지 명시해주는 것을 추천한다.

    ✅ 올바른 예

      Int64(someUInt32)
      String(someNumber)
      String(someNumber, radix: 16)
      UInt32(truncating: someUInt64) //64비트 -> 32비트로 손실 발생 명시
    

즉, 무손실 타입 변환이 일어나는 생성자가 아니라면 첫번째 파라미터에는 이름을 꼭 부여한다.

메서드 및 함수

  • 첫번째 파라미터가 전치사(to, in, at, from, with 등등)구의 일부라면 파라미터명을 부여한다.

    ✅ 올바른 예

      x.removeBoxes(havingLength: 12)
      employees.remove(at: x)
    
  • 그렇지 않고 첫번째 파라미터가 자연스럽게 이어지면 생략한다.

    ✅ 올바른 예

      x.addSubview(y)
      allViews.remove(cancelButton)
      x.insert(y, at: z)
      x.append(y)
    
  • 그 외 모든 경우에는 파라미터 이름을 부여한다.

끝.

가이드라인 원본

가이드라인 번역본

Tags: Swift API Design Guidelines, abriged