자기가 처리하면 위임이 아님

포함은 어떤 객체가 다른 객체를 품고 있으면 포함

그 객체를 쓴다는 건 그 객체에 의존한다는 거

그 작업을 하기 위해서는 걔가 필요함

특정 메서드를 실행할 때 포함할 거냐
그게 의존(Dependency) 관계

내가 이 특정 메서드에만 쓰는 게 아니라
다른 메서드에서도 계속 쓰면 연관
Aggregation

com.eomcs.oop.ex05.x5.CarTest2.java
Sedan의 run()을 호출하는 거

추상클래스의 목적은 서브클래스에 공통 기능을 물려주는 것
이 클래스를 상속받아서 구체적인 클래스를 만들라는 거

추상클래스와 구현

03-OOP2 / 9 페이지

<<abstract>> AbstractCar
start() {...}
stop() {...}
run()

🔹 추상클래스의 목적
‐ 서브클래스에게 공통 기능을 상속해 주는 것이 목적
start(), stop() ← "이건 내가 만들어놨다. 필요할 때 써라"
run() ← "이건 Car 클래스에 있어야 할 기능이지만 여기서 구현하지 않았다. 서브클래스에서 자신의 역할에 맞춰 잘 구현해라."

generalization (일반화) : 둘 사이의 공통점을 뽑아서 추출
generalization을 통해서 수퍼클래스를 만든 경우는 보통 추상클래스로 선언한다

추상클래스를 만든 개발자의 의도
→ 상속받아서 입맛에 맞게 만들어서 써라

상속받아서 쓰더라도 서브클래스가 공통적으로 가져야 할 기능은 미리 만들어 놓을게요
서브클래스마다 다를 거 같은 건 구현 안 해놓을게요
서브클래스 역할에 맞춰서 구현하면 돼요
라고 뉘앙스를 받아 들여야 한다

추상클래스의 인스턴스를 만들 수 있게 해버리면
run() 이라는 메서드는 구현되지 않은 상태인데
추상메서드는 구현되지 않은 상태여서 이런 상황을 방지하기 위해서 추상클래스의 인스턴스를 못 만들게 했다

자동차는 기본적으로 어떤 일을 해야 되는지 다 짜놓았다
서브클래스 만들어서 쓰세요
대신 run() 메서드는 Sedan에 맞게 구현하셔야 돼요
Sedan : Concrete(구체적인) class ← '추상적'과 반대 의미
추상클래스 아닌 일반 클래스를 콘크리트 클래스라고 한다.

추상클래스를 상속받아서 클래스를 만든 경우, 추상메서드를 구현하지 않으면 빨간밑줄 나옴. 추상클래스가 만들지 않은 메서드를 만들어야 됨.
서브클래스마다 독특한 작업 수행. 만들어봤자 어차피 서브클래스에서 오버라이딩 해야 되니까 수퍼클래스에서 선언만 하고 정의하지 않은 거. 구현은 서브클래스에 맡긴다.

AbstractCar car;
car = new ASedan();

여기서 다형적 변수가 나온다
어떤 레퍼런스는 그 타입의 객체를 담을 수도 있지만, 그 타입의 서브 타입 객체도 담을 수 있다. (객체 주소를 담을 수 있다.)

어떤 레퍼런스는 자식 타입의 객체 주소를 담을 수 있다.
= 자식 클래스의 인스턴스 주소를 담을 수 있다.
= 자식 타입의 인스턴스 주소를 담을 수 있다.
= 자식 인스턴스의 주소를 담을 수 있다.
= 자식 객체의 주소를 담을 수 있다.
= 자식 객체를 가리킬 수 있다.

서브 클래스의 인스턴스 주소를 담을 수 있다. ← 너무 말이 김
줄여서 "자식 객체를 가리킬 수 있다"
가리킨다를 "저장한다"고 말하기도 한다.
"자식 객체를 담는다"
자식 객체의 주소를 담는 거고 결국 자식 객체를 가리키는 거

AbstractCar car;
car = new ASedan();

car.start();
car.run();
car.stop();

AbstractCar에 start() 메서드 있음 → OK! 컴파일 통과!
AbstractCar에 run() 추상메서드 있음 → OK! 컴파일 통과!
추상메서드인데요..?
컴파일러 입장에서는
추상클래스 객체를 만들어서 호출하진 않을 거를 알고 있음
추상클래스의 서브클래스 중에서 인스턴스를 만들 수 있는 서브클래스의 객체를 담아서 그걸 호출할 거니까 서브클래스에 run() 메서드가 구현된 상태일 것이라고 판단한다.
메서드가 추상메서드냐 아니냐는 컴파일러가 안 따짐
메서드가 있냐 없냐를 따짐
AbstractCar에 stop() 메서드 있음 → OK! 컴파일 통과!

