• 다형성은 지연 바인딩 이라는 매커니즘 ( 왜냐면 런타임시에 결정되기 때문에 )
  • 상속은 코드를 재사용하게하는 널리알려진 방법이지만 캡슐화를 뭉갠다.
  • 캡슐화 측면에서는 합성이 더 좋다.
  • 유연한 객체지향 프로그램을 위해서는 컴파일 시간 의존성과 실행 시간 ( 런타임 ) 의존성이 달라야 한다.
  • 객체지향 패러다임의 핵심 역할 , 책임 , 협력

1. 협력

  • 애플리케이션이 기능을 구현하기 위해 수행하는 상호작용을 협력
  • 객체가 협력에 참여하기 위해 수행하는 로직은 책임
  • 객체들이 협력안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성한다.
  • 메세지 전송 ( message sending) 은 객체 사이의 협력을 위해 사용할 수 있는 유일한 커뮤니케이션 수단이다.
  • 메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다.
  • 객체를 자율적으로 만드는 가장 기본적인 방법은 내부 구현을 캡슐화 하는 것이다.
  • 객체가 자신의 정보를 바탕으로 직접 계산하면 결합도를 느슨하게 유지할 수 있다.
    • 다른 클래스의 변경의 여파도 줄일수 있다.

책임

  • 협력에 필요한 행동들을 할수있는 적절한 객체를 찾는것이다. 이때 협력에 참여하기 위해 객체가 수행하는 행동을 책임 이라고 부른다.
  • 책임 이란 객체에 의해 정의되는 응집도 있는 행위의 집합
    • 주로 책임은 무엇을 알고 있는가 ? 와 무엇을 할수 있는가로 구성된다.
    • 크레이그 라만은 이러한 분류 체계에 따라 객체의 책임을 크게 하는것과 아는것 두가지 범주로 나누어 세분화하고 있다.
    • 하는것
      • 객체를 생성하거나 계산을 수행하는 등의 스스로 하는것
      • 다른 객체의 행동을 시작시키는 것
      • 다른 객체의 활동을 제어하고 조절하는 것
    • 아는 것
      • 사적인 정보에 관해 아는것
      • 관련된 객체에 관해 아는것
      • 자신이 유도하거나 계산할 수있는 것에 관해 아는것.
  • 책임은 객체가 수행할수 있는 행동을 종합적이고 간략하게 서술하기 때문에 메세지보다 추상적이고 개념적으로도 메세지보다 더 크다.
  • 처음에는 단순한 책임이라고 생각했던것이 여러개의 메시지로 분할되기도 하고 하나의 객체가 수행할 수있다고 생각했던 책임이 여러객체들이 협력해야만 하는 커다란 책임으로 자라는 것이 일반적이다.

책임할당

  • 자율적인 객체를 만드는 가장 기본적인 방법은 그 정보를 갖고있는 객체에게 책임을 할당하는 것이다.
  • 이를 책임할당을 위한 Information Expert 정보 전문가 패턴 이라고한다.
  • 협력을 설계하는 출발점은 시스템이 사용자에게 제공하는 기능을 시스템이 담당할 하나의 책임으로 바라보는 것이다.
  • 객체지향 설계는 시스템의 책임을 완료하는데 필요한 더 작은 책임을 찾아내고 이르 객체들에게 할당하는 반복적인 과정을 통해 모양을 갖춰간다.
  • 항상 전문가에게만 요청하는 것은 아니다 어떤 경우엔 응집도와 결합도의 관점에서 정보전문가가 아닌 다른 객체에 책임을 할당하는것이 더 적절한 경우도 있다.

책임주도 설계

  • 협력을 설계하기 위해서는 책임에 초점을 맞춰야 한다는것.
  • 책임주도설계
    1. 시스템이 사용자에게 제공하는 기능인 시스템 책임을 파악한다.
    2. 시스템 책임을 더 작은 책임으로 분할한다.
    3. 분할된 책임을 수행할수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
    4. 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
    5. 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 된다.

