Skip to content
This repository has been archived by the owner on Dec 31, 2023. It is now read-only.

쿠링 iOS 스타일 가이드

Jaesung edited this page Mar 19, 2023 · 2 revisions

개발 컨벤션

참고 https://github.com/kodecocodes/swift-style-guide

네이밍

미리보기

변수명

  • lowerCamelCase를 사용합니다.

    var name: String
    var name = "" // 타입 선언은 선택적
    var isViewPresented: Bool
    var isOnboardPresented: Bool
    var notices: [Notice]
  • Bool 타입의 경우, 하단의 규칙을 따릅니다.

    • is + 과거분사의 수동태 : 일반 변수에서 사용합니다.
    • 3인칭동사 : parameter에서 사용합니다.
    // ✅ GOOD
    @State var isPresented: Bool = false
    func activeMenu(showsMenu: Bool) { }
    
    // ❌ BAD
    @State var nowOn: Bool = false
    func activeMenu(isActive: Bool) { }
    /// State, Binding 은 반드시 is+pp 형태, 그 외에는 과거분사만 사용 혹은 3인칭 동사형태
    init(isViewPresented: Binding<Bool>, showsOnboardView: Bool)
    
    /// Bool 타입 파라미터
    func someNoticeMethod(bookmarked: Bool) -> [Notice] // isBookmarked 🙅
  • Array를 선언하는 경우, 복수의 의미를 가진 단어를 선택합니다.

    var notices: [Notice]

타입명 (Class, Enum, Actor, Struct)

  • UpperCamelCase를 사용합니다.

  • ObservableObject를 준수하는 DataModel의 경우 ViewModel 형식의 네이밍을 가급적 피하도록 합니다.

    class Subscription: ObservableObject { ... }
    
    struct SubscriptionView: View {
    // GOOD!
        @StateObject var subscription = Subscription()
    // Hmm...
        @StateObject var viewModel = Subscription()
        // Oops...
        @StateObject var viewModel = SubscriptionViewModel()
    }
  • 단, 뷰 이름 또는 이미 존재하는 Model과 중복되는 경우 뒤에 Model를 명시합니다. 이 경우 뷰에서는 dataModel 이라는 네이밍을 사용합니다.

    class NoticeListModel: ObservableObject { ... }
    
    struct NoticeList: View {
        // GOOD!
        @StateObject var dataModel = NoticeListModel()
        // Oh...
        @StateObject var viewModel = NoticeListModel()
        // What's wrong with you...
        @StateObject var viewModel = NoticeListViewModel()
    }

함수명

  • 함수 네이밍 시, 첫 파라미터 네이밍과 함수명이 중복인 경우 _ {parameter.name} 형태로 선언하여 파라미터 이름이 외부에서 노출되지 않게 합니다.
    func readNotice(_ notice: Notice)
  • 선언된 함수를 사용할 때 하나의 영어문장이 되게끔 작명합니다.
    func searchNotice(named name: String) { ... }
    
    // 사용 시
    searchNotice(named: "2023")

선언 순서


변수

  • 변수 선언은 하단의 순서로 공백라인 없이 작성합니다.
    • Property wrapper
      • @StateObject
      • @EnvironmentObject
      • @ObservableObject
      • @Published
    • 기본 타입의 변수
    • didSet 과 같은 클로져가 있는 변수

모듈(import)

  • import 는 모듈명 길이순으로 공백라인 없이 작성하고, 중복된 모듈구성을 피합니다.

    // ✅ GOOD
    
    import UIKit
    import Combine
    import Firebase
    import KuringSDK
    import KuringCommons
    import SendbirdChatSDK
    
    // 👎 BAD
    
    import UIKit
    import SwiftUI (: 중복된 모듈)
    import SendbirdChatSDK
    import KuringSDK (: SendbirdChatSDK보다 짧은 모듈명 -> import 순서 바뀌어야 함)

타입


  • Swift의 타입 명시가 필요하지 않은 장점을 살리기 위해 선언되는 변수들의 타입은 선택사항으로 작성하되, 타입이 유추가능한 변수명을 선택해야 합니다.

    // ✅ GOOD
    var title: String = "This is title"
    var notices: [Notice]
    
    // 👎 BAD
    var title = "This is title"

주석


  • 코드에 대한 설명은 //// 3개를 이어 작성합니다.

    • public 한 프로퍼티 또는 메소드는 반드시 ```swift 키워드를 사용하여 코드사용예시를 같이 작성해주어야 합니다.
    • 코드 설명은 한국어로 작성합니다.
  • 유사한 로직 처리를 위한 함수들은 // MARK: - 를 이용하여 처리해 줍니다.

  • extension에 작성하게 되는 프로토콜의 경우, extension code block 당 1개의 프로토콜만 구현되어 있어야 합니다.

    // ✅ GOOD
    /// 온보딩 보여주기
    .fullScreenCover(isPresented: $isOnboardPresented) {
    }
    
    // MARK: - UITableViewDelegate
    extension UIViewController: UITableViewDelegate {
    }
    
    // MARK: - UITableViewDatasource
    extension UIViewController: UITableViewDatasource {
    }
    
    // 👎 BAD
    // MARK: - UITableViewDelegate, UITableViewDatasource 
    extension UIViewController: UITableViewDelegate, UITableViewDatasource {
    }