CODE - 하드웨어와 소프트웨어에 숨어 있는 언어 (찰스 페졸드)

 이 책은 컴퓨터가 어떻게 만들어졌는지(동작하는지)에 대해 아주 기초적인 부분에서 시작하여 상세하게 설명하고 있다.
누구나 이해할 수 있게 쉽게 쓰여 있고 각 챕터를 설명하기 위해 사용한 예제들도 모두 좋았다.

 같이 일했던 분의 추천으로 산 '찰스 페졸드의 WPF'라는 책을 통해 처음으로 알게 되었는데.. 알고 보니 "Programming Windows"라는 윈도우 프로그래밍에 대한 책을 쓴 유명한 분이셨다. 

 평소에 컴퓨터에 대한 기본적인 내용이 궁금하던 차에 우연히 "CODE" 라는 제목의 책을 보고 끌렸는데 알고 보니 찰스 페졸드가 쓴 책이어서 바로 구매하게 되었다. 

 내가 생각했던 것보다 더 책의 내용이 좋았고 컴퓨터가 어떻게 만들어졌는지에 대한 나의 갈증을 해결해 주었다.

아래는 이책의 목차이다. 차후 시간이 되면 각 목차에 대해 더 쓰고 싶다.

  1. 친한 친구와의 대화
  2. 부호와 조합
  3. 점자와 이진 부호
  4. 전등을 분해해 봅시다
  5. 다른 방법을 찾아봅시다
  6. 전신과 릴레이
  7. 우리가 사용하는 열 개의 숫자들
  8. 십진수 이외의 것
  9. 비트, 비트, 비트
  10. 논리와 스위치
  11. 빌 게이츠? 논리 게이트!
  12. 이진 덧셈기
  13. 그렇다면 뺄셈은 어떻게 할까요?
  14. 피드백과 플립플롭
  15. 바이트와 16진수
  16. 메모리를 만들어 봅시다
  17. 혼자서 움직이는 컴퓨터
  18. 주판에서 반도체까지
  19. 두 가지 고전적인 마이크로프로세서들
  20. 아스키코드와 문자의 변환
  21. 버스에 올라탑시다
  22. 운영체제
  23. 곳정소수점과 부동소수점
  24. 고수준 언어와 저수준 언어
  25. 그래픽 혁명

1. Object(객체) 란?
  객체(Object)는 상태(state)와 동작(behavior)이 있는 소프트웨어 번들이다. 실세계 객체도 위의 2개의 특성(상태, 동작)으로 나뉜다. 
예를 들면, 강아지(dogs)는 상태(이름, 색, 배고픔 등)와 동작(짓는 것, 꼬리 흔들기, 달리기 등)이 있다.
자전거(bicycles)는 상태(현재 기어, 현재 속도 등)와 동작(기어 변경, 브레이크 밟기 등) 이 있다.

소프트웨어 객체

소프트웨어 객체는 실세계의 객체와 비슷하다. 소프트웨어 객체는 현재의 상태를 필드(fields or variables)라고 하고 동작을 메서드(methods or functions)라고 한다. 메소드는 객체의 내부 상태(internal state)를 표현하고 다른 객체들과 통신을 위해 사용된다. 객체의 내부상태를 숨기고 다른 객체들과 통신할 수 있는 메서드를 공개하는 것을 데이터 캡슐화(data encapsulation)라고 한다.

소프트웨어 객체로서 자전거 모델

소프트웨어 객체는 아래와 같은 이점이 있다.
 1) 모듈성(modularity)
 2) 정보은닉(information hiding)
 3) 코드 재사용(code re-use)
 4) 플러그 기능과 디버깅 용이(pluggablility and debugging ease)


2. Class(클래스) 란?
 실세계는 많은 개별 객체들로 이루어져 있다. 자전거를 예로들면 수천 종의 자전거가 있다. 하지만 각 자전거들은 동일한 설계도(blueprints)로 만들어지기 때문에 같은 구성요소들을 가지고 있다. 객체지향 개념에서는 위의 자전거를 객체 클래스의 인스턴스(instance of class of objects)라고 한다.
class는 개별적인 객체들을 만들 수 있는 설계도이다.

아래는 자전거 클래스 예제이다.

//자전거 클래스
class Bicycle { 
    //멤버변수들
    int cadence = 0;   //cadence field
    int speed = 0;      //speed field
    int gear = 1;        //gear field
    