메시지가 객체를 결정한다.

  • 객체에게 책임을 할당하는 데 필요한 메시지를 먼저 식별하고 메시지를 처리할 객체를 나중에 선택했다는것이 중요하다.
  • 다시 말해 객체가 메시지를 선택하는것이 아니라 메시지가 객체를 선택하게 했다.
  • 메시지가 객체를 선택해야 하는 이유
    1. 객체가 최소한의 인터페이스를 가질수 있게 된다.
    2. 객체는 충분히 추상적인 인터페이스 를 가질수 있게 된다
    • 객체의 인터페이스는 필요한 메시지가 식별될때까지 객체의 퍼블릭 인터페이스에 어떤것도 추가하지 않기 때문에 적당한 크기의 퍼블릭 인터페이스를 가질 수 있다.
    • 객체의 인터페이스는 무엇을 하는지는 표현해야 하지만 어떻게 하는지를 노출해서는 안된다. 메시지는 외부의 객체가 요청하는 무언가를 의미하기 때문에 메시지를 먼저 식별하면 무엇을 수행할지에 초점을 맞추는 인터페이스를 얻을 수 있다.

행동이 상태를 결정한다.

  • 객체가 존재하는 이유는 협력에 참여하기 위해서다.
  • 따라서 객체는 협력에 필요한 행동을 제공해야하며 객체를 객체답게 만드는 것은 객체의 상태가아니라 객체가 다른 객체에게 제공하는 행동
  • 초보자들은 먼저 객체에 필요한 상태가 무엇인지를 결정하고 그 후에 상태에 필요한 행동을 결정한다.
  • 이런 방식은 객체 내부 구현이 객체의 퍼블릭 인터페이스에 노출되도록 만들기 때문에 캡슐화를 저해한다.
  • 객체 내부의 구현을 변경하면 인터페이스도 함께 변경되고 결국 객체에 의존하는 클라이언트로 변경의 영향이 전파된다.
  • 객체 내부구현에 초점을 맞춘 설계 방법을 데이터 주도 설계라고 부른다.
  • 캡슐화를 위반하지 않도록 구현에 대한 결정을 뒤로 미루면서 객체의 행위를 고려하기 위해서는 항상 협력이라는 문맥안에서 객체를 생각해야 한다
  • 객체의 상태가 아니라 행동이 중요하다
  • 행동이 그객체의 책임이 된다

역할

역할과 협력

  • 객체는 협력이라는 주어진 문맥 안에서 특정한 목적을 가진다.
  • 객체의 목적은 협력 안에서 객체가 맡게되는 책임의 집합으로 표시된다.
  • 이처럼 객체가 어떤 특정한 협력안에서 수행하는 책임의 집합을 역할 이라고 한다.
  • 책에서 들어주는 예가 역할을 수행하는 객체를 선택하는게 인상적임.

유연하고 재사용 가능한 협력

  • 역할이 중요한 이유는 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있기 때문이다
  • 역할은 다른것으로 교체 할 수 있는 책임의 집합이다
  • 역할을 구현하는 가장 일반적인 방법은 추상 클래스와 인터페이스를 사용하는 것이다

객체 대 역할

  • 객체는 동일한 종류의 객체가 하나의 역할을 항상 수행한다면 둘은 동일한 것이다.
  • 하지만 어떤 협력에서 하나 이상의 객체가 동일한 책임을 수행할 수 있다면 역할은 서로 다른 방법으로 실행할 수 있는 책임의 집합이 된다.
  • 역할이란 프로그램이 실행될 때 소프트웨어기계 장치에서 적절한 객체로 메워 넣을 수 있는 하나의 슬롯으로 생각 할수 있다.
  • 대부분의 경우에 어떤 것이 역할이고 어떤 것이 객체인지 또렷하게 드러나지는 않는다.
  • 저자 개인적인 견해로는 설계 초반에는 적절한 책임과 협력의 큰 그림을 탐색하는것이 가장 최우선 목표이고 역할과 객체를 명확하게 구분하는것은 그렇게 중요하지는 않다는 것이다.
  • 따라서 애매하다면 단순하게 객체로 시작하고 반복적으로 책임과 협력을 정제해가면서 필요한 순간에 객체로부터 역할을 분리해내는 것이 가장 좋은 방법이다.
  • 중요한 것은 책임 이다.
  • 역할을 설계의 중심으로 보는 역할 모델링
    • 상호작용하는 객체들의 협력패턴을 역할들 사이의 협력 패턴으로 추상화 함으로써 유연하고 재사용가능한 시스템을 얻을수 있는 방법