실행하면 그때부터는 JVM의 일
클래스 파일이 만들어졌다는 건 문법적으로 문제가 없다는 뜻

car가 실제 가리키는 건 ASedan
ASedan에서 start()를 찾는다
ASedan에 없으면 수퍼클래스를 찾아간다
시작은 ASeda부터 찾아 올라가는 거
car 레퍼런스에 저장된 인스턴스에 찾아간다. 거기에 인스턴스 정보가 있다. 어떤 클래스의 인스턴스인지 알 수 있다. car가 실제 가리키는 인스턴스.
ASedan에 가서 run() 메서드가 있는지 찾는다. 있다! 호출한다. (추상메서드가 호출되는 게 아니다.)
ASedan에 가서 stop()을 찾는다. 없으면 수퍼클래스로 가서 찾는다.

AbstractCar car;
car = new ASedan();

car.start();
car.run();
car.stop();
car.openSunroof(); // 컴파일 에러!

JVM은 호출할 수 있는데 실행하고 싶어도 실행이 안 됨
컴파일러 단계에서 에러가 남.
컴파일 안 해줌. 컴파일러는 문법적으로 따짐.
추상메서드든 구현된 메서드든 AbstractCar에 있는 메서드면 OK
메서드가 구현되어 있는 상태인지 안 따짐.

(AbstractCar car)
서브클래스도 다 가능해서 뭐가 넘어올지 컴파일러는 모름
그래서 에러 냄
컴파일러 입장에서는 서브클래스 중에 뭐가 넘어온지 모름
문법적으로만 따짐

디버깅 해보면 실제로 어느 메서드가 실행되는지 알 수 있다.

상속이라는 문법에는 반드시 다형성이 등장한다.

AbstactCar car
car = new AbstactCar(); // 추상클래스는 인스턴스 생성 불가능!!!
car = new Sedan(); // OK
car = new Truck(); // OK

car = new AbstactCar(); // 추상클래스는 인스턴스 생성 불가능!!!
추상클래스이기 때문에 AbstactCar 인스턴스를 담을 수 없음.
구현된 서브클래스를 담아야 됨
car = new Sedan(); // OK
car = new Truck(); // OK
전형적인 다형성 변수
추상메서드를 서브클래스에서 정의하는 것도 오버라이딩
상속이라는 문법과 함께 '다형적 변수'나 '오버라이딩'이 같이 딸려옴
'생성자'도! 수퍼클래스 생성자를 자동으로 호출하는 거

com.eomcs.oop.ex05.x6

com.eomcs.oop.ex05.x6 패키지 생성

단순한 문법을 구현할 줄 알아야 됨

실전 프로그램 1단계

메서드는 기본적으로 public으로 하면 됨

boolean openedSunroof; // 상태를 저장할 인스턴스 변수 필요해서 추가함

설계도면에 없는 변수를 만들어야 될 경우가 발생함
변수 만들고 설계도면 바꾸면 됨

유지보수 → 중복코드 제거
공통 분모 찾기
쓰려고 만든 게 아니라 중복되지 않게 하기 위해서 만든 거
generalization 할 때 추상클래스가 만들어진다.
일반클래스는 추상메서드는 가질 수 없다.
추상메서드를 가질 수 있는 건 추상클래스 뿐이다.
기존에 Truck 메서드를 쓴 것들도 다 바꿔줘야 됨
지금 바꿔주는 게 향후 유지보수에 낫다

package com.eomcs.oop.ex05.x6;

public class CarTest1 {

  public static void main(String[] args) {
    Sedan sedan = new Sedan();
    testSedan(sedan);
    
    System.out.println("----------------------------");

    Truck truck = new Truck();
    testTruck(truck);
  }

  static void testSedan(Sedan car) {
    car.start();
    car.run();
    car.stop();
  }

  static void testTruck(Truck car) {
    car.launch();
    car.go();
    car.stopping();
  }

}
          Sedan
CarTest1 
          Truck

CarTest1은 Sedan도 사용하고 Truck도 사용한다.
서로 관계를 맺었다는 걸 coupling 이라고 한다.
CarTest1은 Sedan과 Truck 두 개의 객체와 관계를 맺고 있다.
두 개의 클래스와 관계를 맺고 있다.
클래스, 인스턴스, 메서드, 필드, 변수를 퉁쳐서 객체라고 표현한다.

