전체 글

전체 글

    CI/CD 구현 ( fastlane, github actions )

    CI/CD 구현 도입 이유 lean startup methodology를 따라서 개발, 배포, 가설 검증, 피드백 등을 진행하면서 빠른 배포의 필요성이 대두되었다. 병렬적으로 배포를 올리고 다른 태스크를 쳐내면서 업무의 효율성을 올리기 위해서 CI/CD 도입을 하게 되었다. 또한 sprint #2 부터 배포를 진행하면서 빠르게 사용자들의 피드백을 받고싶었고 테스터들을 점점 늘리면서 지속적인 피드백을 가지고 가고 싶었다. 현재 서비스의 문제점 한 번 빌드를 올리기 위해서는 현재 모든 기능들이 정상적으로 작동하는지 확인하고 ( 테스트 ) provisioning profile, certificate 설정을 해주고 빌드 번호 체크를 한 뒤 testflight에 배포 위의 과정을 따라야 하는데, 일주일에 약 2번..

    BDD로 테스트하기(feat. Quick)

    도입 계기 아래와 같은 이유를 통해서 BDD(Behavior-Driven Development)를 도입하기로 결정하였다. 명확한 요구 사항 이해: 개발과 기획에서 모두가 이해하기 쉬운 플로우로 요구사항을 명확히 할 수 있다. 이를 통해 높은 수준의 통일성과 명확성을 유지할 수 있다. 문서화와 테스팅의 통합: BDD는 자연어 스타일의 표현을 사용하여 테스트 케이스를 작성한다. 테스트 케이스는 동시에 문서 역할도 하므로, 코드의 기능이 어떻게 동작해야 하는지 명확하게 알려주는 동시에, 추후에 변경이나 확장이 이루어질 때 문서의 역할도 할 수 있다. 코드 품질 향상: BDD는 TDD(Test-Driven Development)의 원칙을 기반으로 하기 때문에, 테스팅이 중요한 부분을 차지한다. 따라서 코드 품질..

    Modular Architecture 실전편

    PlugIn Tuist를 사용하면서 각각의 역할을 나눠 Plugin을 만들어서 사용하면 가독성을 높일 수 있습니다. 두가지 플러그인을 만들어서 사용했고, 각각에 대해서 설명드리겠습니다. TemplatePlugin 많은 사람이 한 번에 작업을 하면 프로젝트나 타겟을 추가하면서 앱의 구조에 통일성을 유지하는 것이 어려워지는 경우가 많았습니다. scaffold를 사용해서 프로젝트의 기본 요소 세팅과 폴더링을 손쉽게 할 수 있도록 하였습니다. App Template TemplatePlugin 내부에는 두가지 템플릿이 존재하는데요, 먼저 App이라는 템플릿에 대해서 알아보겠습니다. 왼쪽처럼 플러그인들만 추가한 상태에서 tuist scaffold App --name Chansoo 다음과 같은 명령어를 사용하게 되면..

    Modular Architecture 이론편

    조만간 진행할 프로젝트에서 적용할 앱 구조에 대해서 고민을 하면서 Tuist를 기반으로 모듈화 RIBs를 사용해서 프로토콜 지향 프로그래밍을 사용하고 Clean Architecture를 도입하는 방법을 생각했습니다. 간단하게 공부를 하고 난 이후에 직접 만들어보며 익혀야겠다는 생각으로 바로 샘플앱을 만들기 시작했습니다. 샘플앱 기본 코드는 RIBs를 공부하기 위해 노수진님의 강의(https://github.com/nsoojin/MiniSuperApp-fastcampus)를 들으며 공부했던 코드를 사용했습니다. 이번 글에서는 설계에 대한 내용을 중심으로 이야기하겠습니다. 이전에 사용하던 모듈화 방법의 불편했던 점 포괄적인 모듈을 나누는 기준 이전의 프로젝트에서는 Tuist를 하나의 프로젝트로 모듈화를 했습..

    Custom Network Module에서 토큰 관리하기(RequestInterceptor)

    공간감 앱을 만들면서 네트워크 모듈을 만들어서 사용할지, Alamofire나 Moya를 사용할 지에 대해서 팀원들과 토의를 했습니다. 이전에 네트워크 모듈을 직접 만들어서 사용한 경험이 있어서 써드파티의 필요성을 잘 느끼지 못했습니다. 다만 이번 서비스에서 jwt로 인증을 구현하여서 토큰 관리에 대한 필요성이 생겼습니다. Alamofire에서는 토큰 관리를 어떻게 하는지에 대해서 알아보았고, RequestInterceptor를 사용한다는 것을 알게 되었습니다. RequestInterceptor는 말 그대로 Request를 중도에 빼았는 아이인데요, /// request를 보내기 전 처리를 해주는 메소드 func adapt(_ urlRequest: URLRequest, for session: Alamofi..

    Queenfisher 이미지 캐시 개선기

    Trinap 앱을 만들며 우리 팀이 생각한 도전들 중 하나는 라이브러리 만들어서 써보기였습니다. 그중 Kingfisher를 Queenfisher(ㅋㅋ)라는 이름으로 만들어서 사용했는데요, 이 Queenfisher를 개선한 경험을 남겨보도록 하겠습니다. 이전에 적용된 이미지 캐시 로직과 정책 memoryCache와 diskCache 중 하나를 선택해서 사용을 할 수 있도록 해두었습니다. 캐싱 정책에 대해서 고민하지 않고 무제한으로 캐싱하도록 했습니다. 문제는? memoryCache와 diskCache 중 하나만 사용을 하면서 캐싱의 효율을 극대화할 수 없었습니다. memoryCache의 리밋이 없어서 imageData들을 모두 NSCache에 넣게 되었고, 이미지가 많이 로드되고 나서 지워지지 않고 계속 ..

    MVVM-C + Clean Architecture 도입기

    MVC의 문제점 iOS 개발을 하시는 분들은 아마 MVC를 가장 먼저 사용해볼 것입니다. apple이 설명하는 Cocoa MVC는 위의 그림과 같습니다. Controller가 View의 life cycle, 비즈니스 로직, 화면 전환 로직 등 대부분의 기능을 하게 됩니다. 간단한 로직이 들어간 뷰에서는 별 문제가 없고 오히려 빠르게 구현할 수 있어서 괜찮지만, 뷰와 비즈니스 로직이 복잡해질수록 뷰, 비즈니스 로직, 화면 전환 로직 등이 얽혀 이해하기 쉽지 않아지는 경험을 했습니다. 또한 View와 Controller의 결합도(Coupling)이 높아서 Controller만 독립적으로 테스트를 하기에도 무리가 생깁니다. ViewController가 20개가 넘어가는 Trinap을 개발을 진행하면서 View..

    Operators - RxSwift를 편리하게 사용해보자

    값을 변경, 필터링, 합치는 operator를 사용해서 조금 더 편리하게 RxSwift를 사용할 수 있습니다. Operator는 3가지 타입으로 나눌 수 있습니다. 1. Transformation Operator 2. Filtering Operator 3. Combining Operator Transformation Operations map Observable의 값을 변환합니다. flatMap Observable을 받아서 새로운 Observable을 만듭니다. -> map과 flatMap의 차이점 map: Observable 내부의 값을 바꿈 (클로저 내부의 return 값이 일반 값) flatMap: Observable 내부의 값을 받아서 새로운 Observable을 만들어서 return함 (클로저 ..

    RxSwift 알아보기

    RxSwift 공부하게 된 이유? RxSwift를 왜 사용할까??? RxSwift를 사용하기 이전에는 비동기적인 task를 처리하기 위해서 escaping closure를 사용해야했습니다. 이로 인해서 return 타입이 명시되지 않고 escaping closure 내부의 파라미터에 적어줘서 직관적이지 않고, 중첩 클로저가 쌓이는 등 다양한 문제가 생겼습니다. -> 'return 타입으로 비동기 처리의 결과를 전달할 수 있지 않을까?' 라는 생각을 했습니다. Rx를 사용하지 않기 위한 노력 항상 어떠한 기술을 사용하기 전에 그 기술이 필요한 이유를 생각하고 정말 필요하다고 생각이 들 때 도입을 하려고 노력을 합니다. Rx 공부를 하기 전 뷰를 최대한 멍청하게 하고 뷰모델이 뷰를 모르게 하기 위해서 did..

    Tuist 도입기

    도입 전 상황 1. merge conflict 4명의 사람이 함께 프로덕트를 개발하면서 다양한 충돌을 경험했습니다. 일반적인 swift 코드 내에서의 충돌의 경우는 코드를 읽어보고 팀원들과 상의하면서 수정을 하기가 그렇게 어렵지는 않았습니다. 하지만 pbxproj 파일의 충돌의 경우 swift 코드처럼 쉽게 읽으면서 conflict를 해결하기에 어려움이 있었습니다. 파일을 수정, 이동, 삭제 등을 할 때마다 팀원들과 상의를 하는 것이 불필요하게 우리의 노력을 낭비하는 것이라는 생각이 들었습니다. 2. 모듈화 또한 구현을 할 수 있는 선에서의 라이브러리들은 직접 구현을 해서 사용하고, 각각의 코드의 역할 분리를 명확하게 하기로 한 상황에서 해당 구현체들을 모듈화 해서 관리를 하고 싶었습니다. 도입 이유 위..