본문 바로가기
🌐 유니티 (Unity)

Day 31 - 객체 지향 SOLID 원칙(표 정리, 예제)

by shin0707 2024. 5. 26.
728x90
반응형

  • 주제

>> 객체 지향 SOLID 원칙

(단일 책임 원칙 - S)

(개방 폐쇄 원칙 - O)

(리스코프 치환 원칙 - L)

(인터페이스 분리 원칙 - I)

(의존성 역전 원칙 - D)

 

>> 사용자인증시스템을 주제로 하는 예제

(나쁜 예)

(좋은 예)

 

*** SOLID원칙을 알고 있으면 다른 사람의 코드를 이해하는데 도움이 된다.

(추가적인 기능 구현 가능)

*** But, 많이 사용하면 그만큼 코드가 복잡해진다.


  • 공부내용

1. SOLID 원칙(표)

원칙 개념 장점 단점
단일책임원칙
(SRP)
각 클래스는 하나의 책임만 코드 이해,
유지보수 용이
클래스 수 증가
개방폐쇄원칙
(OCP)
확장 가능,
수정 불가능
코드 재사용성,
확장 용이
초기설계가 복잡
리스코프치환원칙
(LSP)
부모 클래스가
제공하는 모든 기능을
자식 클래스도 제대로 사용
코드 예측가능성 증가 잘못된 상속 관계로 인해
오류 발생 가능
인터페이스
분리원칙(ISP)
필요한 기능만 포함된
작은 인터페이스를
여러 개 사용
유연성,
재사용성 증가
인터페이스 수 증가로
관리가 복잡
의존성역전원칙
(DIP)
상위 모듈(클래스)이 
하위 모듈(인터페이스)에 의존
유연성,
테스트용이성 증가
초기설정이 복잡

주제: 사용자 인증 시스템

 

2. 단일 책임 원칙

 

나쁜 예제

public class UserManager {
    public void RegisterUser(string username, string password) {
        // 사용자 등록 로직
        // 비밀번호 해싱 로직
        // 데이터베이스 저장 로직
    }

    public bool LoginUser(string username, string password) {
        // 로그인 로직
        // 데이터베이스 조회 로직
        // 비밀번호 검증 로직
    }
}

 

좋은 예제

public class UserManager {
    private readonly IUserRepository _userRepository; // 사용자 저장소
    private readonly IPasswordHasher _passwordHasher; // 비밀번호 해싱기

    public UserManager(IUserRepository userRepository, IPasswordHasher passwordHasher) {
        _userRepository = userRepository; // 의존성 주입
        _passwordHasher = passwordHasher; // 의존성 주입
    }

    public void RegisterUser(string username, string password) {
        var hashedPassword = _passwordHasher.HashPassword(password); // 비밀번호 해싱
        _userRepository.SaveUser(username, hashedPassword); // 사용자 저장
    }

    public bool LoginUser(string username, string password) {
        var user = _userRepository.GetUser(username); // 사용자 조회
        return _passwordHasher.VerifyPassword(password, user.HashedPassword); // 비밀번호 검증
    }
}

public interface IUserRepository {
    void SaveUser(string username, string hashedPassword); // 사용자 저장
    User GetUser(string username); // 사용자 조회
}

public interface IPasswordHasher {
    string HashPassword(string password); // 비밀번호 해싱
    bool VerifyPassword(string password, string hashedPassword); // 비밀번호 검증
}

3. 개방 폐쇄 원칙


나쁜 예제

public class UserManager {
    public bool LoginUser(string username, string password) {
        // 로그인 로직
        // 기본 인증 방식
    }
}

 

좋은 예제

public interface IAuthenticationService {
    bool Authenticate(string username, string password); // 인증
}

public class UserManager {
    private readonly IAuthenticationService _authService; // 인증 서비스

    public UserManager(IAuthenticationService authService) {
        _authService = authService; // 의존성 주입
    }

    public bool LoginUser(string username, string password) {
        return _authService.Authenticate(username, password); // 인증
    }
}

public class BasicAuthenticationService : IAuthenticationService {
    public bool Authenticate(string username, string password) {
        // 기본 인증 로직
    }
}

public class OAuthAuthenticationService : IAuthenticationService {
    public bool Authenticate(string username, string password) {
        // OAuth 인증 로직
    }
}

4. 리스코프 치환 원칙


나쁜 예제

public class User {
    public virtual void Authenticate() {
        // 일반 사용자 인증
    }
}

public class GuestUser : User {
    public override void Authenticate() {
        throw new NotImplementedException("Guest users cannot authenticate"); // 예외
    }
}

 

좋은 예제

public abstract class User {
    public abstract void Authenticate(); // 인증
}

public class RegularUser : User {
    public override void Authenticate() {
        // 일반 사용자 인증
    }
}

public class GuestUser : User {
    public override void Authenticate() {
        // 게스트 사용자 인증 (특별한 처리 없음)
    }
}

5. 인터페이스 분리 원칙


나쁜 예제

public interface IUserService {
    void Register(string username, string password); // 사용자 등록
    bool Login(string username, string password); // 로그인
    void SendPasswordResetEmail(string email); // 비밀번호 재설정 이메일 전송
}

public class UserService : IUserService {
    public void Register(string username, string password) {
        // 사용자 등록
    }

    public bool Login(string username, string password) {
        // 로그인
    }

    public void SendPasswordResetEmail(string email) {
        throw new NotImplementedException(); // 예외
    }
}

 

좋은 예제

public interface IRegistrationService {
    void Register(string username, string password); // 사용자 등록
}

public interface ILoginService {
    bool Login(string username, string password); // 로그인
}

public interface IPasswordResetService {
    void SendPasswordResetEmail(string email); // 비밀번호 재설정 이메일 전송
}

public class UserService : IRegistrationService, ILoginService {
    public void Register(string username, string password) {
        // 사용자 등록
    }

    public bool Login(string username, string password) {
        // 로그인
    }
}

6. 의존성 역전 원칙


나쁜 예제

public class UserManager {
    private readonly SqlUserRepository _userRepository = new SqlUserRepository(); // 구체적 의존성

    public void RegisterUser(string username, string password) {
        _userRepository.SaveUser(username, password); // 사용자 저장
    }
}

 

좋은 예제

public interface IUserRepository {
    void SaveUser(string username, string password); // 사용자 저장
}

public class SqlUserRepository : IUserRepository {
    public void SaveUser(string username, string password) {
        // SQL 데이터베이스에 사용자 저장
    }
}

public class UserManager {
    private readonly IUserRepository _userRepository; // 추상화 의존성

    public UserManager(IUserRepository userRepository) {
        _userRepository = userRepository; // 의존성 주입
    }

    public void RegisterUser(string username, string password) {
        _userRepository.SaveUser(username, password); // 사용자 저장
    }
}

 

728x90
반응형