클래스
인스턴스
메서드
필드
로컬 변수

'객체'라는 단어가 그렇게 쓰임

객체가 클래스를 의미하는지 인스턴스를 의미하는지 메서드를 의미하는지
문맥에 따라서 상황에 따라서 파악해야 된다.

클래스와 클래스 사이의 관계인데 왜 객체 간의 관계라고 하느냐
객체라는 게 문맥에 따라서 클래스가 될 수도 있고 인스턴스가 될 수도 있음
설명서에서 객체라고 말해도 헷갈리지 말기

실전 프로그램 2단계 - 상속, 오버라이딩, 다형적 변수

두 클래스에 공통점이 발견됨
Car를 만든다

상속 2가지
수퍼클래스에서 서브클래스를 만드는 거 ← specialization
서브클래스를 가지고 수퍼클래스를 정의하는 거 ← generalization
이렇게 만들어진 수퍼클래스는 추상메서드가 없다 하더라도 추상클래스로 선언한다. 추상메서드가 있어야 추상클래스가 되는 게 아님. 추상클래스는 직접 쓰지 말고 상속받아서 서브클래스 만들어서 쓰라고 만든 거.
공통분모 물려주려고 만든 거야

실무에서는 추상클래스 일반클래스로 만들어야 될 지 애매할 때가 있음
공부할 때는 선명하게 하기!
추상클래스 만들어놓고 마음에 안 들면 abstract 떼버리면 됨

abstract가 붙었으면 무조건 서브클래스 만들어서 쓰라는 거

기존의 트럭 메서드에서 다 에러남
실무에서는 이게 단순하지 않음

같은 종류가 되는 순간
testSedan testTruck 따로 만들 필요가 없음

새로 만든 검사소는 규칙이 있음
testCar(Car car)
우리는 Car 종류만 테스트 합니다.

자동차 검사소가 100군데가 있는 상태에서 트럭을 바꿔버리면 100군데 다 못 씀

기존에 만든 클래스를 이미 사용해서 프로젝트를 진행한 것들이 많음
기존 프로그램도 고려해서 바꿔야 됨

기존 메서드들 그대로 두고
상속받은 메서드는 오버라이딩 해서 기존 메서드 호출하게 한다

package com.eomcs.oop.ex05.x6;

public class Truck extends Car {
  int weight;

  @Override
  public void run() {
    // 기존에 이미 있는 메서드를 호출한다.
    this.go();
  }

  @Override
  public void start() {
    this.launch();
  }

  @Override
  public void stop() {
    this.stopping();
  }

  public void launch() {
    System.out.println("트럭 시동 건다!");
  }

  public void stopping() {
    System.out.println("트럭 시동 끈다!");
  }

  public void go() {
    System.out.println("덜컹덜컹 달린다!");
  }

  public void dump() {
    System.out.println("짐 내린다!");
  }
}

기존 검사소는 그대로 유지하고
신규 검사소에 맞춰서 돌아가도록

기존의 메서드를 호출

기존 메서드 코드를 그대로 복붙하는 건 너무 비효율적
기존 메서드를 호출하는 게 효율적!

기존 검사소에서도 돌아가고 신규 검사소에서도 돌아간다

실전 프로그래밍 2단계 - 상속, 오버라이딩, 다형적 변수

CarTest2 → Car
coupling이 줄었다.
testCar(Car car)
구체적으로 관계를 맺는 건 Car
연결성이 줄어들었다.
연결성이 줄어들었다는 건 Sedan이랑 Truck에 변경사항이 발생해도
영향을 덜 받는다는 거
객체지향에서는 coupling을 줄이는 게 중요하다
Low Coupling

신규 자동차 만들자
SUV

package com.eomcs.oop.ex05.x6;

public class SUV extends Car {
  boolean enabled4wd;

  @Override
  public void run() {
    if (enabled4wd) {
      System.out.println("강력한 파워로 달린다!");
    } else {
      System.out.println("그냥 달린다!");
    }
  }

  public void active4wd(boolean enable) {
    this.enabled4wd = enable;
  }
}

run()을 실행하기 전에 active4wd 상태값을 바꿔준다.

    SUV suv = new SUV();
    suv.active4wd(true);
    testCar(suv);

데코레이터 패턴을 사용해보자

실전 프로그래밍 3단계 - 데코레이터 설계 기법 적용

기존 객체에 옵션을 붙였다 떼었다 하고 싶다
메서드를 붙였다 떼었다 하고 싶다

Option ← 별도의 수퍼클래스로 만든다. 데코레이터로서 기존 객체에 붙이는 역할.
기존 객체에 붙이기 때문에 Car를 포함하는 관계