역할과 추상화

  • 추상화를 이용하면 캡슐화가 가능해지고 내부 구현을 숨길수 있다.
    • = 추상화계층을 이용시 중요한 정책을 상위 수준에서 단순화 할수 있다
    • 왜냐면 내부 구현을 숨기고 상위 추상화만을 사용하기때문.
  • 추상화를 쓰면 설계가 유연해진다.
  • 이렇게 추상화를 사용하면 협력이라는 관점에서 세세한 구현사항은 무시하고 추상화에 집중하여 큰 그림을 파학할수 있다.

'book > 오브젝트' 카테고리의 다른 글

5장 - 2. 책임 할당을 위한 GRASP 패턴  (0) 2021.05.09
5장 - 1 책임 할당하기  (0) 2021.05.08
4장 설계 품질과 트레이드오프  (0) 2021.05.05
오브젝트 2장  (0) 2021.04.29
오브젝트 1장  (0) 2021.04.28

2장.

  1. 구현하기 전에 먼저 각 객체들이 어떤 상태인지 어떤 행동을 가지는지를 결정해야한다.
  2. 각 객체들은 독립적인 존재가 아닌 기능 구현을 위한 공동협력체의 일원으로 봐야한다.
  3. 클래스 내부의 인스턴스 변수들은 private으로 선언하여 외부의 접근을 막자.
    • 오로지 적절한 퍼블릭 메소드만을 사용해 내부상태를 변경할수 있게 해야한다.
  4. 내부와 외부를 구분해야하는 이유는 무엇일까 ?
    • 경계의 명확성이 객체의 자율성을 보장한다
      • 무슨소린지 이해를 못하겠음
      • 어느정도 명확한 경계를 통한 자율성의 범위를 정한다는것인지 ?
    • 구현의 자유를 제공한다.
      • 위와 같은 이야기인듯 ? 헷갈림.
  5. 객체는 상태와 행동을 같이 갖는 복합적인 존재
  6. 4번이야기를 좀더하자면 객체의 접근을 통제하면 좀더 자율적이게 됨.
    • 왜냐 다른곳에서 접근할수 없으므로 스스로 상태를 관리, 판단 할수 있게됨
    • 그렇기 떄문에 자율적이게 되는것.
  7. 외부에서 접근 가능한 부분은 퍼블릭 인터페이스
  8. 내부에서만 접근가능한것은 구현 ( implements )
  9. 인터페이스와 구현의 분리 원칙은 훌륭한 객체지향 프로그램을 만들기위해 따라야하는 핵심원칙이다.
  10. 객체가 객체와 통신하는법은 메세지를 전송하는것 뿐이다. 객체가 메세지를 수신하면 수신했다고 한다.
    • 이처럼 수신된 메세지를 처리하기위한 객체 자신만의 방법을 메소드라고 부른다.
  11. 템플릿 패턴을 이용하여 부모클래스에서 로직에대한 구현을 해놓고 자식클래스에서 세부사항을 구현한다.
  12. 전략패턴사용 다양한경우의 조건일 경우 interface를 이용한 전략패턴 사용
  13. 이러한 전략적패턴이라던지 템플릿패턴같은것들 사용하면 디버깅은 어려워지나 유지보수성은 좋아지고 유연성도 늘어난다.
  14. 자식클래스가 부모클래스를 대신하는것을 업캐스팅이라고 한다.
  15. 11~14까지가 다형성
    • 위와같은 부모클래스를 자식클래스들이 상속받아 어떤클래스가 실행되는지에 따라 결과도 달라진다.
  16. 이렇게 런타임시점에 결정되는것을 지연바인딩 또는 동적바인딩이라고 부른다
  17. 컴파일 시점에 결정되는것은 초기바인딩 또는 정적바인딩이라고 한다.
  18. 구현된 코드를 상속받는것은 변경에 취약한 코드다
    • 왜냐면 최상위코드가 변경이되면 하위코드도 다 변경해줘야하기 때문..
  19. 추상화를 사용하면 세부적인 내용을 무시한채 상위 정책을 쉽고 간단하게 표현할 수가 있다.
    • 추상화를 이용해 상위정책을 기술한다는 것은 기본적인 애플리케이션의 협력 흐름을 기술한다는 것을 의미
  20. 추상화를 사용할경우 그 추상클래스나 인터페이스를 상속이나 구현한 어떤 클래스를 추가하면 확장가능해진다.
  21. 이런것들을 컨텍스트 독립성이라고 불린다. 유연한 설계분야에서 진가를 발휘한다.
    • 결론은 유연성이 필요한곳에 추상화를 사용하라
  22. 추상클래스와 인터페이스 중에 어떤것을 고를것인지는 트레이드오프를 통해 정한다.
  23. — 상속 —
    1. 상속은 캡슐화를 위반한다 2. 설계를 유연하지 못하게한다. 위에서 설명함
  24. 캡슐화 위반은 부모클래스의 구현이 자식클래스에게 노출되기 때문.
    • 의문점 디폴트 메소드를 통한 인터페이스의 상속은 왜나온것인가 ?

