스프링 입문을 위한 자바 객체지향의 원리와 이해 ( ~ 197p)

스프링 삼각형

  • IoC/DI, AOP, PSA.
  • 스프링을 지배하는 근원적인 요소.
  • POJO(Plain Old Java Object)에 세 가지 유형의 진동을 줌으로써 거대한 프레임워크를 완성.

현실 세계 vs 자바 세계

  • Write Once Run Anywhere.
현실 세계 자바 세계
하드웨어(물리적 컴퓨터) JVM(자바 가상 기계) - 가상의 컴퓨터.
운영체제 JRE(자바 실행 환경) - JVM용 OS
소프트웨어 개발 도구 JDK(자바 개발 도구) - JVM용 소프트웨어 개발 도구
  • JDK에는 JRE가 포함되어 있고, JRE에는 JVM이 포함되어 있다.
  • 편의를 위해, JDK만 배포 받으면 사용이 가능한 것이다.

  • JDK에는 자바 소스 컴파일러 javac.exe가 포함되어 있다.
    • .java -> .class
  • JRE에는 자바프로그램 실행기 java.exe가 포함되어 있다.
    • .class파일을 이용한 실행.

main() 메서드와 Java run

  • 간략히 추상화한 메모리 구조의 데이터 저장영역을 편의를 위해 T 메모리 모델 이라 부르겠다. SimpleMemory
  1. JRE가 프로그램의 main() 메서드가 있는지 확인한다.
  2. main() 메서드의 존재가 확인되면, JRE는 프로그램을 실행하기 위한 사전 준비.
    • 비유적으로, JVM 부팅.
  3. JVM은 object file 실행.
    • 패키지 로딩
      • java.lang 패키지 스테틱 영역에 위치시킨다.
      • import 된 패키지를 스테틱 영역에 위치시킨다.
    • 클래스 로딩
      • 프로그램 상의 모든 클래스를 스테틱 영역에 위치시킨다.
    • 스택 프레임 배치
      • Class를 생성하는 중괄호를 제외하고, 여는 중괄호를 만날 때 마다 Stack영역에 메서드 스택 프레임을 할당한다.
    • 변수 공간 배치
      • 메서드에 인자가 있다면, 인자를 저장할 변수 공간을 해당 스택 프레임 최하단에 확보한다.
    • 위 과정을 완료했다면, main() 메서드 안의 첫 명령문을 실행한다.
    • 닫는 중괄호를 만나면 스택 프레임을 소멸한다.
  4. main() 메서드가 종료되면 JRE는 JVM을 종료시키고 JRE 자체도 OS의 메모리에서 사라진다.

변수와 메모리

  • 로컬 변수는 Stack Area.
    • 스택 프레임이 사라지면 함께 사라진다.
  • 클래스 변수는 Static Area.
    • JVM이 종료될 때 사라진다.
  • 인스턴스 변수는 Heap Area.
    • 가비지 컬렉터가 힙 메모리 회수 시 사라진다.

멀티 스레드 / 멀티 프로세스

  • 멀티 스레드는 스택 영역을 스레드 개수만큼 분할하여 사용한다.

  • 멀티 프로세스는 다수의 데이터 저장 영역 즉 다수의 T 메모리 모델 을 갖는다.

  • 멀티 프로세스는 각자 고유의 공간을 침범할 수 없다.
  • 그에 반해 멀티 스레드는 스테틱 영역과 힙 영역은 공유한다. (멀티 프로세스보다 메모리를 적게 사용한다.)

클래스(Class) vs 객체(Instance)

  • 클래스는 개념이고 객체는 실체다.
    • 클래스는 분류에 대한 개념.
    • 클래스와 객체를 구분하는 정의 중 가장 와닿는 정의였다.
  • 또한 이 책의 작가는 객체와 클래스를 다음과 같이 정의하기도 하였다.
    • 객체 : 세상에 존재하는 유일무이한 사물.
    • 클래스 : 분류, 집합. 같은 속성을 가진 객체를 총칭하는 개념.

객체지향의 4대 특성

  1. 캡슐화(Encapsulation)
    • 정보 은닉(information hiding)
  2. 상속(Inheritance)
    • 재사용(re-use)
  3. 추상화(Abstraction)
    • 모델링
  4. 다형성(Polymorphism)
    • 사용 편의

상속

  • 객체지향에서의 상속 정의.
    • 상위 클래스의 특성을 하위 클래스에서 상속(재사용)하고,
    • 거기에 필요한 특성을 추가 및 확장 가능하다.
    • extends 라는 단어에서 느껴지듯, 상속 보다 확장의 개념이 강하다.
  • 부모 - 자식 보다는, 상위 분류 - 하위 분류 라고 이해하는 것이 더 좋다.
    • 상위 클래스 쪽으로 갈수록 추상화, 일반화 되었다고 말하며
    • 하위 클래스 쪽으로 갈수록 구체화, 특수화 되었다고 말한다.
  • Bird bird = new Bird()
    • 위와 같은 선언을 줄이자.
    • Bird theBird = new Bird() 가 훨씬 명확하다.
  • 상속은 is a 관계다?
    • is a kind of 관계 가 더욱 명확하다.
    • 하위 클래스 is a kind of 상위 클래스
  • 하위 클래스 인스턴스가 생성될 때 상위 클래스의 인스턴스도 함께 생성된다.
    • 당연히 Heap 영역.