기존 객체에 기능을 붙였다 떼었다 하고 싶다
기존 그대로 유지하면서 기능을 붙였다 떼었다 하고 싶은 거

데코레이터는 Sedan, Truck, SUV와 똑같은 조상을 가져야 한다.

Car를 포함한다는 건 Sedan, Truck, SUV, 자기 자신까지 포함할 수 있다는 거

public abstract class Option extends Car {
  Car car;
}

Car를 포함할 수 있다는 건 Sedan, Truck, SUV를 다 포함할 수 있다는 거

Option도 Car의 자식

Option 자체가 직접 쓰이는 건 아니기 때문에 추상클래스로 만든다.
Option 상속받아서 서브클래스 만들어서 쓸 거임

어떤 클래스가 걔를 포함한다
사람이 핸드폰을 사용하는 거지 포함하는 게 아님
교육센터가 전자칠판을 포함한다
교실이 칠판을 포함한다 ← 집합(aggregation) 관계
집합도 포함이고 복합도 포함인데
폐업한다고 하더라도 전자칠판은 다른 용도로 쓴다
LifeCycle이 다르면 일반적인 집합 관계
교실은 형광등을 포함하는데 교실이 파괴될 때 사라진다. 교실과 LifeCycle 같다.

연관(association) 관계
사람이 핸드폰을 사용하는데 일시적으로 쓰는 게 아니라 지속적으로 쓴다.

의존(dependency) 관계
특정 메서드에서만 파라미터로 받아서 사용한다면
파라미터로 받을 수도 있고 메서드 안에서 생성해서 쓸 수도 있음
특정 메서드 안에서만 사용하는 객체라면 의존 관계라고 한다.
다 의존 객체인데 관계라는 측면에서 의존(Dependency) 관계라고 한다
일시적으로 사용하는 거

집합 관계, 복합 관계
인스턴스 필드 포함
연관 관계나 집합 관계나 복합 관계나 코드는 똑같음
코드로 구분이 안 됨
개념적으로 그렇다는 거지 코드는 똑같음

Option과 Car는 집합(aggregation) 관계

Car car; ← 이 변수에 대한 용어가 있는데...

package com.eomcs.oop.ex05.x6;

public abstract class Option extends Car {
  Car car;

  public Option(Car car) {
    this.car = car;
  }
}

눈 올 때 체인 + 자동차

Option(Car car)
Option의 서브 클래스들은 반드시 생성자에서 포함하는 Car 객체를 받아야 한다. 어느 자동차에 붙일지!

이 그림(↓)을 보고 이 코드(↑)를 떠올릴 수 있어야 함

Option 자체를 쓰기 위해서 만든 게 아니라 Option 클래스를 묶어주는 역할을 하기 때문에 인스턴스를 만들어서 쓸 일이 없다. 추상메서드로 만드는 게 적절하다.

Option을 상속받아서 데코레이터 SnowChain을 만들자

<<concrete>> SnowChain ← 콘크리트 클래스
class SnowChain extends Option

package com.eomcs.oop.ex05.x6;

public class SnowChain extends Option {

  public SnowChain(Car car) {
    super(car);
  }

  @Override
  public void run() {
    System.out.println("도로 마찰력을 증가시킨다.");
    car.run();
  }

  @Override
  public void start() {
    // 데코레이터는 자동차가 아니다.
    // 따라서 시동을 걸라고 요청이 들어오면
    // 데코레이터를 붙인 자동차에게 위임해야 한다.
    car.start();
  }

  @Override
  public void stop() {
    car.stop();
  }

}

Option에는 기본 생성자 없음. Car 객체를 받는 생성자밖에 없음.
기본 생성자가 없으니까 SnowChain에서 기본 생성자 자동으로 호출되면 안 됨
super(car) ← Car 객체를 받는 생성자를 명시해준다

블랙박스 옵션 추가하자
BlackBox
class BlackBox extends Option

run() 달리기에 옵션을 넣고 싶은 거
달리는 게 주임

super.start() → car.start()
자기거 쓰면 안 됨
car로 바꿔준다

데코레이터는 자기가 상속받은 메서드는 버려버림

Option에서 Car 메서드 오버라이딩 하는 걸로..

package com.eomcs.oop.ex05.x6;

public abstract class Option extends Car {
  Car car;

  public Option(Car car) {
    this.car = car;
  }

  @Override
  public void start() {
    // 데코레이터는 자동차가 아니다.
    // 따라서 시동을 걸라고 요청이 들어오면
    // 실제 자동차 객체에게 위임해야 한다.
    car.start();
  }