'book > 오브젝트' 카테고리의 다른 글

5장 - 2. 책임 할당을 위한 GRASP 패턴  (0) 2021.05.09
5장 - 1 책임 할당하기  (0) 2021.05.08
4장 설계 품질과 트레이드오프  (0) 2021.05.05
오브젝트 3장 - 역할, 책임, 협력  (0) 2021.04.30
오브젝트 1장  (0) 2021.04.28

1장.

  1. 객체를 자율화 시켜서 그 객체의 책임이 있는 동작은 객체 스스로 처리하게 하자.
    • 그 객체 로직은 객체 내부에서 동작하자.
    • 그럼 캡슐화가 이루어진다. 외부에서 내부의 동작을 알 필요가 없어짐.
    • 또한 응집도가 높아진다 객체의 책임을 객체가 책임지기 때문에.
    • 결합도가 낮아진다 다른외부에서 이 객체를 가져다 내부작업을 할 필요가 없어졌기 때문에.
  2. 절차지향은 메인클래스에서 모든것을 처리하며 나머지 객체는 단지 데이터보관소에 불과할 뿐이다.
    • 하지만 객체지향은 모든 객체에 자율성이 존재하며 캡슐화가 이루어지며 응집도가 높고 결합도가 낮아진다.
    • 객체지향은 제어의 흐름이 각 객체에 적절하게 분산.
    • 절차지향은 제어의 흐름이 중앙에 한 클래스에 밀집되어있음.
  3. 설계를 어렵게 만드는것은 의존성. 쓸데없는 의존성을 제거해서 객체간의 결합도를 낮추자.
    • 결합도를 낮추기 위해서는 캡슐화를 하고 객체의 응집도도 높이자.
  4. 결합도와 자율성이 충돌되는 시점이 있다.
    • 이때는 트레이드오프로 잘 비교해보고 결정하자.
  5. 객체지향적 설계는 유지보수에 강점을 준다.

'book > 오브젝트' 카테고리의 다른 글

5장 - 2. 책임 할당을 위한 GRASP 패턴  (0) 2021.05.09
5장 - 1 책임 할당하기  (0) 2021.05.08
4장 설계 품질과 트레이드오프  (0) 2021.05.05
오브젝트 3장 - 역할, 책임, 협력  (0) 2021.04.30
오브젝트 2장  (0) 2021.04.29

문제

어느날 갑자기 api server가 죽어서 엄청 느려진 상태가 됬다.

파드를 내렸다가 올리면 정상적으로 작동하다 다시 느려지는 상태가 반복.

