2022 신입 공채 iOS 기술 온보딩을 소개합니다.

안녕하세요, 2022 신입 공채 개발자 vapor입니다. 저는 mac에서 카카오톡을 개발하는 macOS 직무를 맡게 됐습니다. 이번 글에서는 카카오 iOS & mac 뉴크루를 위한 기술 온보딩은 무엇이고, 무엇을 배웠는지 공유하고자 합니다.



iOS 기술 온보딩 소개

카카오 문화를 경험하고 이해하며 4주의 프리온보딩 시간을 보냈다면, 이제 6주의 기술온보딩에 참여하게 됩니다. 이때는 해당 직무경험이 없는 크루들이 직무를 이해하고, 경험하여 직무에 잘 적응할 수 있는 것을 목표로 합니다. 

iOS 기술 온보딩은 Swift 언어를 익히고, iOS 앱 개발 환경을 이해하며, 기초적인 앱 개발 기술을 익혀 향후 스스로 학습하며 업무할 수 있는 발판을 마련할 수 있도록 합니다.

6주 동안 이런 것을 했어요

라이브세션 

‘스위프트 프로그래밍’ 저자께서 직접 진행해 주셨습니다. iOS를 공부하고 계신 분이라면 누구나 아는 유명하신 야곰님이시죠. 매주 2번 화상회의를 통해서 iOS 개발하기 위한 중요한 개념들을 설명해 주시고 궁금한 질문들을 친절하게 알려주십니다.

뉴크루와 야곰이 함께 화상회의를 이용하여 참석하고 있는 사진입니다 😎


그룹 활동 학습 

매주 2번 iOS 및 mac OS 직무의 뉴크루들이 짝을 지어, 프로젝트에 적용해야 하는 개념 위주로 함께 미션을 수행합니다. 우선 강의자분께서 개념을 설명해 주시고, 이해한 개념을 바탕으로 특정 미션을 수행합니다. 미션 수행 후 다른 그룹과 결과를 공유하는 시간도 갖습니다.

brendan과 제가 함께 열심히 미션을 수행하고 있는 사진입니다 😎


프로젝트 

매주 새 프로젝트를 진행하게 되는데, 주로 라이브 세션에서 설명해 주신 개념들을 적용하게 됩니다.

뿐만 아니라 뉴크루가 추가적으로 학습해야 하는 개념들도 많습니다. 🥲 ( 하지만 저희는 카카오니까 매우 재밌게 공부했습니다(?) )  중간중간 프로젝트를 수행하면서 PR을 통해 코드 리뷰를 진행합니다. 코드 리뷰를 통해서 단순히 프로젝트 구현의 목적을 넘어서 깊이 있는 고민을 하게 됐습니다.

이런 것을 만들었어요

로그인 화면

iOS의 레이아웃을 이해하기 위해 간단한 로그인 화면을 구현했습니다. 화면 구성요소는 간단하지만, 개념적으로 중요한 부분들을 적용시킨 프로젝트입니다. 오토 레이아웃을 이용하여 레이아웃을 구성했습니다. 

또한 사용자에게 좋은 경험을 제공하면서 다른 앱과의 차별성을 줄 수 있는 방법도 적용했습니다. Dynamic Type를 통해서 시스템 폰트 크기에 대응했고, Localizing을 통해서 다국어 처리도 가능하게 했습니다.


만국 박람회

iOS 개발에 있어서 가장 중요하면서도 어려운 UITableView를 이용하여 리스트 형식으로 스크롤 가능한 화면을 구현했습니다. 내부 화면들은 좀 더 쉽게 뷰들을 배치가 가능한 StackView를 이용했습니다.


메모장

이번 프로젝트에서는 러닝 커브가 높지만 아주 중요한 CoreData를 이용하여 사용자가 작성한 메모들을 로컬에 저장할 수 있도록 했습니다. 추가적으로 Size Class를 이용하여 디바이스마다 또는 같은 디바이스에서도 회전에 따라 레이아웃을 다르게 보여주도록 했습니다.


오픈마켓

그동안 배운 개념들을 모두 적용시켜 구현한 가장 어려운 프로젝트입니다. UITableView 만큼 중요한 UICollectionView를 이용하여 바둑판 형식으로 스크롤 가능한 화면을 구현했고, 마지막 프로젝트인 만큼 서버와 통신을 했는데요, URLSession을 이용하여 데이터들을 가져오고, 서버에 업로드했습니다.