    //케이던스 메소드
    void changeCadence(int newValue) { 
         cadence = newValue; 
    } 
    //기어변경 메소드
    void changeGear(int newValue) { 
         gear = newValue; 
    } 
    //속도변경 메소드
    void speedUp(int increment) { 
         speed = speed + increment;    
    } 
    //브레이크 메소드
    void applyBrakes(int decrement) { 
         speed = speed - decrement; 
    } 
    //상태 출력 메소드
    void printStates() { 
         System.out.println("cadence:" + 
             cadence + " speed:" +  
             speed + " gear:" + gear); 
    } 
}



//자전거 클래스를 실행시킬 수 있는 데모클래스
class BicycleDemo { 
    //JVM이 main() 메소드를 찾아 실행시킨다.
    public static void main(String[] args) { 
        // Create two different  
        // Bicycle objects 
        Bicycle bike1 = new Bicycle(); 
        Bicycle bike2 = new Bicycle(); 

        // Invoke methods on  
        // those objects 
        bike1.changeCadence(50); 
        bike1.speedUp(10); 
        bike1.changeGear(2); 
        bike1.printStates(); 

        bike2.changeCadence(50); 
        bike2.speedUp(10); 
        bike2.changeGear(2); 
        bike2.changeCadence(40); 
        bike2.speedUp(10); 
        bike2.changeGear(3); 
        bike2.printStates(); 
    } 
}



<결과>
cadence:50 speed:10 gear:2 
cadence:40 speed:20 gear:3

3. Inheritance(상속) 란?
 공통 특성들을 부모 클래스(super class)로 모으고 부모 클래스의 특성들을 상속(inherit)받아 각 서브 클래스(sub class)를 구현하는 것을 상속이라고 한다.

자전거 객체 상속

아래는 상속 관련 예제이다. Java에서는 extends 키워드를 사용하여 상속을 구현한다.

class MountainBike extends Bicycle {

    // new fields and methods defining 
    // a mountain bike would go here

}

4. Interface(인터페이스) 란?
 객체들은 외부로 노출되는 메소드를 통해 다른 객체들과 상호작용을 한다. 이런 메서드들은 외부 세계와 객체의 인터페이스를 형성한다. 예를 들면 텔레비전의 전원 버튼은 TV와 사람과 연결해 주는 인터페이스이다.
가장 일반적인 인터페이스는 관련 메소드들만 정의하고 실제 어떻게 동작하는지는 비어있다. 각 객체에서는 비어있는 인터페이스를 구현하여 해당 인터페이스가 어떻게 동작하는지를 정의한다.

아래는 인터페이스 관련 예제이다. Java에서 인터페이스는 implements 키워드를 통해 구현한다.

//Bycycle 인터페이스 정의
interface Bicycle {

    //  wheel revolutions per minute
    void changeCadence(int newValue);

    void changeGear(int newValue);

    void speedUp(int increment);

    void applyBrakes(int decrement);
}


//Bicycle 인터페이스 구현
class ACMEBicycle implements Bicycle {

    int cadence = 0;
    int speed = 0;
    int gear = 1;

   // The compiler will now require that methods
   // changeCadence, changeGear, speedUp, and applyBrakes
   // all be implemented. Compilation will fail if those
   // methods are missing from this class.

    void changeCadence(int newValue) {
         cadence = newValue;
    }

    void changeGear(int newValue) {
         gear = newValue;
    }

    void speedUp(int increment) {
         speed = speed + increment;   
    }

    void applyBrakes(int decrement) {
         speed = speed - decrement;
    }

    void printStates() {
         System.out.println("cadence:" + cadence + " speed:" + speed + " gear:" + gear);
    }
}

5. Package(패키지) 란?
 패키지는 관련된 클래스와 인터페이스 집합들을 관리하는 네임스페이스(namespace)이다. 개념적으로는 폴더(디렉토리)와 유사하다. 유사한 기능을 하는 클래스와 인터페이스들을 패키지로 구성하여 유지하는 것이 차후에도 관리하기가 편하다.

 

 

참조: https://docs.oracle.com/javase/tutorial/java/concepts/index.html

 

1. Java Technology
 Java는 프로그래밍 언어이자 플랫폼입니다.

 1) Java 프로그래밍 언어
   Java는 아래 용어들로 특징지을 수 있는 고급언어입니다.
   - Simple
   - Architecture neutral
   - Object oriented
   - Portable
   - Distibuted
   - High performance
   - Multithreaded
   - Robust
   - Dynamic
   - Secure
  
 Java 소스코드는 .java 파일로 작성하며, javac로  소스코드를 컴파일하면 .class 파일이 생성됩니다. 해당 .class파일에는 컴파일한 프로세서에 대한 네이티브 코드가 포함되지 않고 JVM(Java Virtual Machine)이 해석할 수 있는 바이트코드가 포함됩니다. Java launcher는 JVM과 함께 만든 프로그램을 실행합니다.

