본문 바로가기
iOS

iOS 개발 전에 정리하는 코드 스타일 가이드 📌 | 효율적인 협업과 유지보수를 위해...

by 23g 2025. 3. 24.

 

 

iOS 개발을 하면서 코드 스타일을 통일하는 것은 가독성을 높이고 유지보수를 쉽게 만드는 중요한 요소다.

특히 협업 시 일관된 코드 스타일을 유지하면 리뷰 속도도 빨라지고, 기능 추가 및 수정이 수월해진다.

이번 포스팅에서는 iOS 개발에서 지켜야 할 코드 스타일 가이드를 정리해보겠다 🚀

 

뭐든지 기초가 중요함...


 1. 코드 스타일 기본 규칙 

1.1 들여쓰기 (Indentation)

Xcode에서 기본 들여쓰기는 4인데, 2로 설정하면 더 깔끔하다.

📌 설정 방법: Xcode > Settings > Text Editing > Indentation 에서 2로 변경

 

1.2 MARK 주석 스타일

  • // MARK: - 형태로 작성
  • : 이후 한 줄 개행
  • 관련 항목이 끝난 후 두 줄 개행
// MARK: - User Model

struct User {
    let name: String
    let age: Int
}

 

앞으로 이렇게 해보려구요

이것은 개취...

 

1.3 미니맵 활성화

Editor > Minimap

코드 구조를 한눈에 보기 편하다.

 

1.4 Import 문 정렬

  • 알파벳 순서로 정렬
  • 관련된 항목끼리 그룹화
import Foundation
import UIKit

import FirebaseAuth
import FirebaseDatabase

🎯 2. 객체 지향 및 설계 원칙

2.1 상속을 지양하고 final을 활용하자

상속은 최소화하고, 상속 하지 않을 시에 final 키워드를 사용하자

이유

  • 상속 시 필요하지 않은 속성/메서드까지 포함될 수 있음
  • 결합도를 낮추고 유지보수를 쉽게 하기 위함
final class UserManager {
    func fetchUsers() {
        // 유저 데이터 가져오기
    }
}

 

2.2 프로토콜을 활용한 컴포지셔널 프로그래밍

"상속"보다 "구성(Composition)"을 지향하자

프로토콜을 활용해 기능을 조합하면 더 유연한 설계 가능

protocol Printable {
    func printInfo()
}

struct User: Printable {
    let name: String
    
    func printInfo() {
        print("User: \(name)")
    }
}

 

2.3 객체가 아닌 개념에 의존해야 한다

구체적인 클래스 대신 프로토콜에 의존하면 확장성이 높아진다.

 

❌ 잘못된 예시 (구체적인 클래스 의존)

class UserManager {
    let database = FirebaseDatabase()
}

오...이거 완전 나잖아

 

✅ 올바른 예시 (추상화된 개념 의존)

protocol Database {
    func fetchData()
}

class FirebaseDatabase: Database {
    func fetchData() {
        print("Fetching data from Firebase")
    }
}

class UserManager {
    let database: Database
    
    init(database: Database) {
        self.database = database
    }
}

🏗 3. 코드 작성 원칙

3.1 변수 vs 상수

가능하면 let을 우선 사용하고, 변경될 가능성이 있을 때만 var 사용

  변수 (var) 상수 (let)
값 변경 여부 변경 가능 변경 불가능
메모리 사용 최적화에 따라 다름 최적화 가능성이 높음
가독성 변경 가능성이 있어 추적 필요 변경되지 않아 코드 예측 가능

 

3.2 뷰컨트롤러와 비즈니스 로직 분리

뷰컨트롤러: UI 표시, 사용자 상호작용 처리
비즈니스 로직: 데이터 생성, 연산, 네트워크 호출

// ❌ 잘못된 예시 (비즈니스 로직을 ViewController에 포함)
class UserViewController: UIViewController {
    func fetchUser() {
        // 네트워크 요청을 직접 실행 🚨
    }
}

// ✅ 올바른 예시 (비즈니스 로직을 분리)
class UserService {
    func fetchUser() {
        // 네트워크 요청 수행
    }
}

 

3.3 메서드 분리

하나의 메서드는 하나의 역할만 수행해야 한다.

추상화 레벨을 맞춰 메서드를 나누자

func fetchUserData() {
    validateUser()
    requestData()
    updateUI()
}

 

3.4 Depth는 최대 2단계까지

들여쓰기(Depth)는 최대 2단계까지만 허용하여 가독성을 높이자

나쁜 예시 (깊은 중첩)

if isValid {
    if isAuthenticated {
        if hasPermission {
            print("Access Granted")
        }
    }
}

 

좋은 예시 (Early Exit 적용)

guard isValid else { return }
guard isAuthenticated else { return }
guard hasPermission else { return }

print("Access Granted")

 

3.5 순수 함수 (Pure Function)

외부 상태를 변경하지 않는 함수
사이드 이펙트가 없음

func add(a: Int, b: Int) -> Int {
    return a + b
}

🔥 4. 코드 품질 유지

4.1 기술 부채 지양

코드가 복잡해지기 전에 리팩토링을 주기적으로 진행

 

4.2 임플리먼트 vs 인터페이스

구현은 내부에서 (Implement)
외부와 소통은 인터페이스에서 (Protocol)

protocol AuthService {
    func login()
}

class FirebaseAuthService: AuthService {
    func login() {
        print("Logging in with Firebase")
    }
}

 

4.3 좋은 코드의 조건

✅ 가독성 높은 네이밍
✅ 사이드 이펙트 최소화
✅ 코드가 간결하고 직관적
✅ 불필요한 분기 최소화


🎯 5. 협업을 위한 PR 전략

Pull Request (PR)는 최소한의 단위로
Git PR에 변경 사항을 자세히 설명

주석은 필요할 때에!
ex : 백엔드에서 처리해야 할 로직을 임시 구현한 경우 주석 자세히 달아주기

// TODO: 백엔드에서 처리하도록 변경 예정
func fetchUserData() {
    print("Fetching user data from local storage")
}

🏁 마무리

위의 가이드를 따르면 더 깔끔하고 유지보수하기 쉬운 iOS 코드를 작성할 수 있다. 🚀

iOS 개발을 하면서 "읽기 좋은 코드"를 작성하는 습관을 들이자!

으아아아 그럼 난 이만 출근하러@!!!!!