가장 힘들었던 기술적 문제

Delegation Pattern

iOS, mac 개발을 하다 보면 필수적인 패턴이 있는데, 그중 하나가 Delegation Pattern입니다. 저는 Delegation Pattern 개념을 이해하는 데 있어서 굉장히 낯설었습니다.

Delegation Pattern은 주로 특정 객체(Object)가 받는 이벤트를 다른 객체(Delegate)에 전달하기 위해 사용됩니다. 이때 객체 (Object)가 받는 이벤트를 정의하는 데 있어서 Protocol을 이용합니다.

구현 과정

  1. Object가 이벤트가 발생했을 때 알리고 싶은 작업을 Protocol에 정의합니다.
  2. DelegateObject가 정의한 Protocol을 채택하여 구현합니다. 
  3. Object는 정의한 Protocol 타입을 객체로 가지고 있습니다.
  4. DelegateObject를 생성할 때, ObjectProtocol 타입 객체에 자기 자신을 할당합니다. 

이후 Object에서 특정 이벤트가 발생했을 때, Object는 자신이 가지고 있는  Protocol 타입의 객체를 호출하게 되면, Delegate에서 구현한 메소드가 호출됩니다! 

예로 들면, UIViewController 안에 UITableView를 구현했습니다. 그런데 UITableView의 Cell에 터치 이벤트를 받고 싶습니다. 특정 Cell의 터치 이벤트를 이용하여  상세화면을 보여주고 싶습니다.


이때 Delegation pattern을 사용해야 하는데,
UITableView은 내부적으로 delegate 객체를 가지고 있습니다.

이 객체는 UITableViewDelegate 프로토콜 타입입니다.


Delegation Pattern을 사용할 때는 Protocol을 이용하여 정의한다고 했습니다. 
무엇을 정의 해야할까요? 아무래도 “특정 Cell을 선택 또는 터치한다”라는 정의가 필요할 것 같습니다.

마침 UITableVIewDelegate에는 didSelectRowAt이라는 메소드가 정의되어 있군요!


그러면
UIViewControllerUITableView가 정의한 UITableViewDelegate를 채택하여 didSelectRowAt을 구현합니다.

그리고 UITableViewdelegate 객체에 자기 자신을 할당합니다.

그러면 사용자가 특정 Cell에 터치를 하게 되면 시스템에서는 UITableView의 delegate를 호출하게 되고, UIViewController가 구현한 메소드가 호출되면서 처리할 수 있게 됩니다! 그래서 UIViewController, UITableView, UITableViewDelegate는 다음과 같이 정리할 수 있겠네요!


Auto Layout & Intrinsic Content Size

Intrinsic Content Size

오토 레이아웃을 이용하여 뷰들간의 관계를 맺다 보면 AutoLayout warning 이 종종 나타나게 됩니다. ( 말 그대로 에러가 아닌 워닝이라서 무시할 수도 있습니다. 화면에서도 그다지 문제가 되지 않아 보이는 경우도 있거든요. 하지만 나비효과처럼 하나의 작은 워닝이 원하는 화면이 나타나지 않을 수 있습니다. ) 저희는 (카카오) 개발자이므로 워닝이 나는 이유를 알아야 합니다!

UILabel 뷰는 스토리보드에서 오토 레이아웃을 이용하여 centerX, Y를 주어도 문제가 없습니다.

반면 UIView를 위와 같이 centerX, Y를 주게 되면 빨갛게 나타나며 위험해 보입니다(?).


친절하게도 Xcode에서는 그 이유를 알려주는데요, View가 x위치나 width 그리고 y위치나 height를 가져야 한다고 알려주고 있습니다.


여기서 알 수 있는 점은 UILabel은 x위치나 width, y위치나 height를 주지 않아도 된다는 걸 알 수 있는데요, Intrinsic content size를 직역해도 본래의 콘텐츠 사이즈로 해석되고, 그러므로 UILabel은 width, height를 기본적으로 가지고 있다고 이해할 수 있습니다. 그래서 UILabel은 사이즈에 대해 별다른 오토레이아웃을 지정하지 않아도 문제가 없던 것이죠. (UILabel은 text를 기반으로 Intrinsic content size가 정해지게 됩니다.)