Java 프로그램 개발 개요

 아래와 같이 컴파일러에 의해 만들어진 .class 파일은 여러 운영 체제에 설치되어 있는 JVM에서 대부분 동일하게 수행됩니다.

여러 운영체제에서 JVM을 통해 같은 프로그램이 실행됨


2) Java 플랫폼
 플랫폼(flatform)은 프로그램이 수행되는 하드웨어나 소프트웨어 환경입니다. Microsoft Windows, Linux, Solaris OS, Mac OS 가 대표적인 플랫폼입니다. 대부분의 플랫폼은 운영체제와 기본 하드웨어의 조합으로 설명할 수 있습니다.
Java 플랫폼은 다른 하드웨어 기반 플랫폼에서 실행되는 소프트웨어 플랫폼입니다.
 
Java 플랫폼은 JVM(Java Virtual Machine) 과 Java API(Application Programming Interface)를 포함하고 있습니다.
JVM은 Java 플랫폼의 기반으로 서로 다른 하드웨어에서 실행됩니다.
API는 프로그램에 바로 적용 가능한 유용한 기능들의 모음입니다. 해당 API는 class와 interface의 library로 묶여 있고 이것을 패키지(package)라고 합니다.

Java platform 개요

 Java 플랫폼은 네이티브 코드보다 느릴 수 있지만, 컴파일러와 JVM 기술의 발전으로 네이티브 코드에 가까운 성능을 제공합니다. 


2. Java로 할 수 있는 것
 1) Development Tools
   : 프로그램을 compiling, running, monitorning, debugging, documenting 할 수 있다.
 2) API
   : networking, security, XML generation, database access 등이 있다.
 3) Deployment
   : Java Web Start, Java Plug-in을 통해 배포할 수 있다.
 4) UI Toolkits
   : JavaFX, Swing, Java 2D로 GUI를 만들 수 있다.
 5) 통합 라이브러리
   : Java IDL API, JDBC API, JNDI API, Java RMI 등이 있다.


3. Java "Hello world"
 새로운 프로그래밍 언어를 배울때 관례적으로 접하는 "Hello World" 출력 프로그램을 Java로 작성해 보자.

/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}

 위처럼 HelloWorld라는 클래스를 정의하고 "public static void main(String [] args)"이라는 메서드를 작성한다. 프로그래밍 언어에선 "main()" 메서드는 조금 특별한데 모든 프로그램의 시작이 되는 부분이다.

JVM이 "main()" 메서드를 읽어들여 프로그램을 시작한다. public인 어디서든지 접근 가능하다는 뜻이고 static은 프로그램이 시작될 때부터 메모리에 올라간다는 뜻이다. 그리고 void는 JVM이 받는 리턴 값이 없다는 뜻이고 "String [] args"는 프로그램이 시작 시 입력받을 수 있는 인자가 저장되어 있는 곳이다.
"System.out.println()" 메서드는 Java에서 제공하는 기본 메서드로 콘솔창에 출력한다는 뜻이다.

간단한 프로그램이기 때문에 따로 개발환경이 설정되어 있지 않으면 아래의 온라인 컴파일에서 테스트할 수 있다.
https://www.tutorialspoint.com/compile_java_online.php

 

출처: https://docs.oracle.com/javase/tutorial/getStarted/intro/index.html

Java로 개발한 프로그램을 컴파일하여 바이트코드를 실행시키기 위한 가상 머신. JRE(Java Runtime Environment)에 포함되어 있으며, Java 컴파일러가 프로트엔드를 담당한다면 Java 가상 머신은 코드 최적화와 백엔드를 담당한다.
Java 소스코드는 javac 컴파일러를 거쳐 바이트코드로 변환되며, 이 바이트코드는 JRE에 들어있는 java classloader에 의해 JVM으로 적재되고 JVM은 적재된 바이트 코드를 JIT 컴파일 방식으로 실행한다.

JVM은 플랫폼 독립적으로, JVM이 실행 가능한 환경이라면 어디서든 Java 프로그램이 실행된 수 있도록 한다.

1. JVM 종류

종류 개발사
HotSpot Sun Microsystems
JRockit BEA System
Eclipse OpenJ9 IMB J9 기반
Kafee 클린 룸
IMB J9 IBM

 - 윈도우, 리눅스 등의 환경에서는 대부분 Hotspot이 사용되지만, IBM AIX에서는 IBM J9이 사용된다.