  @Override
  public void stop() {
    // 데코레이터는 자동차가 아니다.
    // 따라서 시동을 끄라고 요청이 들어오면
    // 실제 자동차 객체에게 위임해야 한다.
    car.stop();
  }
}

super.start()로 변경
super.stop()로 변경

package com.eomcs.oop.ex05.x6;

public class BlackBox extends Option {

  public BlackBox(Car car) {
    super(car);
  }

  @Override
  public void run() {
    car.run();
  }

  @Override
  public void start() {
    System.out.println("녹화 시작!");
    super.start();
  }

  @Override
  public void stop() {
    System.out.println("녹화 종료!");
    super.stop();
  }

}

트럭에 블랙박스 붙여서 테스트해보자

기능을 무조건 포함하는 게 아니라 기능을 자유롭게 확장하고 싶어서

뽁뽁이를 붙이고 그 위에 선팅지를 붙이면 안 됨
순서가 있음

영화관 3D 안경
내 안경 끼고 그 위에 3D 안경 낌

데코레이터 중에서도 순서를 지켜야 되는 게 있고
순서가 바뀌어도 상관 없는 게 있음
데코레이터 사용법에 따라서 내가 결정해야 됨

데코레이터를 사용하는 시점에 로딩된다.
인스턴스를 만드는 시점에 로딩된다.

I/O Streams - java.io.*, java.nio.*

04-입출력스트림 / 1 페이지

자바 패키지들을 다시 모듈로 묶어버림
옛날에는 자바의 패키지가 한 단위로 묶었음
자바에서 제공해주는 패키지가 엄청하게 많은데 한 단위로 묶어버리니까

인터페이스는 나중에 다 설명해줄 거임

character stream classes
char 흐름을 다루는 클래스들

byte stream classes
byte 단위로 데이터를 읽고 쓰는 그 흐름을 다루는 클래스들

data sink stream classes
데이터가 저장된 곳에서 직접 I/O 수행

data processing Stream classes (데코레이터)
중간에서 데이터를 가공

문자를 처리하는 클래스냐 일반 바이트 단위로 주고 받는 클래스냐

클래스 중에서 직접 데이터에서 읽어들이는 클래스냐 아니냐

sink 장소가 파일이냐 아니면 메모리냐 아니면 다른 프로세스냐

실행 중인 프로그램을 '프로세스'라고 한다.

Writer 계열과 Reader 계열

OutputStream 클래스와 InputStream 클래스로 나뉜다

클래스 이름 뒤에 Writer / Reader / OutputStream / InputStream 라고 붙기 때문에 클래스 이름만 보더라도 어디에 속해 있는지 알 수 있다.

🔹 파일
FileWriter / FileReader

🔹 메모리
CharArrayWriter / CharArrayReader
StringReader / StringWriter
캐릭터 배열에 데이터를 읽고 쓰는 거
캐릭터 배열로 문자를 출력

자바 프로그램끼리 주고 받을 때
🔹 다른 프로세스
PipedReader / PipedWriter
어떤 프로그램의 출력이 다른 프로그램의 입력으로 들어갈 때 쓰는 방법

ps -al

ps -el

ps -el |

파이프라인

유닉스에서는 입력된 데이터에서 검색하는 기능이 있는데 grep이다.
grep ← 검색해주는 프로그램

오른쪽에 바로 키워드
ps -el | grep java
ps -el | grep eclipse

ps ← 프로세스 목록 출력하는 거

-el 옵션을 주면 운영체제가 내부적으로 실행하는 프로그램 목록까지 출력

그 출력을 화면에 보내지 않고 grep 이라는 프로그램으로 보내버리는 거

이때 두 프로그램 사이에 파이프가 연결되는데 ps 프로그램의 출력을 PipedWriter
grep에서 다른 프로그램의 출력을 받아야 됨
grep은 PipedReader를 사용해야 됨

PipedWriter
화면을 출력하는 게 아니라 연결된 다른 프로그램의 입력으로 보냄

PipedReader
연결된 프로그램에서 출력하는 걸 받는, 읽어들이는 일을 한다.

자바 프로그램을 이런 식으로 돌아가게 하려면 자바 프로그램이 다른 자바 프로그램으로 출력하려면 PipedWriter
다른 자바 프로그램이 출력한 걸 읽어들이려면 PipedReader를 써야 된다
지금 쓸 일은 없지만 무슨 의미인지는 알아야 됨
자바에서만 있는 개념이 아니라 원래부터 유닉스 운영체제 있는 거