UILabel뿐만 아니라 특정 뷰들은 Intrinsic Content Size를 갖고 있습니다.

Apple – Intrinsic Content Size


Intrinsic Content Size를 이해했다면, 다음 예시를 보죠. 뷰가 UILabel인 A, B가 있습니다. A, B의 width를 정해주지 않은 상태에서 유연하게 대응하기 위해
A의 width가 늘어나길 기대하면서 “A의 오른쪽은 B의 왼쪽보다 20만큼 떨어져라”라고 명시하게 되면 빨갛게 나타나게 됩니다.



고민을 해보면, 왜 이런 문제가 나타나는지 알 수 있습니다. 둘 다 같은 UILabel이고, Intrinsic Content Size를 서로 가지고 있으므로, 20만큼 떨어지라고 하게 되면 Intrinsic Content Size와 충돌이 나는 거죠.

Content Hugging & Compression Resistance

오토 레이아웃은 위와 같은 문제점을 해결하기 위해 Intrinsic Content Size를 이용하여 Content Hugging과 Compression Resistance 두 가지 개념을 만들었습니다. 각 개념들은 0~1000까지의 값을 가지게 되고, 값의 차이에 따라 특정 뷰가 늘어나거나 줄어들 수 있습니다.

두 가지 개념은 늘 헷갈려서 저는 다음과 같이 이해했습니다.

  • Content Hugging이 높을수록 본래의 자신의 사이즈가 늘어나지 않도록 한다.
    • 반대로 낮을수록 본래의 자신의 사이즈가 늘어나게 한다.
  • Compression Resistance가 높을수록 본래의 자신의 사이즈가 줄어들지 않도록 한다. 
    • 반대로 낮을수록 본래의 자신의 사이즈가 줄어들게 한다.


저는 처음부터 A와 B의 오토 레이아웃 관계를 명시할 때, A의 width가 늘어나길 기대했기 때문에 A의 Content Hugging의 Horizontal을 B의 Content Hugging의 Horizontal 보다 낮은 값을 주면 될 것 같습니다. 

그러면 제가 원하는 화면이 나타나게 되고 빨간색도 없어지게 되죠! 

가장 간단한 이슈를 언급했지만, 이러한 원리를 이용하면 꽤나 많은 부분들을 대응할 수 있게 됩니다. 예를 들어 StackView 안에서도 특정 뷰가 늘어나게 하거나, 줄어들게 할 수도 있겠죠.

View Life Cycle 

iOS에서 앱을 만들기 위해서 가장 중요한 개념 중 하나는 UIViewController라고 생각합니다. 뷰 계층구조를 관리하며, 뷰들과의 사용자 인터렉션에 반응하고, 뷰들의 레이아웃을 관리하고, 다른 뷰 컨트롤러와도 연관되어 있고 관리를 할 수 있습니다. 

대부분의 앱들은 하나의 뷰 컨트롤러로 만 이루어져 있지 않습니다. 아래의 사진처럼 다른 화면으로 전환하는 경우가 굉장히 많습니다.


이때 애플에서는 뷰 컨트롤러와 뷰 컨트롤러가 전환되는 사이에 다양한 이벤트를 받을 수 있는 API를 아래와 같이 제공하고 있습니다.

develoep.apple.com

 

각 API들은 뷰 컨트롤러의 현재 상태를 의미합니다. 

  • viewWillAppear,  viewDidAppear, viewWillDisappear, viewDidDisappear
  • 네이밍 그대로 뷰가 나타날 건지, 나타났는지, 사라질 건지, 사라졌는지를 의미합니다.
  • 네이밍이 view로 시작하는 이유는 뷰 컨트롤러는 항상 root view를 가지고 있기 때문입니다.


그래서 저희는 이 API를 이용하면 다양한 처리를 할 수 있게 됩니다. 예를 들어 처음 뷰 컨트롤러로 다시 돌아올 때 데이터를 갱신하고 싶은 경우가 있겠죠. 사용하는 방법으로는 뷰 컨트롤러가 해당 메소드를 오버라이딩하면 됩니다.