2. JVM 구조

<JVM 구조>


3. JVM 성능
 바이트코드는 실제 기계에서 직접 실행되는 것이 아니라 JVM의 해석 단계를 거쳐 실행되므로 Java로 개발된 프로그램은 같은 기능의 네이티브 언어보다 실행 속도가 느리다. 과거에는 바이트코드를 순수하게 인터프리트 하여 매우 느렸으나 현재는 JIT 컴파일의 도입과 하드웨어의 발전으로 성능이 개선되었다.

 JVM은 추상적인 머신이며, 메모리의 접근을 가상 머신 차원에서 관리하고 있으므로 런타임에 최적화가 가능하다. 특수한 상황에서는 네이티브 언어보다 우월한 성능을 보여주기도 하지만, JIT 컴파일 시간, 가비지 컬렉션을 위한 시간 등이 필요하므로 근본적인 한계가 있다.


4. 가비지 컬렉션(GC)
 JVM은 가비지 컬렉션을 수행하여 할당되었다가 더 이상 쓰이지 않는 메모리를 자동으로 회수한다. Full GC(전체 가비지 컬렉션)의 경우 프로그램 수행을 일시정지(Stop-the-world) 시켜놓고 할 수밖에 없는데, 이게 규치적이지 않고 이유 없이 뚝뚝 끊긴다는 악명을 떨치는데 공헌했다. 대규모 서비스의 운영시 Full GC는 성능에 상당히 심각한 영향을 주므로 프로그래머의 GC튜닝이 필수로 들어간다. 최신 버전(11~12 이후)의 JVM에는 힙의 크기와 상관없이 일시정지 시간이 10ms이하인 GC 알고리즘들(ZGC, Shenandoah)이 탑재되어 있다.

JVM 모니터링 클라이언트 VisualVM과 그 프러그인 Visual GC를 설치하면 가비지 컬렉팅 상황을 시각적으로 확인할 수 있다.

 

참조: 나무위키(https://namu.wiki/w/%EC%9E%90%EB%B0%94%20%EA%B0%80%EC%83%81%20%EB%A8%B8%EC%8B%A0?from=JVM)

Sun Microsystem에서 1995년에 개발한 객체지향 프로그래밍 언어. 창시자는 제임스 고슬링이다.
2010년에 Oracle이 Sun을 인수하면서 Java 저작권을 소유함.
현재는 OpenJDK는 GPL2이나 Oracle이 배포하는 Oracle JDK는 상업 라이선스로 2019년 1월에 유료화됨
Java EE는 Eclipse 재단의 소유이다. Java언어는 J2SE 1.4부터는 JCP(Java Community Process)에서 개발을 주도함.

 

1. JAVA  분류

분류 특징
Java SE
(Java Standard Edition / J2SE)
대부분의 사람들이 가장 많이 접하는 표준 에디션.
Java의 핵심 API와 기능들을 제고한다.
Jakarta EE, 구 Java EE
(Java Enterprise Edition / J2EE)
기업에서 운영하는 서버 페이지에 특화된 에디션.
JSP와 서블릿을 비롯한 웹 어플리케이션 서버 관련된 기술들이 포함되어 있음.
Java ME
(JAva Micro Edition / J2ME)
PDA나 셋톱박스, 센서 등의 임베디드 시스템에 특화된 에디션.
JavaFX 데스크톱 어플리케이션 개발 및 배포를 위한 에디션.
크로스플랫폼 이식과 GUI 라이브러리를 제공한다.

 

2. JAVA 특징
 - 소스코드를 기계어로 직접 컴파일하여 링크하는 C/C++의 컴파일러와 달리 자바 컴파일러는 바이트코드인 클래스 파일(. class)을 생성한다. 이 파일의 바이트코드를 읽은 뒤 기계어로 바꾸어 실행하는 것은 Java Virtual Machine(JVM)이다. 따라서 자바의 가장 큰 특징은 JVM이 설치된 곳이면 어디든지 실행되는 플랫폼 독 집적인 언어이다.

 

3. JAVA 장점
 1) 수많은 개발자와 레퍼런스
 2) 비교적 높은 생산성
 3) 기기 호환성
 3) 안정성
 4) 소스코드 가독성

 

4.  JAVA 단점
 1)  속도문제
   - JVM 로딩 속도 문제
   - 가상 머신 바이트코드 실행 속도 문제
   - 가비지 컬렉션에 의한 실행 지연 문제
 2) 불필요한 예외처리
 3) 소스코드 길이

 

참조: 나무위키(https://namu.wiki/w/Java)