{"id":20738077,"url":"https://github.com/developeracademy-postech/swift-style-guide","last_synced_at":"2026-01-27T06:01:09.044Z","repository":{"id":39364430,"uuid":"506836193","full_name":"DeveloperAcademy-POSTECH/swift-style-guide","owner":"DeveloperAcademy-POSTECH","description":"아카데미에서 사용 하는 코딩 스타일 가이드 입니다.","archived":false,"fork":false,"pushed_at":"2024-06-24T13:04:09.000Z","size":103,"stargazers_count":251,"open_issues_count":8,"forks_count":38,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-11T11:36:21.290Z","etag":null,"topics":["hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DeveloperAcademy-POSTECH.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-24T01:02:26.000Z","updated_at":"2025-02-23T10:11:30.000Z","dependencies_parsed_at":"2024-06-24T14:39:11.074Z","dependency_job_id":"d9e814f7-f44b-4b04-bd1a-a0f0474c085e","html_url":"https://github.com/DeveloperAcademy-POSTECH/swift-style-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DeveloperAcademy-POSTECH/swift-style-guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeveloperAcademy-POSTECH%2Fswift-style-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeveloperAcademy-POSTECH%2Fswift-style-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeveloperAcademy-POSTECH%2Fswift-style-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeveloperAcademy-POSTECH%2Fswift-style-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DeveloperAcademy-POSTECH","download_url":"https://codeload.github.com/DeveloperAcademy-POSTECH/swift-style-guide/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DeveloperAcademy-POSTECH%2Fswift-style-guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28805316,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T05:43:52.625Z","status":"ssl_error","status_checked_at":"2026-01-27T05:43:48.957Z","response_time":168,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest"],"created_at":"2024-11-17T06:16:32.902Z","updated_at":"2026-01-27T06:01:09.012Z","avatar_url":"https://github.com/DeveloperAcademy-POSTECH.png","language":null,"readme":"# swift-style-guide\n\nApple Developer Academy의 개발자들이 따르고 있는 스위프트 스타일 가이드입니다. 다른 사람의 코드를 읽을 때 가독성을 높여주며,\n내가 코드를 작성할 때 애매한 부분을 제거해줘 생산성 향상에 도움을 줍니다!\n\n취향에 문제가 많기 때문에 코드를 작성하는데 어려움이 생긴다면 PR을 통해 언제나 의견을 주세요.\n\n기여를 하고싶으신 분들을 위한 가이드는 [컨트리뷰션 가이드라인](./.github/CONTRIBUTING.md)을 참고해주세요.\n\n\n\n\n## 목차\n\n1. [네이밍](#네이밍)\n    1. [변수](#변수)\n    2. [함수](#함수)\n    3. [열거형](#열거형)\n    4. [구조체와 클래스](#구조체와-클래스)\n    5. [프로토콜](#프로토콜)\n    6. [델리게이트](#델리게이트)\n2. [주석](#주석)\n3. [띄어쓰기](#띄어쓰기)\n4. 코드 구성\n   1. 미사용 코드\n5. 접근제어자\n6. 클래스와 스트럭트\n7. 함수호출\n8. [클로져](#클로져)\n    1. [후행 클로저 축약](#후행-클로저-축약)\n    2. [다중 후행 클로져](#다중-후행-클로져)\n9. 타입\n    1. [타입 추론](#타입-추론)\n    2. [타입 어노테이션](#타입-어노테이션)\n10. [메모리 관리](#메모리-관리)\n11. [파일관리](#파일관리)\n12. [SwiftUI](#SwiftUI)\n    1. [View 선언 방법](#View-선언-방법)\n\n\n## 네이밍\n### 변수\n- 변수 이름은 `lowerCamelCase`를 사용해주세요.\n- 배열과 같이 복수의 의미를 담고있는 변수라면 끝에 **s**를 붙여서 사용해주세요.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n\n  - **Good ✅**\n    ```swift\n    var categories: [String]\n    var person: Person\n    var isShowing: Bool\n    ```\n  - **Bad ❌**\n    ```swift\n    var category: [String]\n    var show: Bool\n    ```\n  \u003c/details\u003e\n  \n### 함수\n- 함수 이름에는 `lowerCamelCase`를 사용해주세요.\n- 함수는 일반적으로 동사원형으로 시작해주세요.\n- Event-Handling 함수의 경우 (조동사 + 동사원형)으로 시작해주세요. 주어는 유추 가능하다면, 생략 가능합니다.\n    - will은 특정 행위가 일어나기 직전을 의미합니다.\n    - did는 특정 행위가 일어난 직후를 의미합니다.\n    \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Good ✅**\n        ```swift\n        class AcademyViewController {\n\n            private func didFinishSession() {\n                // ...\n            }\n\n            private func willFinishSession() {\n                // ...\n            }\n\n            private func scheduleDidChange() {\n                // ...\n            }\n        }\n        ```\n    - **Bad ❌**\n        ```swift\n        class AcademyViewController {\n\n            private func handleSessionEnd() {\n                // ...\n            }\n\n            private func finishSession() {\n                // ...\n            }\n\n            private func scheduleChanged() {\n                // ...\n            }\n        }\n        ```\n    \u003c/details\u003e\n    \n- 데이터를 가져오는 함수의 경우, `get` 사용을 지양하고 `request`, `fetch`을 적절하게 사용해주세요.\n    - `request` : 에러가 발생하거나, 실패할 수 있는 비동기 작업에 사용합니다. 예를 들어, http 통신을 통해 값을 요청하는 경우가 이에 해당합니다.\n    - `fetch` : 요청이 실패하지 않고 결과를 바로 반환할 때 사용합니다. 예를 들어, data를 찾고자 하는 모든 행위를 할 때가 이에 해당합니다.\n    \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Good ✅**\n        ```swift\n        func reqeustData(for user: User) -\u003e Data?\n        func fetchData(for user: User) -\u003e Data\n        ```\n    - **Bad ❌**\n        ```swift\n        func getData(for user: User) -\u003e Data?\n        ```\n    \u003c/details\u003e\n\n    \n### 열거형\n- 열거형의 이름은 `UpperCamelCase`를 사용해주세요.\n- 열거형의 각 case에는 `lowerCamelCase`를 사용해주세요.\n    \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Good ✅**\n      ```swift\n      enum Result {\n        case .success\n        case .failure\n      }\n      ```\n  - **Bad ❌**\n      ```swift\n      enum result {\n        case .Success\n        case .Failure\n      }\n      ```\n     \u003c/details\u003e\n   \n### 구조체와 클래스\n- 구조체와 클래스의 이름은 `UpperCamelCase`를 사용해주세요.\n- 구조체와 함수의 이름 앞에 `prefix`를 붙이지 말아주세요.\n- 구조체와 클래스의 프로퍼티 및 메소드는 `lowerCamelCase`를 사용해주세요.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n\n  - **Good ✅**\n      ```swift\n      struct LeftRectangle {\n          var width: Int\n          var height: Int\n\n          func drawRectangle() {\n              // ...\n          }\n      }\n      ```\n      ```swift\n      class Mentee {\n          let id: String\n          let session: String\n          var group: Int\n          var team: Int\n\n          func callOutMentor() {\n              // ...\n          }\n      }\n      ```\n  - **Bad ❌**\n      ```swift\n      struct rwRightRectangle {\n          var Width: Int\n          var Height: Int\n\n          func DrawRectangle() {\n              // ...\n          }\n      }\n      ```\n      ```swift\n      class rwMentor {\n          let Id: String\n          var Group: Int\n\n          func GiveAdvice() {\n              // ...\n          }\n      }\n      ```\n    \u003c/details\u003e\n\n### 프로토콜\n- 구조를 나타내는 프로토콜은 명사로 작성해야합니다.\n- 무언가를 할 수 있음(능력)을 설명하는 프로토콜은 형용사로 작성해야합니다.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n\n  - **Good ✅**\n      ```swift\n      protocol Car {\n          var speed: Int { get set }\n          var name: String { get }\n\n          func speedUp(speed: Int) -\u003e Bool\n      }\n      ```\n      ```swift\n      protocol Drivable {\n          func accelerate(speed: Int) -\u003e ()\n          func slowDown(speed: Int) -\u003e ()\n      }\n      ```\n  - **Bad ❌**\n      ```swift\n      protocol Drivable {\n          var speed: Int { get set }\n          var name: String { get }\n\n          func speedUp(speed: Int) -\u003e Bool\n          func accelerate(speed: Int) -\u003e ()\n          func slowDown(speed: Int) -\u003e ()\n      }\n      ```\n    \u003c/details\u003e\n\n### 델리게이트\n- protocol을 이용해 delegate 패턴을 구현합니다.\n- 함수의 첫번째 인자는 생략가능한 델리게이트의 소스 객체를 사용합니다.\n   - **Good ✅**\n        ```swift\n            // 델리게이트의 소스 객체만을 메서드의 인자로 받는 경우\n            protocol UserScrollViewDelegate {\n                func scrollViewDidScroll(_ scrollView: UIScrollView)\n                func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -\u003e Bool\n            }\n\n            // 델리게이트의 소스 객체 다음에 추가적인 인자를 받는 경우\n            protocol UserTableViewDelegate {\n                func tableView(\n                    _ tableView: UITableView,\n                    willDisplayCell cell: Cell,\n                    cellForRowAt indexPath: IndexPath)\n                )\n                func tableView(\n                    _ tableView: UITableView,\n                    numberOfRowsInSection section: Int) -\u003e Int\n                )\n            }\n        ```\n    - **Bad ❌**\n        ```swift\n            protocol UserViewDelegate {\n                // 인자를 생략한 경우\n                func didScroll()\n                // 델리게이트의 소스 객체를 인수로 사용하지 않은 경우\n                func willDisplay(cell: Cell)\n                // 함수명을 UpperCamelCase로 작성한 경우, 다른 클래스가 존재하면 컴파일 오류 발생\n                func UserScrollView(_ scrollView: UIScrollView)\n            }  \n        ```\n\n## 주석\n\u003e 주석은 협업에 있어 가독성을 높이고 다른 사람의 코드를 이해하는 중요한 도구입니다. \n- 설명은 최대한 간결하고 핵심 요약에 집중해서 작성해주세요.\n- 함수와 메소드는 기본적으로 무엇을 하는지 무엇을 반환하는지 설명해주시고,  \n널효과나 void 반환은 생략합니다.\n- 작성한 주석은 퀵헬프 메뉴에서 언제든지 조회가 가능합니다.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n\n  - **Good ✅**\n    ```swift\n    /// 사용자 데이터를 추가합니다.\n    /// - Parameter name: user fullname\n    /// - Parameter age: user age\n    func addData(name: String, age: Int) {\n        // code to add data...\n    }\n    ```\n\n    ```swift\n    /// DB내 사용자 이름과 ID로 나이를 조회합니다.\n    /// - Parameter ID: user ID\n    /// - Parameter name: user fullname\n    /// - Returns: user age\n    func readData(ID: Int, name: String) {\n        var age: Int\n        // code to read data...\n        return age\n    }\n    ```\n\n  - **Bad ❌**\n    ```swift\n    // 사용자 데이터 추가\n    func addData(name: String, age: Int) {\n        // return void\n    }\n    ```\n  \u003c/details\u003e\n  \n\n- 연관된 코드가 있다면 MARK를 사용하여 코드영역을 구분지는것을 권장합니다.\n\n  \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Example 💡**\n        ```swift\n        // MARK: - Gryffindor\n        let password = \"Fotuna Major\"\n        struct Gryffindor {\n            let harry: String\n            let ron: String\n            let hermione: String\n        }\n\n        // MARK: - Slytherin  \n        class Slytherin {\n            let voldemort: String\n            let malfoy: String\n            func deadlyCurse() {\n                print(\"Avada Kedavra!\")\n            }\n        }\n        ```\n    \u003c/details\u003e\n  \n\n- 아직 개발이 완료되지 않은 코드가 있다면 TODO나 FIXME를 사용하여 체크하는 것도 좋습니다.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n\n  - **Example 💡**\n      ```swift\n      // FIXME: - 버그 수정 필요\n      public func buggyFunc() {\n          // buggy code..\n      }\n\n      // TODO: - 문자열 인코딩 함수 작업 계획 \n      private func todoFunc() {\n          // tbd..\n      }\n  \u003c/details\u003e\n  \n\n## 들여쓰기\n- 인덴테이션은 스페이스바 4개를 기본으로 하되, 스페이스바 4개는 탭 1개의 역할을 합니다.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n  \n  - **Good ✅**\n      ```swift\n      func sayHiLeeo(isHappy: Bool) {\n          if isHappy {\n              print(\"Hi Leeo!\")\n          }\n      }\n      ```\n  - **Bad ❌**\n      ```swift\n      func sayHiLeeo(isHappy: Bool) {\n        if isHappy {\n          print(\"Hi Leeo!\")\n        }\n      }\n      ```\n  \u003c/details\u003e\n  \n    \n## 띄어쓰기\n- 콜론(`:`)을 사용할 땐 콜론의 오른쪽으로 한 칸의 여백을 생성합니다. 콜론의 왼쪽은 공백없이 코드를 작성합니다.\n  - **Example 💡**\n    ```swift\n    let leeo: HappyLeeo\n    ```\n\n## 클로져\n### 후행 클로저 축약\n- 단일 후행 클로저의 경우에는 타입유추, 함수 라벨 생략, 소괄호 생략을 사용합니다.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n\n  - **Function**\n    ```\n    func someFunctionThatTakesAClosure(closure: (Int) -\u003e Void) {\n          // function body goes here\n    }\n    ```\n\n  - **Good ✅**\n    ```swift\n    someFunctionThatTakesAClosure { int in\n        // trailing closure's body goes here\n    }\n    ```\n  \n  - **Bad ❌**\n    ```swift\n    someFunctionThatTakesAClosure(closure: { (arguInt: Int) -\u003e Void)\n        // function body goes here\n    })\n    ```\n  \u003c/details\u003e  \n\n### 다중 후행 클로져\n- 함수 또는 메서드의 형식 매개변수에서 클로져들만을 실 매개변수로 받는 경우 함수 또는 메서드 호출 시 함수 또는 메서드의 소괄호, 첫 번째 실 매개변수의 라벨, 실 매개변수 사이의 콤마를 생략합니다.\n  \u003cdetails\u003e\n  \u003csummary\u003e예제코드\u003c/summary\u003e\n  \n  - **Good ✅**\n    ```swift\n    func doSomething(do: (String) -\u003e Void, onSuccess: (Any) -\u003e Void, onFailure: (Error) -\u003e Void) {\n        // function body\n    }\n\n    doSomething { something in\n        // do closure\n    } onSuccess: { result in\n        // success closure\n    } onFailure: { error in\n        // failure closure\n    }\n    ```\n  \n  - **Bad ❌**\n    ```swift\n    func doSomething(do: (String) -\u003e Void, onSuccess: (Any) -\u003e Void, onFailure: (Error) -\u003e Void) {\n        // function body\n    }\n\n    doSomething (do: { something in\n        // do closure\n    }, onSuccess: { result in\n        // success closure\n    }, onFailure: { error in\n        // failure closure\n    })\n    ```\n  \u003c/details\u003e  \n\n\n## 타입\n### 타입 추론\n- 컴팩트 코드를 선호하고 컴파일러가 단일 인스턴스의 상수나 변수의 타입을 추론하도록 합니다.\n- 필요한 경우 `CGFloat`나 `Int64`와 같은 경우는 특정 타입을 지정해줍니다.\n  \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n    \n    - **Good ✅**\n      ```swift\n      let apple = \"Developer\"\n      let book1 = Book()\n      let age = 25\n      let frameWidth: CGFloat = 120\n      ```\n    \n    - **Bad ❌**\n      ```swift\n      let apple: String = \"Developer\"\n      let book1: Book = Book()\n      let age: Int = 25\n      ```\n  \u003c/details\u003e\n    \n### 타입 어노테이션    \n- 전체 제네릭 구문 `Array\u003cT\u003e`와 `Dictionary\u003cT: U\u003e` 보다는 단축 구문 `[T]`, `[T: U]`를 사용합니다.\n  \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n    \n    - **Good ✅**\n      ```swift\n      var student: [String: String]?\n      var students: [String]?\n      ```\n    \n    - **Bad ❌**\n      ```swift\n      var student: Dictionary\u003cString, String\u003e?\n      var students: Array\u003cString\u003e?\n      ``` \n  \u003c/details\u003e\n  \n\n- 빈 배열과 딕셔너리 선언 시, 타입을 명시하는 것을 선호합니다.\n  \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n    \n    - **Good ✅**\n      ```swift\n      var student: [String: String] = [:]\n      var students: [String] = []\n      ```\n    \n    - **Bad ❌**\n      ```swift\n      var student = [String: String]()\n      var students = [String]()\n      ``` \n  \u003c/details\u003e\n  \n\n## 메모리 관리\n- 메모리 누수의 원인이 되는 순환 참조가 일어나지 않도록 주의해주세요.\n- 객체 간의 관계를 분석하면서 `weak`와 `unowned`를 사용하여 순환 참조를 방지할 수 있습니다.\n- `weak` 참조 변수는 반드시 Optional 타입이어야 합니다.\n  \u003cdetails\u003e\n    \u003csummary\u003e예제코드\u003c/summary\u003e\n    \n    - **Good ✅**\n      ```swift\n      class ExampleClass {\n          weak var example: ExmapleClass? = nil\n          \n          init(){\n              print(\"init class\")\n          }\n          \n          deinit{\n              print(\"deinit class\")\n          }\n      }\n\n      // 객체 내의 인스턴스가 서로를 가리키고 있지만, weak 참조를 선언했기에 순환 참조가 일어나지 않습니다.\n      var ex1: ExampleClass? = ExampleClass()\n      var ex2: ExampleClass? = ExampleClass()\n\n      ex1?.example = ex2\n      ex2?.example = ex1\n\n      ex1 = nil\n      ex2 = nil\n\n      // 출력결과\n      // init class\n      // init class\n      // deinit class\n      // deinit class\n      ```\n  \u003c/details\u003e\n\n## 파일관리\n- 파일 내에서 모듈 `import`를 알파벳순으로 지정하고 중복된 것들을 제거해주세요.\n  \u003cdetails\u003e\n      \u003csummary\u003e예제코드\u003c/summary\u003e\n      \n    - **Good ✅**\n        ```swift\n        import Alamofire\n        import Foundation\n        import SnapKit\n        ```\n    - **Bad ❌**\n        ```swift\n        import Foundation\n\n        import SnapKit\n        import Alamofire\n        import Foundation\n        ```\n\n  \u003c/details\u003e\n\n- `Computed properties`와 `property observers`가 있는 `property`는 같은 종류의 선언 집합 끝에 나타나야 합니다.\n  \u003cdetails\u003e\n      \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Good ✅**\n        ```swift\n        var gravity: CGFloat\n        var atmosphere: Atmosphere {\n            didSet {\n                print(\"oh my god, the atmosphere changed\")\n            }\n        }\n        ```\n    - **Bad ❌**\n        ```swift\n        var atmosphere: Atmosphere {\n            didSet {\n                print(\"oh my god, the atmosphere changed\")\n            }\n        }\n        var gravity: CGFloat\n        ```\n\n  \u003c/details\u003e\n\n## SwiftUI\n### View 선언 방법\n- 모든 뷰는 `Struct`로 정의하는 것을 권장합니다. `@ViewBuilder` function이나 computed property로 정의하는 것은 지양합니다.\n  - 이를 통해 State와 Binding 등의 관계가 명확히 정의됩니다. 해당 뷰의 구현부를 보지 않고도 역할을 짐작할 수 있습니다.\n  - function이나 computed property로 정의했을 때, 이를 다른 뷰에서도 재사용할 수 있게 바꾸려면 추가적인 작업이 필수입니다. 미리 struct로 정의해두면 이런 일을 방지할 수 있습니다.\n  \u003cbr\u003e\n\n  \u003cdetails\u003e\n      \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Good ✅**\n        ```swift\n        struct Item: View {\n            @State private var isFavorite: Bool = false\n            var body: some View {\n                FavoriteButton(isFavorite: $isFavorite)\n            }\n\n            struct FavoriteButton: View { // ✅ extension을 사용해서 정의해도 무방합니다\n                @Binding var isFavorite: Bool\n                var body: some View {\n                    Button {\n                        isFavorite.toggle()\n                    } label: {\n                        ...\n                    }\n                }\n            }\n        }\n        ```\n    - **Bad ❌** : `@ViewBuilder Function`\n        ```swift\n        struct Item: View {\n            @State private var isFavorite: Bool = false\n            var body: some View {\n                FavoriteButton()\n            }\n\n            @ViewBuilder\n            private func FavoriteButton() -\u003e some View { // ❌\n                Button {\n                    isFavorite.toggle()\n                } label: {\n                    ...\n                }\n            }\n        }\n        ```\n    - **Bad ❌** : `computed property`\n        ```swift\n        struct Item: View {\n            @State private var isFavorite: Bool = false\n            var body: some View {\n                FavoriteButton\n            }\n\n            @ViewBuilder\n            var FavoriteButton: some View { // ❌\n                Button {\n                    isFavorite.toggle()\n                } label: {\n                    ...\n                }\n            }\n        }\n        ```\n  \u003c/details\u003e\n- 하나의 뷰 Struct에서 [레이아웃 컨테이너](https://developer.apple.com/documentation/swiftui/layout-fundamentals)(VStack, HStack, ZStack, Grid 등)는 최대 1개까지만 사용하는 것을 권장합니다.\n  - 레이아웃 컨테이너를 2개 이상 겹치게 되면 배치의 방향성이 일관되지 않게 되므로 코드의 가독성이 매우 떨어집니다. 각 배치 방향이 무엇을 의미하는지 이름을 결정해두면 가독성이 더 좋아집니다.\n  - 레이아웃 컨테이너는 남발되기 매우 쉽습니다. 레이아웃 컨테이너를 기준으로 뷰를 분리하는 과정에서 불필요한 레이아웃 컨테이너를 발견할 확률을 높일 수 있습니다.\n  \u003cbr\u003e\n\n  \u003cdetails\u003e\n      \u003csummary\u003e예제코드\u003c/summary\u003e\n\n    - **Good ✅**\n        ```swift\n        struct Articles: View {\n            var body: some View {\n                VStack {\n                    Text(\"Featured\")\n                    FeaturedArticles() // ✅\n                    Divider()\n                    Text(\"All Articles\")\n                    AllArticles() // ✅\n                }\n            }\n\n            struct FeaturedArticles: View { // ✅\n                var body: some View {\n                    HStack {\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                    }\n                }\n            }\n\n            struct AllArticles: View { // ✅\n                var body: some View {\n                    HStack {\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                    }\n                }\n            }\n        }\n        ```\n    - **Bad ❌**\n        ```swift\n        struct Articles: View {\n            var body: some View {\n                VStack {\n                    Text(\"Featured\")\n                    HStack { // ❌\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                    }\n                    Divider()\n                    Text(\"All Articles\")\n                    HStack { // ❌\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                        NavigationLink {\n                            ...\n                        } label: {\n                            ...\n                        }\n                    }\n                }\n            }\n        }\n        ```\n  \u003c/details\u003e\n\n## Reference\n- [Google Swift Style Guide](https://google.github.io/swift/)\n- [Airbnb Swift Style Guide](https://github.com/airbnb/swift)\n- [Linkedin Swift Style Guide](https://github.com/linkedin/swift-style-guide)\n- [Raywenderlich Swift Style Guide](https://github.com/raywenderlich/swift-style-guide)\n- [StyleShare Swift Style Guide](https://github.com/StyleShare/swift-style-guide#%EC%B5%9C%EB%8C%80-%EC%A4%84-%EA%B8%B8%EC%9D%B4)\n- [Channel Talk Swift Code Convention Guide](https://github.com/channel-io/ios-convention-guide)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeveloperacademy-postech%2Fswift-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeveloperacademy-postech%2Fswift-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeveloperacademy-postech%2Fswift-style-guide/lists"}