재미있는 점이라면, 항상 모든 상황에서 해당 API가 호출되지 않는 점인데요, 예를 들어,

(A) NavigationController에서 AViewController를 보여주고 있습니다. 이때 새로운 BViewController를 push하여 보여준 다음, 다시 뒤돌아가는 경우에 AViewController에서 viewWillAppear이 호출이 됩니다.


(B) 하지만 새로운 BViewController를 push가 아닌 present로 기본 modal로 보여주고 난 후 BViewController를 내리게 되면 AViewController에서는 viewWillAppear이 호출되지 않습니다.


그래도 저희는 직관적으로 나름 이해할 수 있습니다. BViewController가 나타났을 때 AViewController가 화면에서 이미 보인다면 돌아올 때는 viewWillAppear이 호출되지 않는다라고 알 수 있죠. ( modal 방식으로는 AViewController가 살짝 뒤로 숨겨져있는 걸 볼 수 있죠 )

하지만 개발자라면 직관보다는 근거를 찾을 필요가 있습니다. viewWillAppear의 메소드 정의를 살펴보면, 

“뷰 컨트롤러의 뷰가 뷰 계층구조(view hierarchy)에 추가될 때 알린다”라고 나와있습니다. 우리가 직관적으로 이해한 바와 다르게 어려운 말로 나와있군요! 🥲


뷰 계층구조 – view hierarchy 


모든 뷰들은 부모와 자식 구조로 계층구조를 이루고 있습니다. 뷰는 오직 하나의 부모 뷰만을 가지고 있습니다. 뷰 계층구조는 아래 이미지처럼 스토리보드에서도 확인이 가능합니다. 

좀 더 자세하게는 런타임 중에 View Debug Hierarchy에서 확인이 가능합니다.


그러면 현재 보이고 있는 화면과 계층구조를 확인할 수 있습니다. AViewController가 뷰 계층구조에 있는 걸 확인할 수 있군요!


다시 본론으로 돌아오면, viewWillAppear은 뷰 계층구조에 추가될 때 호출된다고 했습니다. 저희는 뷰 계층구조가 무엇인지 알았으니, (A) 경우에 NavigationController에서 새로운 뷰 컨트롤러를 push 한 상황에서는 뷰 계층구조에 AViewController가 없다는 의미겠죠. 확인해 볼까요?!

🎉 눈을 씻고 찾아봐도 BViewController만 존재하고, AViewController가 보이지 않습니다!!

그러므로 다시 AViewController로 돌아올 때는 계층구조에 AViewController가 없으니, 추가함으로써 viewWillAppear이 호출되는 것이죠.

그럼 (B) 경우에서는 새로운 BViewController를 present로 띄우면 AViewController는 뷰 계층구조에 남아있어야겠죠?? 한번 확인해 보죠.

🎉 정말로 AViewController가 계층구조에 속하고, BViewController도 계층구조에 속하는 것을 확인할 수 있습니다.


그러므로 BViewController를 화면에서 없애도 AViewController는 뷰 계층구조에 남아있기 때문에 viewWillAppear이 호출되지 않는 걸 알 수 있습니다. 

이렇게 실제로 View Debug Hierarchy를 이용하여 런타임의 뷰 계층구조를 확인할 수 있고, 실제 뷰 계층구조의 변화를 통하여 API의 정의를 이해할 수 있습니다.


– Quiz 

present로 다른 뷰 컨트롤러를 띄우는 방식에는 다양한 스타일이 있습니다. 여기서 fullScreen과 overFullScreen의 차이는 무엇일까요?! 👀 해당 스타일로 띄운 뷰 컨트롤러를 화면에서 없애면 기존 뷰 컨트롤러의 viewWillAppear이 호출될까요?? 그렇지 않다면 근거는 무엇인가요?!  (충분히 답을 찾을 수 있으리라 생각합니다~! ) 


이런 경험! 좋았어요


공식 문서