strlen
유닉스는 함수 단위로 프로그램이 존재한다
작은 함수 단위의 프로그램들이 수백개 존재
그 함수 단위의 프로그램을 명령창에서 실행을 하는데 그 실행결과를 파이프로 쭉 연결하면서 우리가 원하는 작업 결과를 얻을 수 있다.
그게 유닉스의 프로그램 실행 원리
유닉스는 프로그램 한 개가 다 하는 게 아니라 함수 단위의 프로그램을 잘게 쪼개서 하나의 독립적인 프로그램으로 만들어놓고 마치 레고 조립하듯이 그 프로그램들을 조립해서 사용자가 원하는 걸 만들어낸다

cat CarTest1.java
파일을 바로 읽어서 콘솔창에 보여줌

이 파일에 단어가 몇 개인지 알고 싶음

unix word count

cat CarTest1.java | wc

25 45 447

cat CarTest1.java | wc -l ← 라인 카운트

25

25개 라인

유닉스 프로그램이 함수 단위의 기능을 아예 독립적인 프로그램으로 만듦

grep ← 단어 검색. 그 단어를 포함하는 한 줄을 찾는 거.

cat ← 파일을 읽어들임

wc ← 카운트 하는 거

명령창에서 쓰는 문법이 필요
그 문법을 shell script 라고 한다

자바는 얘가 shell script

배치파일..

@ECHO OFF ← 화면 출력을 막음

이게 shell script
명령창에서 실행하는 shell script

Unix 라는 운영체제에 아주 작은 단위
wc, grep, cat, echo, strlen, ... 등등 수많은 프로그램들이 있음
실행하려면 콘솔창 필요. 명령어를 작성해야 됨.
명령어를 작성할 때 사용하는 게 shell script
왜 shell입니까? 사람이 운영체제에게 직접 얘기 못하니까 console창을 통해서 운영체제에 얘기한다. 운영체제 껍데기 역할을 하는 거.
유닉스 껍데기 shell을 통해서 운영체제를 실행.
가볍게 쓸 수 있는 프로그래밍 언어를 script 라고 한다.
php script, javascript, visual basic script
script
변수를 어떻게 선언할 것인가
조건문은 어떻게 줄 것인가
함수라는 걸 정의할 수 있는가
기본적으로 갖춰야되는 문법들이 있음
그 문법에 따라서 명령을 작성
유닉스 시스템 초창기에는 대학교수, 조교, 대학교 직원, 대학생들이 주로 썼었음
초창기에는 그렇게 친절하지 않았음
그 용도로 shell script 사용
1970년대 중반 이후
수퍼유저.. 준프로그래머...
프로그래밍을 전문적으로 하는 사람들이 등장
아예 프로그래밍을 짜놓고 그 프로그램 한 개만
이 당시부터 파이프라인 개념 등장
프로그램과 프로그램을 연결해서 작업을 완료
그래서 파이프라는 개념 등장

🔹 kenel
메모리 관리
파일시스템 관리 ← 파일이 어느 디렉토리에 어디에 있는지를 관리하는 거
프로세스 관리 ← 실행중인 프로그램
cpu 스케줄링 ← cpu를 어떻게 분배해서 프로그램에게 나눠줄 거냐

커널의 기능을 사용해서 사용자에게 원하는 걸 만들어 주는 거

cat, echo, wc, nano : utility

사용자가 유틸리티를 통해서 작업할 수 있도록 접근 제공 → shell

shell을 통해서 명령을 내리면

윈도우에서는 shell이 2개
powershell

유닉스에서는 shell이 많음
zsh
bash
bsh
csh
tsh
AppleScript

윈도우 자체가 마우스로 자꾸만 통제하다 보니까 키보드로 통제할 일이 없

개발자들은 명령으로 통제해야 됨

유닉스랑 비슷

powershell은 유닉스와 가까운 문법을 쓸 수 있다

echo $SHELL ← 현재 shell 알려줌

쉘 바꿀 수 있음

유닉스의 탄생 자체가 명령어들을 shell script를 사용해서 명령어를 쳐서 유닉스를 통제하고 사용

프로그램과 프로그램 사이에 연결이 필요했음
그래서 등장한 게 파이프라인

자바에서도 파이프라인 개념을 도와주기 위해서 나온 게 PipedReader / PipedWriter

바이트 단위로 데이터를 읽고 쓴다

문자 단위하고 바이트 단위하고 차이가 뭡니까

