IT_study/스터디

객체지향 설계 원칙, 트랜잭션 격리, 해쉬테이블

meong_j 2022. 8. 24. 20:13
728x90
반응형

객체 지향 설계 원칙인 SOLID 원칙에 대해서 설명해주세요. 예시를 들어주세요.

객체지향 프로그래밍을 할때 지켜야할 5대 원칙을 말한다.

 

1. SRP(Single Responsibility Principle) 단일 책임의 원칙

  • 하나의 클래스은 하나의 책임(기능)을 가져야 한다는 것

예시)

어떤 자동차 클래스가 있는데, 엔진, 히터 등등 복잡한 시스템이 있다
class car {
   // 여기에 모두 넣어버리면 복잡해짐
  seat : 다른 클래스 불러옴(쪼갬)
  heater : 다른 클래스 불러옴(쪼갬)
}
=> 이러한 복잡한 시스템을 여러개로 쪼개서 나누고 하나로 묶는 것

 

 

 

2. OCP(Open Close Principle) 개방 폐쇄의 원칙

  • 확장에는 열려있고, 수정에는 닫혀있어야 한다는 원칙
  • 확장 - 요구사항이 변경될때 새로운 동작을 추가하여 애플리케이션의 기능을 확장할 수 있다
  • 수정 - 기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있다
  • 추상화에 의존
    • 추상화? 핵심적인 부분만 남기고, 불필요한 부분 제거함으로써 복잡한 것 -> 간단히 하는것

예시)

class Animal {
 울기 () {  
   강아지 -> 멍멍
   고양이 -> 야용
   // 기능 추가   => 계속 추가하면 안됨!!!!!
    소 -> 음메   
    ...
 }
}

////////잘못된 방법
Animal a = new Animal("강아지"); 
a.울기();

/////////옳은 방법
Animal 클래스를 상속받는 강아지.class, 고양이.class .... 만든다
소라는 클래스 만들고 Animal 클래스 상속받기
Animal  a = new 강아지();
Animal a = new 소();
a.울기();

 

 

3. ISP(Interface Segregation Principle) 인터페이스 분리 원칙

  • 목적과 관심이 각기 다른 클라이언트가 있다면 인터페이스를 통해 적절하게 분리해야함
  • 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공하는 것
  • 하나의 일반적인 인터페이스 보다는 여러개의 구체적인 인터페이스를 사용하는 게 좋다

예시)

Interface 동물 {
   짖기();
   걷기();
}

class 강아지 implements 동물 {
    짖기();
    걷기():
}

class 고양이 implements 동물 {
    //고양이는 짖기();가 필요없지만  인터페이스 받으면 짖기();도 같이 가져와야한다 
    걷기(); 
}


=> 그래서 짖기();용 인터페이스 따로   |    걷기();용 인터페이스 따로 여러개로 구분해서 분리해서 쓰는 것이 좋다!! 

 

 

 

4. LSP(Liskov Substitution Principle) 리스코프 치환 원칙

  • 올바른 상속 관계 특징 정의
  • 자식클래스는 언제나 부모클래스를 대체할 수 있도록 상속해야 한다는 원칙
    • 해당 객체를 사용하는 상위타입이 하위 타입으로 변경되어도, 차이점을 인식하지 못한채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용할 수 있어야 함

 

예시)

class 로보트 {
   size = 10*10;
}
를 상속받는 
class AI로보트 extends 로보트 {
}
자식 클래스가 있는데
 
로보트 a = new Al로보트();
a.size = 10*10; 이어야지 다른 값이면 안된다!!

 

 

5. DIP(Dependency Inversion Priniple) 의존 역전 원칙

  •  추상화에 의존하며 구체화에는 의존하지 않는 설계원칙
  • 개방 폐쇄 원칙과 밀접한 관련 있음 -> 2번
  • 의존관계에서는 좀 더 추상화된 것을 의존하는 게 좋다

예시)

class 토끼 {
    ///이런식으로 쓰지말고
    //먹이 = carrot;
    // vegetable 데이터 타입 받아서 쓰는 것이 좋다 
    vegetable 먹이;
}

// 상위개념을 의존하는 게 좋다!!!
class vegetable { // 부모클래스
}

// 이런 하위 개념을 의존하지 말고
class carrot extends vegetable {  //상속받음

class apple extends  vegetable {  //상속받음

 

결국, 핵심은 추상화이다.
구체 클래스에 의존하지 않고 추상 클래스(or 인터페이스)에 의존함으로써 유연하고 확장 가능한 애플리케이션을 만들 수 있다는 것!!!

 

출처:

https://www.youtube.com/watch?v=KO2xdqOZSAs


트랜잭션 격리 수준별로 어떠한 문제가 발생할 수 있을까요?

경쟁 상태 (Race Condition)

- 여러 클라이언트가 같은 데이터 동시 접근할 경우 문제 발생

  • 커밋되지 않은 데이터 읽기
  • 커밋되지 않은 데이터 덮어쓰기

- 트랜잭션 격리(Isolation)

트랜잭션을 격리시켜서 다른 트랜잭션이 영향을 주지 못하게 하는것

- 가장 쉬운 방법은 트랜잭션을 순서대로 실행하는 것

  동시 접근 문제 아예없지만

   한 번에 한개 트랜잭션만 처리하므로 성능(처리량) 저하 가능

- 그래서 !! 문제 상황에 맞게 다양한 격리 수준 지원

  • Read Uncommitted : 사실상 사용안함
  • Read Committed : 커밋된 데이터만 읽음
    • 트랜잭션이 끝날때 까지 기다려야함
    • 읽는 동안 데이터 변경
  • Repeatable Read : 트랜잭션 동안 데이터가 변경되더라도 같은 데이터를 읽게함
    • 변경한 내용이 유실될 수도 있다
  • Serializable : 인덱스 잠금이나 조건 기반 잠금 등 사용
    • 잠금 시간이 길어지면 성능(처리량) 저하

 

 

출처:

https://www.youtube.com/watch?v=poyjLx-LOEU

 

 

해쉬 테이블은 무엇인가요? 해쉬값이 충돌하면 어떻게 해결할 수 있을까요?

 

 

해쉬테이블 Hasp map (=Hash Table)

  • key-value 형태로 데이터를 저장하는 자료구조
  • 하나의 key는 하나의 value에 맵핑
  • key는 고유함

 

구현?

  • 배열을 사용하여 구현
    • 배열의 크기와 상관없이 데이터의 상수시간으로 접근 가능
    • array[index%key] 로 값 구함 (모듈러 연산)

 

 

해쉬충돌?

 -> 절대 hashmap은 key 사이즈 만큼 잡지 않는다

      만약 key 사이즈 만큼 잡아버리면 메모리 낭비 발생!!

예) 5000만 국민 모두 서비스 사용안함 -> key 5000만개 만들어봤자 필요x -> 현실은 1000명만 쓰고 있어서 hashmap 사이즈는 1000개 로 만들어둔다

 

해결 방법?

 

 

 

출처

https://www.youtube.com/watch?v=tEOkPaZXGOk 

https://www.youtube.com/watch?v=dKqv1mQotNU

반응형