저는 카카오에 입사하기 전에 iOS를 공부했었는데요, 늘 기능 구현에만 급급했습니다. 그래서 필요한 API들의 이해를 제대로 갖추지 않고서 사용하거나 오류가 생길 때 제대로 대응하지 못하고 다른 사람이 정리해둔 글을 보느라 바빴는데요, 이는 매우 좋지 않은 습관입니다. 한 단계 성장하기 위해서는 이러한 습관을 버려야 한다고 생각합니다. 습관을 버리는 가장 좋은 방법으로는 공식 문서를 보는 거라고 생각합니다. 단순히 공식 문서를 보는 것을 넘어서 고민하며 이해하는 과정이 가장 중요하다고 생각합니다.

앱을 만들기 위해서는 애플에서 제공하는 프레임워크를 이용해야 합니다. 그 뜻은 애플에서 제공하는 프레임워크를 알아야 사용할 수 있겠죠. 그래서 애플은 개발자들이 프레임워크를 이해하며 사용할 수 있도록 공식 문서 (developer.apple.com)를 만들었습니다. 여기에는 프레임워크에 사용되는 많은 기능들의 개념과 어떻게 사용하는지 등 안내되어 있습니다. 어려운 개념도 보다 보면 익숙해지고 이해하게 되듯이 공식 문서도 마찬가지입니다. 처음에는 굉장히 낯설고, 내용도 많으며, 한 번에 원하는 내용을 찾기란 쉽지 않습니다. 하지만 시간을 두면서 계속 보다 보면 노하우가 생기게 되고, 비로소 개발하면서 오류를 마주할 때 공식 문서를 통해서 해결할 수 있게 됩니다.

이번 기술 온보딩에서 강의할 때나 미션을 수행할 때 대부분 공식 문서를 참고했습니다. 이러한 경험을 통해서 어떻게 공식 문서를 참고하는지, 공식 문서가 얼마나 중요한지를 다시 한번 깨닫게 됐습니다. 개발에 있어서 필요한 기능이 있다면, 이 기능의 개념은 무엇인지, 이 기능을 구현하기 위해서는 어떻게 사용하는지, 구현하기 위해 사용된 코드의 의미는 무엇인지를 중점으로 보다보면 자연스럽게 누구의 도움 없이 공식 문서만을 통해서 직접 구현할 수 있게 될 겁니다! 

 

코드 리뷰

저희는 프로젝트를 진행하면서 매번 PR을 통하여 코드 리뷰를 받았는데요, 굉장히 장점이 많았습니다. 자신이 작성한 코드가 다른 동료에게 리뷰를 받는다고 생각할수록 자신의 코드에 대해 고민을 할 수밖에 없습니다. 저는 주로 지금 코드가 동료가 봤을 때 쉽게 이해할 수 있는 코드인가를 중점으로 두었습니다. 이런 관점에서 코드를 보다 보면 네이밍을 통해서 쉽게 문맥이 유추가 가능한지, 실제로 내부 코드가 네이밍과 일치하는 일을 하는지, 코드가 일관성이 있는지 등을 고민하게 됐습니다. 그럼으로써 자연스럽게 리팩토링도 하게 됩니다. 저는 “코드는 살아있다”라고 생각합니다. 지금 작성한 코드는 불변하지 않으며 시간이 지날수록 바뀔 수밖에 없기 때문입니다. 즉 나중에 여러 요인을 통해서 코드를 다시 보게 되는 상황이 생기게 됩니다. 자신의 코드도 하루 뒤면 까먹는데 몇 주 혹은 몇 개월 뒤의 코드는 더더욱 이해하기가 어렵겠죠. 그래서 최대한 쉽게 이해할 수 있는 코드가 된다면 나중에 코드를 보더라도 이해하는데 있어서 훨씬 시간이 단축될 것 입니다.

실제로 리뷰어가 가독성이 좋은 코드였다고 코멘트 남겨줄 때 굉장히 기분이 좋았습니다. 감사합니다!


리뷰어가 리뷰를 하다 보면 개선점이나 궁금증을 코멘트로 다는데요, 여기서 미처 제가 생각하지 못한 관점을 볼 수 있고, 내가 작성한 코드에 대해 이유를 설명할 수 있는지에 대해 고민하게 됩니다. 이전에는 단순히 코드를 작성했다면, 이제는 “왜?”라는 의문을 스스로 품으면서 이 메소드가 맞는지, API를 내가 이해하고 있는 상태에서 사용하고 있는지, 이후 스펙이 추가되는 상황에서도 최대한 변경을 줄일 수 있는지를 계속 고민하는 과정이 생겼습니다. 