파드를 재시작할경우 정상적으로 작동하는것으로 보아 뭔가 쌓여서 문제가 되는것 같아

우선 네트워크부터 봤다.

처음시작할경우 netstat -antp로 보면 Est + Time_wait된 포트가 close_wait된 포트보다 많았으나

시간이 지날수록 close_wait된 포트가 많아지면서 서버가 응답이 느려지기 시작했다.

결론

Resttemplate으로 api서버에 요청을하는 서버에서 connection이 종료되지 않아서

CLOSE_WAIT이 쌓여 결국 서버가 멈추는 문제.

 

 

예측

  • Resttemplate이 작업을 처리하느라 close 요청을 못받는줄암.
  • 그래서 Resttemplate에서 응답을 받고 강제로 connection 을 종료 시켜주기로함.
    • Resttemplate는 직접 connection을 닫지않아도 자동으로 닫아준다고 했는데 안닫아지는건 뭔가 외부적인 이슈가 있을거라 판단
  • https://www.popit.kr/마이크로-서비스와-time_wait-문제/
    • 위 링크를 참조하여 EntityUtils로 닫아보려고 했지만 타입이 맞지 않아 에러로 닫아짐

해결

  • api서버에서 CLOSE 요청을 내려주질 않아서 Connection 을 종료할수 가 없는 상황.
  • 그래서 Resttemplate의 timeout 설정을 줘서 일정시간 없으면 요청을 종료하기로함.
  • 정상적으로 timeout 시간이 지나면 timeout으로 종료됨.

문제 2.

  • timeout줘서 요청을 종료하기로 했으나 api 서버에서 응답을 늦게내려줘서 모든 요청이 타임아웃 걸리는 상황.
  • api 서버를 확인해보니 포트 4만6천개정도가 사용중인 상태.

해결

  • 커넥션 새로 열때마다 새로운 포트를 생성하므로 커넥션풀을 만들어 사용하기로함.
  • 이미 커넥션풀이 있었으나 특정 요청은 커넥션풀이 적용되지 않았었음.
  • 그래서 적용되니 요청이 정상적으로 작동.
  1. 자식은 부모를 따라야된다 근데 자신을 반환할수도 있다
  2. 배열

공변 , 불변, 반공변

  • 공변 = ( ? extends T )
  • 반공변 = 공변의 반대 ( ? super T )
  • 불변 = 공변과 관계가 없음 ( 하위에서 상위로감 )
  • 메소드를 만드는 사람의 입장에서 다른사람이 이걸 어떻게 사용할지 공변 반공변을 정의해준다.

이펙티브 자바 31장 확인

 

PECS ?

제공하는 사람의 입장, 가져다 쓰는사람의 입장

'개발 > java' 카테고리의 다른 글

TDD 와 리팩토링  (0) 2020.09.07
JVM 구조 복습 - 1  (0) 2020.08.03
enum 사용시 주의할점  (0) 2020.05.13
멤버변수의 초기화 시기와 순서  (0) 2020.04.15

docker0

container가 통신하기 위한 가상 linux bridge

brdige는 기본적으로 l2통신 기반임

container가 하나 생성되면 이 bridge에 cotainer의 interface가 하나씩 binding되는 형태

그래서 container가 외부로 통신할때는 무조건 docker0 interface를 지나야 한다.

특징

  • IP는 자동으로 172.17.42.1로 설정됨. 16 bit netmask ( 255.255.0.0 ) 으로 설정
  • IP는 DHCP를 통해 할당받는 것이 아닌 docker 내부 로직에 의해 자동 할당받음
  • docker0는 일반적인 interface가 아닌 virtual ethernet bridge다.

'개발 > docker' 카테고리의 다른 글