FileOutputStream / FileInputStream
바이트를 그대로 출력
바이트를 읽어들이는 메서드가 FileInputStream
new String 으로 문자열로 바꿔야 됨
문자열을 출력할 때는 FileReader / FileWriter가 편함
바이트 단위로 그대로 읽고 출력할 때
바이너리 데이터를 다룰 때 FileOutputStream / FileInputStream
텍스트 에디터로 편집 불가한 대표적인 pdf ppt
java는 메모장 됨
.class 파일은 메모장에서 켜면 안 됨. 전문 에디터가 아니면 안 됨

메모리
ByteArrayOutputStream / ByteArrayInputStream

다른 프로세스
PipedOutputStream / PipedInputStream

data processing Stream classes (데코레이터)
중간에서 데이터를 가공

BufferedWriter / BufferedReader
PrintWriter / LineNumberReader

BufferedOutputStream / BufferedInputStream /
DataOutputStream / DataInputStream
ObjectOutputStream / ObjectInputStream
PrintStream / PrintWriter

메모장에서 읽을 수 있는 거면 FileReader
jpg pdf 라면 FileInputStream

메모장에서 읽을 수 있는 텍스트를 출력하는 거라면 FileWriter
메모장에서 읽을 수 없는 데이터를 파일로 출력할 거라면 FileOutputStream

크게 텍스트를 다루는 클래스냐 바이트를 다루는 클래스냐

실제 데이터가 있는 곳에서 직접 읽고 쓰는 클래스냐 중간에 붙여서 쓰는 클래스냐

PrintStream 가능하면 데코레이터로 쓰기

PrintWriter는 붙여서도 쓸 수 있음
PrintWriter는 파일에 직접 출력할 수도 있음. 추천은 안 함

첨부파일 하려면 파일입출력 알아야 됨

com.eomcs.io.ex01.Exam0110.java

OS의 파일 시스템 다루기 - File 클래스

파일 시스템 : 파일과 디렉토리의 위치 정보를 관리하는 시스템
위치정보 : HDD, CD-ROM , USB 메모리 등 저장장치
파일과 디렉토리가 어디에 보관되었는지

HDD 구조
플래터의 옆모습
플래터가 한 장인 경우도 있지만 여러 장인 경우도 있다
트랙
암이 여러 개여도 같이 움진인다
한 바퀴 돌 때 데이터를 읽어들인다
데이터를 저장할 때 어디부터 저장
트랙을 구분하기 좋게끔 여러 개의 단위로 쪼갠다
한 섹터는 512 byte
섹터도 구분
각 섹터마다 번호가 붙는다
모든 섹터에 번호가 붙는다
a.txt / 20 byte / 19번 섹터
b.txt / 1 byte / 20번 섹터
관리의 편의성 때문에 각각 방마다 주소를 부여할 수 없음
관리가 너무 힘들어짐
최소 단위가 섹터
관리의 측면에서

크기 : 실제 파일 데이터 크기

디스크 할당 크기
실제 점유하고 있는 섹터의 크기

디스크 할당 크기 / 512 = 섹터 몇 개 나옴

물리적으로는 512인데 512 단위로 주소를 붙여야
집 방마다 주소를 붙이면 너무 많아짐
호마다 주소를 붙임
Windows는 8개를 한 단위로 묶는다
물리섹터(512 byte) * 8 = 논리섹터(4096 byte = 4KB) ← 포맷할 때 논리섹터 크기를 설정할 수 있다
나머지는 버리는 거
1000 바이트 미만 되는 파일을 저장한다면 하드디스크 메모리 낭비가 심하겠네요
4KB가 기본
바꿀 수 있음

주로 동영상을 저장한다고치면 보통 100MG 이상이니까 단위로 2048KB로 크게 한다
섹터 크기를 너무 작게 하면 섹터 주소가 길어짐

파일 크기가 섞여 있음
기본 크기 4KB로
범용
일반적인 용도로 쓸 때는 논리섹터를 4KB로
그게 바로 포맷

파일명 / 크기 / 점유섹터들
a.txt / 20 byte / 19번 섹터
b.txt / 1 byte / 20번 섹터 ← 4095 byte 버리는 거
c.class / 8193 byte / 21, 22, 23번 섹터 사용

점유
File이 어느 섹터에 할당 배정 저장되었는지 Allocation
File Allocation Table(FAT)
파일시스템 : 파일이 저장 장치에 보관된 위치 정보를 관리하는 방법
파일명 255자 = FAT32
이 아이디로 로그인 사용자는 이 파일을 볼 수 있다
접근 권한을 추가한 게
접근 권한 = NTFS (New Technology File System)
사용 권한을 설정할 수 있다