또한 프로젝트의 관점에서도 장점이 있다고 생각하는데요, 현업에서는 하나의 프로젝트를 주로 여러 명의 개발자가 같이 개발을 하는데, 당연히 다른 사람이 작성한 코드에 대해서는 잘 모르는 경우가 많겠죠.   하지만 코드 리뷰를 통해 자신이 직접 구현하지 않은 코드에 대해서 이해가 생기고, 코드를 작성한 사람이 미처 발견하지 못한 버그나 앞으로 발생할 수 있는 이슈들을 리뷰어가 찾을 수도 있다고 생각합니다.


그룹 활동학습

강의자 분께서 미션을 수행하기 위해 필요한 개념을 간단하게 설명해준 뒤 그룹으로 짝을 지어 스스로 추가적인 개념들을 공부하고 미션을 수행했습니다. 떠먹여주듯 필요한 기능들을 모두 설명하는 강의와 다르게 저희가 주체적으로 고민하면서 필요한 기능들을 살펴보며 미션을 해결해 나간 점이 가장 큰 경험이었습니다. 중간중간에 강의자 분께서 “왜?”라는 질문을 남겨주시는 것도 큰 도움이 됐습니다. 때로는 정답이 없는 질문도 있지만 자신이 생각한 답에 대해 나름대로 근거 있는 이유를 찾아가는 과정 자체가 중요하다고 생각합니다. 

미션은 혼자가 수행하는 것이 아니기 때문에 제가 미처 모르는 부분을 다른 뉴크루한테서 얻을 수 있었습니다. 카카오에는 5가지 문화가 있는데 그중 하나가 “나보다 동료의 생각이 더 옳을 수 있다는 믿음을 가지는 것”입니다. 혼자 가면 빨리 갈 수 있지만, 함께 가면 멀리 갈 수 있다는 말을 다시 한번 깨닫게 되었습니다.


서로 다른 의견이 충돌하는 경우는 논리적으로 생각하면서 제 생각 또는 다른 분의 의견을 수용하기도 했습니다. 일방적인 수용이 아닌 토론의 과정을 거치면서 받아들임으로써 자신의 생각을 어떻게 잘 설득시킬 수 있는지, 근거가 있는지 등을 생각하게 됐습니다.

Pair Programming

사실 저는 카카오에 입사하면서 처음으로 Pair Programming ( 이상 짝 프로그래밍 )을 처음 접했는데요, 굉장히 신선하면서 재밌고 좋은 경험이였습니다. 하나의 코드를 두 명이서 짝을 지어서 작성하는데요, 한 명은 Navigator가 되며 방향성을 제시하며, 나머지 한 명은 Driver가 되어 코드를 작성합니다. 

저는 짝 프로그래밍을 하면서 얻게 되는 장점이 굉장히 많았습니다. 우선 실시간으로 코드를 작성하다 보니 바로바로 의문점이나 개선점을 제시할 수 있었습니다. 그럼으로써 이슈가 발생했을 때도 빠르게 해결할 수 있었습니다. 제가 미처 생각하지 못했던 부분을 다른 사람에게서 들을 수 있기 때문입니다. 마지막으로 서로가 코드에 대해 이해가 높아집니다.

기술 온보딩 회고

뉴크루 분들과 함께 회고하는 시간을 가졌었는데, 그때 한 뉴크루가 우스갯소리로 “돈을 내야 하는 강의를 돈을 받으면서 들을 수 있어서 좋았다”라고 했습니다. 그만큼 온보딩 과정이 굉장히 값진 경험이었기 때문이겠죠. 저는 이번 기술 온보딩에서 6주 동안 iOS 개발에 중요한 개념들을 배웠고 앞으로 좋은 개발자가 되기 위한 과정도 깨달았습니다. 저에게 있어서도 기술 온보딩이 굉장히 값진 경험이었고, 이 경험을 기반으로 앞으로 현업에서 빠르게 적응하고, 늘 생각하는 개발자가 되겠습니다. 

끝으로 기술 온보딩 동안 같이 참여한 brendan, chesire, claire, hayden, joel, liam, wily 모두 각 부서에서 잘 적응하고 성장하길 기원합니다.

Latest Posts