인터페이스
  • 구현 클래스 is able to 인터페이스
  • 구현 클래스는 인터페이스 할 수 있다.
  • 때문에 인터페이스는 be able to 라는 표현 형태로 만드는 것이 좋다.
    • 예) Comparable, Runnable, Cloneable …
  • 퍼블릭 추상 메서드와 퍼블릭 정적 상수만을 가질 수 있다.
    • 메서드에는 따로 입력하지 않아도 public, abstract가 추가되어 컴파일 된다.
    • 속성에는 public, static, final이 추가되어 컴파일 된다.
    • 하지만, 키워드들을 적는 것이 보다 명확하다.
  • 자바 8, 람다를 지원하면서 부터
    • 디폴트 메서드를 지원하도록 스펙이 바뀌었다.
      • 객체 구상 메서드, 정적 추상 메서드
  • 인터페이스는 구현을 강제하는 메소드가 적을수록 좋다.
    • 상속은 반대로 많을수록 좋다고 할 수 있다.

추상

  • 객체지향의 추상화는 곧 모델링이다.
  • 추상의 사전적 의미 : 여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용.
    • 조금 더 자세히
      • 구체적인 것을 분해해서 관찰자가 관심 있는 특성만 가지고 재조합 하는 것
    • 조금 더 IT 적으로
      • 추상화란, 구체적인 것을 분해해서 관심 영역(애플리케이션 경계, Apllication Boundary)에 있는 특성만 갖고 재조합 하는 것
      • = 모델링.

다형성

  • 다형성의 가장 기본은 오버라이딩과 오버로딩에 있다.
    • 오버로딩이 다형성인지 아닌지에 대해서는 이견이 있다고 한다.

Abstract

  • 추상 클래스
    • 하나 이상의 메소드가 추상 메소드인 경우.
    • 사실 추상 메소드가 없어도 추상 클래스로 선언은 가능하다.
      • 하나 이상의 추상 메소드를 갖는 경우 반드시 추상 클래스로 선언하여야 한다.
    • 추상 클래스는 인스턴스를 생성할 수 없다.
    • 추상 클래스를 상속 받는 하위 클래스는 반드시 추상 메소드의 구현부를 구현해야 한다.
      • 오버라이딩 강제.

static block

public class A {
    static {
        System.out.println("hello");
    }
}
  • static block에 놓인 코드블록은 클래스가 스테틱 영역에 배치될 때 단 한 번 실행된다.

  • 클래스 정보는 해당 클래스가 코드에서 맨 처음 사용될 때 메모리의 스태틱 영역에 로드된다.

  • 위와 유사하게 아무런 표시 없이 {} block을 사용하게 되면,
  • 인스턴스가 생성될 때 마다 생성자보다 먼저 {} block을 실행한다.

final

  • final keyword가 붙을 수 있는 곳은 세가지. 클래스, 변수, 메소드.
  • final Class
    • 상속을 허용하지 않는다.
  • final 변수
    • 상수(변경을 허용하지 않는다.)
  • final 메소드
    • 오버라이딩을 허용하지 않는다.

SOLID

  • 객체 지향 프로그래밍 설계의 다섯 가지 기본 원칙.
  • for High Cohesion, Loose Coupling
    • 응집도↑, 결합도↓

SRP(Single Responsibility Principle)

“어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.” - 로버트 C.마틴

  • 단일 책임 원칙.

  • 설계(모델링) 시, 단일 책임 원칙을 고려하는 습관을 들이자.
    • 애플리케이션 경계를 정하고
    • 추상화를 통해 클래스, 속성, 메소드를 설계할 때.
    • 단일 책임 원칙을 기억하자. 애플리케이션의 경계를 정하고 추상화를 통해 클래스들을 선별하고 속성과 메소드를 설계할 때.
  • 또한, 리팩토링을 통해 코드를 개선할 때에도 단일 책임 원칙을 기억.

OCP(Open Closed Principle)

“소프트웨어 엔티티는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다.” - 로버트 C.마틴

  • 개방 폐쇄 원칙.

  • 확장성 있게 설계하고,
  • 변화에 유연하게 대처할 수 있게 설계하라는 것 같다.

  • 하나의 예로 JDBC 인터페이스를 들었다.
    • DB가 변경(MySQL -> Oracle 등)되더라도, Connection을 설정하는 부분 외에는 아무것도 수정할 필요가 없다.
    • 변경 시에 수정할 부분은 아주 미세하나, 확장 시 매우 편리한 것.
  • 위 규칙을 준수할 경우 유연성, 재사용성, 유지보수성이 향상하는 효과를 얻을 수 있다.

  • 하지만, 너무 어려워 보인다.

LSP(Liskov Substitution Principle)

“서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다. - 로버트 C.마틴

  • 리스코프 치환 원칙.

  • 즉, 하위 클래스의 인스턴스는 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야 한다.

ISP(Interface Segregation Principle)

“클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.” - 로버트 C.마틴

  • 인터페이스 분리 원칙.

  • 인터페이스는 그 역할에 충실한 최소한의 기능만 공개.
  • 인터페이스는 is able to 라는 기준으로 만드는 것이 정석.

DIP(Dependency Inversion Principle)

“고차원 모듈은 저차원 모듈에 의존하면 안된다.
이 두 모듈 모두 다른 추상화된 것에 의존해야 한다.”
“추상화된 것은 구체적인 것에 의존하면 안된다.
구체적인 것이 추상화된 것에 의존해야 한다.”
“자주 변경되는 구체 클레스에 의존하지 마라” - 로버트 C.마틴

  • 의존 역전 원칙.

  • 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것이 의존 역전 원칙이다.