Windows OS
File Allocation Table(FAT)
파일명 255자 = FAT32
접근 권한 = NTFS (New Technology File System)

운영체제마다 다름

리눅스든 맥이든 윈도우든 상관없이 읽게 하려면 FAT32

맥 전용 파일 시스템으로 포맷해서 윈도우에서 인식 못 함
자기가 모르는 파일 시스템
자기가 모르는 방식으로 파일 위치를 다루는 거

NTFS 읽을 순 있는데 쓰진 못 함

쓸려면 다 공통으로 쓰는 파일 시스템으로 포맷해야 됨

파일시스템이 뭔지는 알아야 됨
몇 번 섹터를 점유하고 있다 이거를 관리하는 거

키워드
파일 시스템
FAT 파일 시스템
FAT32 파일 시스템
NTFS 파일 시스템
리눅스 파일 시스템
macOS 파일 시스템
HDD 수직 기록 방식 / 수평 기록 방식
트랙, 섹터, 실린더

위아래 섹터를 한번에 읽는다
한번에 같은 위치에 있는 걸 읽는다
같은 위치에 있는 섹터를 묶었을 때 실린더라고 한다

리눅스 : ext3, ext2

APFS(APple File System)

수평 기록 방식
옆으로 뉘이는 것보다 세우는 것이 더 조밀하게
같은 공간에 더 많은 데이터를 저장할 수 있음

지금은 다 수직 기록 방식

바깥쪽 섹터도 512, 안쪽 섹터도 512

분당 7200바퀴 돈다

노트북 분당 5400바퀴

서버 서버 10000바퀴 속도가 엄청나다!

속도가 일정 무조건 분당 바퀴

CD-ROM : 트랙이 계속 연결되어 있음 (HDD는 트랙이 끊겨 있음)
안쪽에 있는 거 읽을 수록 더 많이 돌아야 돼서 빨리 돌아야 됨
바깥쪽에 있는 거 읽을 때 길이 짧아서 천천히 돈다
속도를 조정해야됨
읽기 속도를 헤드 조정하는 게 더 어려움
CD를 돌리는 게 더 쉬움

File System API - File 클래스

🔹 HDD

🔹 OS
I/O API
File System API
  ↕
NTFS

🔹 JVM
java.io.*
java.nio.*

FileReader
FileWriter

File

자바에 있는 클래스는 하드에 액세스 할 수 없다
직접 액세스 불가능
운영체제에서 제공해주는 함수를 호출하면 결과를 리턴해준다

HDD에
자바에서 제공해주는 call 해서 파일이나 디렉토리를 다룬다

운영체제에서 제공해주는

이 방식의 장점
운영체제가 어떤 파일시스템으로 되어 있든
JVM에서 제공해주는 파일 클래스 호출
윈도우용 JVM
리눅스용 JVM
맥용 JVM
운영체제가 내부적으로 어떤 파일시스템을 쓰는지 상관없음
영향받지 않음. 그걸 다 JVM이
JVM은 운영체제마다 따로 있음.
운영체제에서 제공해주는 function을 call 한다
개발자들은 고민할 필요 없다

블로그 뒤지고 유튜브 뒤지는 거
기술서적은 같은 류의 서적을 많이 봐야 됨

com.eomcs.io.ex01

com.eomcs.io.ex01.Exam0110.java

java.io.File 클래스

🔹 File 클래스
디렉토리나 파일을 다룰 때 사용하는 클래스이다.
디렉토리나 파일을 생성, 삭제, 변경할 수 있다.

JVM을 실행하는 위치가 현재 폴더이다.

이클립스에서 실행하면 현재 폴더는 프로젝트 폴더

app이 현재 폴더

getCanonicalPath() : .이나 ..을 없애버린다.

getFreeSpace()
getUsableSpace() ← 실제 쓸 수 있는 공간
다른 용도로 확보된 공간이 있으면 못 씀

canExecute() ← 접근가능여부

존재여부: false

존재하지 않으니까 알아낼 수 없음

실행가능여부 ← 들어갈 수 있냐 없냐

존재하지 않는 폴더 조회
총크기: 0
남은크기: 0
가용크기: 0
존재여부: false

항상 존재여부 먼저 체크하기
존재한다면 여기 정보는 진짜 정보
존재하지 않는다면 의미 없는 정보임

바이너리로 저장
네트워킹 프로그래밍과 쓰레드 프로그래밍을 해봐야지 데이터베이스를 다룰 수 있음
그렇게 하다 보면 지루해서 못 함
파일입출력 끝나고 MyList에 적용하고 데이터베이스로 바꾸겠습니다

0개의 댓글