Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

안드로이드 개발자를 위한 스위프트

9,104 views

Published on

안드로이드 개발자를 위한 스위프트

Published in: Software

안드로이드 개발자를 위한 스위프트

  1. 1. let swift(16) 안드로이드 개발자를 위한 스위프트 Swift & VIPER osxdev.org / todait유병한
  2. 2. 저는… 유병한 현재 투데잇에서 iOS 개발을 담당
 (하고 있지만 사실은 Android 개발자 🙈🙉) 이제는 iOS 개발자가 되고픔
  3. 3. 아니 Android 개발자가 왜 iOS 개발을...?
  4. 4. 회사에 iOS 개발자가 없어서... 😭
  5. 5. Agenda Swift를 사용하면서 Java에 비해 좋았던 부분
 (중요한 부분만 빠르게 알아봐요!) VIPER 아키텍처 적용 사례
  6. 6. let swift(16) Android 개발을 하면서 아쉬웠던 부분
  7. 7. Java ☕ Null Pointer Exception Getter / Setter Anonymous Class 복잡한 계산로직을 자유자재로, 가독성이 좋게 짜기 힘듦
  8. 8. Activity (== ViewController) 너무나 많은 역할을 하는 Activity View, Life Cycle, Navigation, Networking, DB, Business Logic, … 어떤 코드가 어디에 있는지 찾기 힘듦
 (== 뭣이 중헌지 모름) 이러한 구조로는 테스트도 불가능
  9. 9. 빚이되어 돌아오리… 💸 Dirty & Fast 모든 것이 빚으로 돌아옴 버그라던지. 버그라던지.. 버그라던지...
  10. 10. 인간의 욕심은 끝이 없고
  11. 11. 같은 실수를 반복한다
  12. 12. 같은 실수를 반복하지 말자! 🤔
  13. 13. let swift(16) Swift
  14. 14. Swift Optional Type Property Closure & Functional Protocol & Extension
  15. 15. Java, 넘나 위험한 것! ⚠ Optional Type
  16. 16. Optional Type이란? 타입 선언 시 변수에 nil이 저장될 수 있는지 여부를 명시 var nonOptional: Int = 0 nonOptional = nil // Compile Error! var optional: Int? = 0 optional = nil // OK!
  17. 17. Optional Chaining let viewController = UIViewController() print(viewController.navigationItem.backBarButtonItem?.title?.characters.count) print(viewController.navigationItem.backBarButtonItem?.title ?? "Title")
  18. 18. Optional Binding - if let if let viewController = viewController as? UITableViewController { viewController.tableView.reloadData() }
  19. 19. Optional Binding - if let if let viewController = viewController as? UITableViewController, refreshControl = viewController.refreshControl { refreshControl.beginRefreshing() }
  20. 20. Optional Binding - if let if let viewController = viewController as? UITableViewController, refreshControl = viewController.refreshControl where refreshControl.refreshing { refreshControl.beginRefreshing() }
  21. 21. Optional Binding - guard let func signUp1(email: String?) { guard let email = email else { return } print(email.characters.count) }
  22. 22. Optional Binding - guard let func signUp(email: String?, password: String?) { guard let email = email, password = password else { return } print("(email) / (password)") }
  23. 23. Optional Binding - guard let func signUp(email: String?, password: String?) { guard let email = email, password = password where 8 <= password.characters.count else { return } print("(email) / (password)") }
  24. 24. Optional Binding - switch let passwordText: String? = "" switch(passwordText) { case .Some(let password) where 8 <= password.characters.count: print(password) case .Some: print("8자리 이상 입력해주세요") case .None: print("password is nil") }
  25. 25. 이제는 안녕 Getter, Setter 🙋 Property
  26. 26. Stored Property struct Box { let width: Double let height: Double let depth: Double }
  27. 27. Stored Property struct Box { var width: Double { willSet { print("newValue: (newValue)") } didSet { print("oldValue: (oldValue)") volume = width * height * depth } } var height: Double { ... } var depth: Double { ... } var volume: Double }
  28. 28. Computed Property struct Box { var width: Double var height: Double var depth: Double var volume: Double { get { return width * height * depth } set { print("newValue: (newValue)") } } }
  29. 29. Computed Property struct Box { var width: Double var height: Double var depth: Double var volume: Double { return width * height * depth } }
  30. 30. for, if의 늪에서 나를 구해줘요! 😱 Closure & Functional
  31. 31. 객체로서의 함수 함수의 인자로 함수를 넘길 수 있음 함수의 결과로 함수를 반환할 수 있음
  32. 32. Closure 사용과 타입 추론 Closure는 이름이 없는 함수 var sum = [1, 23, 4, 32].reduce(0, combine: { (sum: Int, element: Int) -> Int in return sum + element })
  33. 33. Closure 사용과 타입 추론 타입이 명확한 경우 생략 가능 extension SequenceType { /// Returns the result of repeatedly calling `combine` with an /// accumulated value initialized to `initial` and each element of /// `self`, in turn, i.e. return /// `combine(combine(...combine(combine(initial, self[0]), /// self[1]),...self[count-2]), self[count-1])`. @warn_unused_result public func reduce<T>(initial: T, @noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> T } var sum = [1, 23, 4, 32].reduce(0, combine: { (sum: Int, element: Int) -> Int in return sum + element })
  34. 34. Closure 사용과 타입 추론 sum = [1, 23, 4, 32].reduce(0, combine: { sum, element in return sum + element }) sum = [1, 23, 4, 32].reduce(0, combine: { return $0 + $1 }) sum = [1, 23, 4, 32].reduce(0, combine: { $0 + $1 }) sum = [1, 23, 4, 32].reduce(0) { $0 + $1 } sum = [1, 23, 4, 32].reduce(0, combine: +)
  35. 35. 투데잇에서의 Functional 통계 계산 로직에서 적극적으로 사용 대용량 데이터를 다루는 것이 아닌 유저 한사람의 데이 터 그 중에서도 특정 날짜의 데이터를 주로 다룸 스레드 처리만 잘 해주면 사용자 체감 상 크게 문제될 상 황은 없음 퍼포먼스도 물론 중요하지만 오류 없고, 가독성이 높고, 수정이 용이한 코드가 필요 map, flatMap, filter, reduce, contains ...
  36. 36. Protocol & Extension
  37. 37. Property&Method Requirements Property & Method 에 대한 명세 protocol Flyable { var distance: Int { get set } func fly() } struct SwiftBird: Flyable { var distance: Int func fly() { print("flying!") } }
  38. 38. Protocol with an Extension Protocol은 Property를 가질 수 없지만 Method는 가질 수 있음 protocol ViewControllerProtocol: class { var loadingView: LoadingView { get set } } extension ViewControllerProtocol where Self: UIViewController { func showLoadingView() { loadingView.showLoadingView(self) } func dismissLoadingView() { loadingView.dismissView() } }
  39. 39. let swift(16) VIPER
  40. 40. 좋은 Architecture는? Distribution Testability Ease of Use
  41. 41. VIPER 구성요소 View Presenter Router Interactor Entity
  42. 42. DataService Todait의 VIPER 구성요소 View Presenter Router Interactor Entity ViewModel DataService
  43. 43. DataService View Presenter Router Interactor Entity ViewModel DataService
  44. 44. View UIViewController에 해당 View Life Cycle
 ex) viewDidLoad 함수가 호출되었음을 Presenter에 알림 View Event
 ex) signUpButton이 클릭되었음을 Presenter에 알림 View Control
 ex) titleLabel의 텍스트를 바꾸는 방법을 Presenter에 제공
  45. 45. DataService View Presenter Router Interactor Entity ViewModel DataService
  46. 46. Presenter View와 Interactor의 중간 다리 역할 View에 대한 비즈니스 로직 Life Cycle에 대한 처리 View Event에 대한 처리 View 업데이트 UIKit Independent
  47. 47. DataService View Presenter Router Interactor Entity ViewModel DataService
  48. 48. Interactor Data(Entity)에 대한 비즈니스 로직
  49. 49. DataService View Presenter Router Interactor Entity ViewModel DataService
  50. 50. Entity 네트워크, DB 등의 데이터 모델 Realm Object, NSUserDefuatls, Json Data 등 Interactor에서 사용
  51. 51. DataService View Presenter Router Interactor Entity ViewModel DataService
  52. 52. Router View 간의 전환 VIPER 컴포넌트들의 DI(Dependency Injection)를 담당
  53. 53. DataService View Presenter Router Interactor Entity ViewModel DataService
  54. 54. DataService Network 요청, DB 접근, UserDefaults, 이미지 처 리 등 반복되는 코드를 모듈화 Interactor가 호출함
  55. 55. DataService View Presenter Router Interactor Entity ViewModel DataService
  56. 56. ViewModel View에 나타나는 데이터와 1:1 매칭 Entity가 어떻게 View에 바인딩될지 정의 Interactor에서 생성되어 Presenter로 전달
  57. 57. VIPER Flow 가입하기 버튼을 눌려 회원가입을 완료하는 과정
  58. 58. DataService presenter.onClickSignUpButton() View Presenter Router Interactor Entity ViewModel DataService
  59. 59. DataService viewController.showLoadingAlert() View Presenter Router Interactor Entity ViewModel DataService
  60. 60. DataService interactor.signUp(signUpViewModel) View Presenter Router Interactor Entity ViewModel DataService
  61. 61. DataService signUpViewModel.checkValidation() View Presenter Router Interactor Entity ViewModel DataService
  62. 62. DataServic serverService.signUp(email, password) View Presenter Router Interactor Entity ViewModel DataService
  63. 63. realmService.saveUserData() DataService View Presenter Router Interactor Entity ViewModel DataService
  64. 64. presenter.onSignUpSucceed() / presenter.onSignUpFailed() DataService View Presenter Router Interactor Entity ViewModel DataService
  65. 65. viewController.dismissLoadingAlert() DataService View Presenter Router Interactor Entity ViewModel DataService
  66. 66. router.dismissViewController() DataService View Presenter Router Interactor Entity ViewModel DataService
  67. 67. VIPER with Swift - Protocol protocol ViewControllerProtocol: class { var loadingAlert: LoadingAlert { get set } } extension ViewControllerProtocol where Self: UIViewController { func showLoadingAlert() { loadingView.showLoadingAlert(self) } func dismissLoadingAlert() { loadingView.dismissAlert() } }
  68. 68. VIPER with Swift - Computed Property protocol SignUpViewControllerProtocolForPresenter: class { var email: String? { get set } var password: String? { get set } } extension SignUpViewController: SignUpViewControllerProtocolForPresenter { var email: String? { get { return emailTextField.text } set { emailTextField.text = newValue } } var password: String? { get { return passwordTextField.text } set { passwordTextField.text = newValue } } }
  69. 69. 장점 하나의 화면에서 기능 단위로 코드를 명확하게 분리 (물론 모든 컴포넌트에 대해 테스트를 하고 있지 않 지만) 모든 컴포넌트에 대해 테스트 가능해지는 구조 가됨 (물론 혼자 개발하고 있지만) 분업이 훨씬 수월해짐
  70. 70. 단점 간단한 화면, 간단한 기능에 대해서도 작성해야할 코 드가 늘어남
  71. 71. Next Step Code Generator RxSwift, KVO Android에도 적용
  72. 72. Swift로 iOS 앱 개발을 하면서 느낀 점 Swift 정말 최고! UI가 있는 어플리케이션 만든다는 관점에서 큰 동작 원리는 Android나 iOS나 비슷한 것 같음 iOS에도 문제가 많다고 하지만 안드로이드에 비할바 는 아닌 것 같음 훨씬 평화로운 iOS! 피쓰~ 🕊
  73. 73. 투데잇의 성장을 함께할 당신을 기다리고 있습니다. i O S 개 발 을 박 ♥ 살 내 주 실 당 신 !
  74. 74. let swift(16)

×