Docker Image  (0) 2021.03.05
Linux Container  (0) 2021.03.03
docker-compose.yml 작성  (0) 2020.06.18
DOCKERFILE  (0) 2020.03.01
내가 자주쓰는 docker 명령어  (0) 2020.02.23
  • 컨테이너 생성

  • 이미지 안에 레이어로 이뤄져 있는 계층구조로 파일이 이뤄져 있음

  • 이 위에 READ WRITE 레이어를 하나 더 올림

  • 이 RW레이어를 통해 이미지의 파일을 읽고 쓰고 할수 있음.

  • 이 상태가 컨테이너

  • 이 RW 레이어를 통해 파일을 읽고 쓰도록 해주는 드라이버가

  • AUFS나 OVERLAY2

  • 도커 컨테이너의 성능은 그래서 이 스토리지 드라이버에 따라 차이가 남.

  • 컨테이너 내부에 프로그램을 구동시켜야되는데

  • 도커파일에 엔트리포인트에 정의된 실행파일 같은걸 실행시킴.

  • 이 과정에서 namespace 격리 cgroup의 자원할당이 일어남.

  • 일어나면서 외부와 격리됨.

  • 위의 과정에서 cgroup와 namespace는 저수준 컨테이너 런타임이 실행과정에서 처리해줌.

  • 저수준 컨테이너 런타임 = ( runc )

  • /var/lib/docker/overlay2/에 이미지가 저장됨

Docker와 containerd

  • 위의 runc로 cgroup namespace 일일히 다 oci 스펙에 맞게 config 작성하는것은 쉽지 않은 일.

  • 이걸 쉽게 해주는게 containerd

  • 도커는 continerd위에 올라가 있는 cli나 데몬 ( dockerd ) 임.

  • 도커는 컨테이너를 다루기 위한 모든 동작이 포함되어있음.

  • 그래서 자체 api나 자체 cli툴이 매우 강력함.

CRI-O

  • 이름부터 container runtime interface - open container initative 이다.

  • CRI 및 이미지가 OCI와 호환되는것에 중점을 둔 CR

  • 오로지 컨테이너의 실행을 목적으로 경량화 했기 떄문에 도커가 제공하는 컨테이너 생성 및 이미지 빌드와 같은 과정이 없었음.

  • 그래서 도커가 필요했음.

  • CRI-O 팀은 도커를 대체하는 툴들을 개발함.

  • Buildah, Podman, Skopeo

 

참고

https://www.samsungsds.com/kr/insights/docker.html

https://ssup2.github.io/theory_analysis/Docker_Component/

lugi 님

  • 유니온 파일 시스템 형식으로 이미지의 변경부분을 관리함

  • 유니온 파일 시스템 형식

    • aufs
    • btrfs
    • devicemapper
  • 도커는 베이스 이미지에서 바뀐 부분만 이미지로 생성

  • 컨테이너로 실행시 베이스 이미지와 바뀐 부분이미지를 합쳐서 실행

  • 각 이미지는 16진수로 ID를 구분한다.

Image Layer

이미지는 하나의 통짜 바이너리 덩어리가 아닌 여러개의 레이어로 이루어져 있다.

이 여러개 레이어는 계층구조로 이루어져 있다.

서로 다른 이미지가 여러개의 레이어를 공유할 수 있다.

만약 OS가 윈도우인 이미지를 받으면

이 윈도우 이미지와 동일한 이미지 위에 추가된 이미지들은 저 OS윈도우 이미지를 같이 사용한다.

그래서 이미지를 새로 받지 않는다.

( 모든 이미지 레이어는 한번만 받는다 )

이미지를 가져올때 도커는 각 레이어를 개별적으로 다운로드 한다.

여러개의 레이어가 이미 저장돼 있다면 도커는 저장되지 않은 레이어만 다운받는다.

이미지 삭제시 이미지가 사용중일 경우에는 이미지의 레이어들이 실제로 삭제 되지는 않는다.

참고

쿠버네티스 인 액션

시작하세요 도커 쿠버

'개발 > docker' 카테고리의 다른 글

docker 0  (0) 2021.03.14
Linux Container  (0) 2021.03.03
docker-compose.yml 작성  (0) 2020.06.18
DOCKERFILE  (0) 2020.03.01
내가 자주쓰는 docker 명령어  (0) 2020.02.23

+ Recent posts