1. 프로그래밍 구동
- 자바의 특징
- 객체 지향적이다.
- 객체들을 정의 해놓고 필요한 객체만 생성하여 사용한다.
- 유지보수가 쉽고 빠르다.
- 재사용성이 높다.
- 기본적으로 컴파일 언어이나 인터프리터 언어로 실행될 수 있다.
- 자바 컴파일러는 우리가 작성한 Java 코드를 자바 가상 머신(Java Virtual Machine, JVM)이 실행시킬 수 있는 자바 바이트 코드로 번역한다.
- 자바 바이트 코드는 자바 가상 머신(JVM)의 자바 인터프리터(Java Interpreter)를 이용해 한 줄씩 실행된다. 조금 더 자세하게 말하자면, 자바 바이트 코드로 작성되어 있는 실행 프로그램을 자바 인터프리터가 한 줄씩 읽으면서 컴퓨터가 이해할 수 있는 2진 코드로 번역한 후 실행시킨다
- 인터프리터 언어란? - 소스 코드를 컴파일 하지 않고, 런타임 환경에 문 단위로 코드를 한 줄씩 읽어서 바로 실행하는 방식으로 동작하는 언어
- 빌드 과정을 거치지 않기 때문에, 별도의 실행 파일이 존재하지 않다는 특징이 있다.
- 운영 체제에 독립적이다. (독립 플랫폼)
- 어떠한 운영 체제(OS - window, linux, macOS 등)에서도 실행된다.
- JVM에서 자체적으로 OS에 맞게 바이트코드를 컴파일 해주기 때문이다.
- 자동 메모리 관리
- 자바는 개발자가 직접 메모리에 관여할 수 없으며 자바가 직접 관리한다.
- 객체 생성시 자동적으로 메모리의 영역을 찾아서 할당, 또한 사용하지 않는 객체를 제거해준다.
- 멀티 쓰레딩 지원
- 하나의 프로그램 단위가 여러가지 쓰레드를 동시에 수행할 수 있다.
- 운영 체제마다 멀티 쓰레드를 이용하는 API가 다르나 자바의 경우는 자바 API를 사용하기 때문에 쉽게 구현이 가능하다.
- 객체 지향적이다.
- Java의 실행
- 자바는 동일한 소스 코드로 운영체제에 상관없이 실행되어야 한다.(write once, run anywhere)
- JDK (Java Development Kit)
- 자바로 개발하기 위한 SDK(Software Development Kit)
- SDK란 프로그래머를 위해서 제공되는 개발 도구이다.
- 소프트웨어 프레임워크, 운영체제, 응용 프로그램 등을 만들 수 있게 해준다.
- 대표적인 예로 안드로이드 스튜디오가 있다.
- javac - 자바 컴파일러. 자바 소스 코드를 바이트 코드로 변환되는데 사용된다. 소스 코드 파일(.java)을 컴파일하여 실행 가능한 클래스 파일(.class)를 생성한다.
- JRE - 자바 런타임 환경. 자바 프로그램을 실행하는데 필요한 라이브러리와 실행 환경을 포함합니다. JDK에는 JRE도 함께 제공되므로, JDK를 설치하면 자바 프로그램을 실행할수 있는 환경이 구축됩니다.
- jd(java deverger) - 자바 디버거. 디버깅을 위한 도구입니다. 변수 추적, 스택 추적, 조건부 중단 등의 디버깅 기능을 제공합니다.
- javadoc - 자바독, 자바 문서 생성 도구. 소스 코드에서 API 문서를 생성하는데 사용됩니다. 주석을 통해 문서화된 코드를 분석하여 HTML형식의 API를 제공합니다.
- 기타 - 자바 애플릿을 디버깅하기 위한 도구, 자바 소스 코드를 분석하고 변환하기 위한 도구 등
- 자바로 개발하기 위한 SDK(Software Development Kit)
- JRE (Java Runtime Environment)
- 자바 런타임 환경
- 런타임 환경 - 프로그램이 실행되는 동안 필요한 모든 컴퓨터 환경을 제공하는 소프트웨어 및 하드웨어.
- 자바 소프트웨어 작성 시 추가 수정 없이 어떤 운영 체제에서도 실행되도록 하는 모든 리소스를 제공하는 번역기 및 촉진제이다.
- JVM - 자바 가상머신. JRE의 핵심적인 구성 요소이다. 바이트 코드를 해당 플랫폼의 기계어로 변환하고 실행하는 역할을 한다.
- Java Class Library - 자바 클래스 라이브러리. 자바에서 사용할 수 있는 표준 클래스 라이브러리이다. 문자열 처리, 파일 입출력, 네트워킹, 데이터 구조, 그래픽 등 다양한 기능을 제공하는 클래스들이 포함되어 있다.
- 문자열 처리(String Handling)
- java.lang.String - 문자열을 나타낸다.
- java.lang.StringBuilder, java.lang.StringBuffer - 문자열을 동적으로 조작하고 변경한다.
- java.util.regex.Pattern, java.util.regex.Matcher - 정규 표현식을 사용하여 문자열을 검색 및 조작한다.
- 파일 입출력(File I/O)
- java.io.File - 파일 및 디렉토리 정보를 다룬다.
- java.io.FileInputStream, java.io.FileOutputStream - 파일에서 데이터를 읽거나 쓴다.
- java.io.FileReader, java.io.FileWriter - 파일에서 문자 데이터를 읽거나 쓴다.
- 네트워킹(Networking)
- java.net.URL - URL을 나타낸다.
- java.net.HttpURLConnection - Http프로토콜을 통해 서버와 통신한다.
- java.net.Socket, java.net.ServerSocket - 네트워크 소켓을 이용해 통신한다.
- 데이터 구조(Data Structure)
- java.util.ArrayList, java.util.LinkedList - 동적 배열 및 연결 리스트 데이터 구조
- java.util.HashMap, java.util.LinkedHashMap - 해시맵 및 링크드 해시맵 데이터 구조
- java.util.Stack, java.util.Queue - 스택 및 큐 데이터 구조
- 그래픽 (Graphics)
- java.awt.Graphics, java.awt.Graphics2D - 그래픽 렌더링을 위한 클래스
- java.swing.JFrame, javax.swing.JPanel - 그래픽 사용자 인터페이스(GUI)컴포넌트를 만들기 위한 클래스
- java.awt.image.BufferedImage - 이미지를 처리하고 그리기 위한 클래스
- 문자열 처리(String Handling)
- Java Tools - 자바 실행 관련 도구.
- 리소스 파일(.jar) 및 설정 파일(property)
- JVM (Java Virtual Machine)
- WOCA(write once, compile anywhere)
- C언어로 코드를 작성하면, 기계에 맞춰진 컴파일러가 각 기계에 맞는 기계어로 변환해 준다. 이렇게 변환 즉, 컴파일 된 코드를 Binary Code(바이너리 코드, 2진 코드, 기계어)라고 한다. 이 기계어는 특정 OS나 CPU구조에 맞춰진 컴파일러에 따라 다르게 컴파일 된다. 즉 다른 OS나 CPU구조를 가진 환경에선 이 기계어를 이해할 수 없다. 이를 '이식성이 낮다.' 라고 하며, C언어가 OS에 종속된 언어라고 말한다.
- WORA(write once, run anywhere)
- 자바로 코드를 작성하면 JVM을 거쳐서 운영체제(OS)와 상호작용을 하게 된다. 즉 운영체제와 상관없이 독립적으로 프로그램을 실행시킬 수 있다는 것이다. 컴파일된 코드와 하드웨어/OS 사이에서 해당 하드웨어/OS에 알맞은 byte code(바이트코드)로 변환시킨다.
- Java Compiler가 자바 코드(.java)를 바이트 코드(.class)로 변환(compile)시킨다.
- 이 바이트 코드를 기계어로 변환하기 위해 가상 CPU가 필요하며 이것이 JVM의 역할이다.
- JVM이 바이트코드를 바이너리코드로 변환한다.
- 이렇게 JVM에 의해 컴파일된 기계어는 바로 CPU에서 실행되어 사용자에게 서비스를 제공한다.
- JVM의 장점
- 이식성이 높다.
- 한번만 작성되면 JVM이 설치되어 있는 환경에서 전부 구동되기 때문에 효율성과 생산성이 높다.
- JVM의 단점
- 다른 언어보다 자바 가상 머신이라는 한 단계를 더 거쳐야 하기 때문에 결국 상대적으로 실행속도가 느리다.
- 이를 보완하기 위해 JIT컴파일러라는 내부 프로그램을 사용하여 필요한 부분만을 기계어로 바꾸도록 한다.
- just-in-time 컴파일
- 런타임 시 바이트 코드를 원시 시스템 코드로 컴파일하여 Java애플리케이션의 성능을 향상시키는 런타임 환경의 컴포넌트
- 그러나 이럼에도 C언어의 실행 속도를 따라잡지는 못한다.(게임이나 임베디드에서 C계열을 사용하는 이유이다.)
- 자바 프로그램의 실행 과정
- 소스코드(HelloWorld.java)를 작성한다.
- 컴파일러(Compiler)는 자바 소스코드를 이용하여 클래스 파일(HelloWorld.class)을 생성한다.컴파일 된 클래스 파일은 JVM이 인식할 수 있는 바이트 코드 파일이다.
- JVM은 클래스 파일의 바이트 코드를 해석하여 바이너리 코드로 변환하고 프로그램을 수행한다.
- HelloWorld 수행 결과가 컴퓨터에 반영된다.
- JVM의 내부 구조
- JVM의 핵심은 컴파일된 바이트코드가 어떻게 바이너리코드로 변환되어 구동되는 것인가? 이다.(빨간 부분)
- 자바 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당받는다.
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트 코드(.class)로 컴파일 한다.
- Class Loader는 동적 로딩을 통해 필요한 클래스들을 로딩 및 링크하여 Runtime Data Area(실질적인 메모리를 할당 받아 관리하는 영역)에 올린다.
- Runtime Data Area에 로딩 된 바이트 코드는 Execution Engine을 통해 해석된다.
- 이 과정에서 Execution Engine(실행엔진)에 의해 Garbage Collector의 작동과 Thread 동기화가 이루어 진다.
위 그림을 좀더 자세히 표현해보자. (JVM에 해당하는 빨간 네모)
- JVM의 구조
- 클래스 로더(Class Loader)
- JVM 내로 클래스 파일(.class)을 동적으로 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다.
- 로드된 바이트코드(.class)들을 엮어서 JVM의 메모리 영역인 Runtime Data Area에 배치한다.
- 한번에 메모리에 올리지 않고, 애플리케이션에서 필요한 경우 동적으로 메모리에 적재한다.
- Loading > Linking > initialization
- Loading - 클래스 파일을 가져와서 JVM메모리에 로드한다.
- Linking - 클래스 파일을 사용하기 위해 검증하는 과정이다.
- Verifying(검증) - 읽어들인 클래스가 JVM 명세에 명시된 대로 구성되어 있는지 검사한다.
- Preaparing(준비) - 클래스가 필요로 하는 메모리를 할당한다.
- Resolving(분석) - 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.
- Initialization(초기화) - 클래스 변수들을 적절한 값으로 초기화한다.(static 필드들을 설정된 값으로 초기화 등)
- 실행 엔진(Execution Engine)
- 클래스 로더를 통해 런타임 데이터 영역에 배치된 바이트 코드를 명령어 단위로 읽어서 실행한다.
- 자바 바이트 코드(.class)는 기계가 바로 수행할 수 있는 언어보다는 가상머신이 이해할 수 있는 중간 레벨로 컴파일 된 코드이다.
- 실행 엔진은 이와 같은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경해준다.
- 이 과정에서 실행 엔진은 인터프리터와 JIT컴파일러 두가지 방식을 혼합하여 바이트 코드를 실행한다.
- 인터프리터(Interpreter) - 바이트 코드 명령어를 하나씩 읽어서 해석하고 바로 실행한다.
- JVM안에서 바이트코드는 기본적으로 인터프리터 방식으로 동작한다.
- 같은 메서드라도 여러번 호출이 된다면 매번 해석하고 수행해야 되서 전체적인 속도는 느리다.
- JIT컴파일러(Just-in-time)
- Interpreter의 단점을 보완하기 위해 도입된 방식으로 반복되는 코드를 발견하여 바이트 코드 전체를 컴파일하여 Navtive Code로 변경하고 이후에는 해당 메서드를 더 이상 인터프리팅 하지 않고 캐싱해 두었다가 네이티브 코드로 직접 실행하는 방식이다.
- Native Code - Java에서 부모가 되는 C언어나, C++, 어셈블리어로 구성된 코드를 의마한다.
- 하나씩 인터프리팅 하여 실행하는것이 아닌, 컴파일 된 네이티브 코드를 실행하는 것이기 때문에 전체적인 실행 속도는 인터프리팅 방식보다 빠르다.
- 바이트 코드를 Native Code로 변환하는 데이도 비용이 소요되므로, JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고 인터프리터 방식을 사용하다 일정 기준이 넘어가면 JIT 컴파일 방식으로 명령어를 실행하는 식으로 진행된다.
- Interpreter의 단점을 보완하기 위해 도입된 방식으로 반복되는 코드를 발견하여 바이트 코드 전체를 컴파일하여 Navtive Code로 변경하고 이후에는 해당 메서드를 더 이상 인터프리팅 하지 않고 캐싱해 두었다가 네이티브 코드로 직접 실행하는 방식이다.
- 가비지 콜렉터(Garbage collector) - Heap 메모리 영역에서 더 사용하지 않는 메모리를 자동으로 회수한다.
- C언어 같은 경우 직접 개발자가 메모리를 해제해줘야 되지만, Java는 이 가비지 컬렉터를 이용해 자동으로 메모리를 실시간 최적화 시켜준다. 따라서 개발자가 따로 메모리를 관리하지 않아도되므로, 더욱 손쉽게 프로그래밍을 할 수 있도록 해준다.
- 일반적으로 자동 실행되지만, GC(가비지 컬렉터)가 실행되는 시간은 정해져 있지 않다.
- 특히 Full GC가 발생하는 경우, GC를 제외한 모든 스레드가 중지되기 때문에 장애가 발생할 수 있다.
- 런타임 데이터 영역(Runtime Data Area)
- JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재한다.
- 메서드 영역(Method Area) - Class Area, Static Area라고도 불린다.
- JVM이 시작될때 생성되며 바이트 코드(.class)를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간이다.
- JVM에서 읽어들인 클래스와 인터페이스에 대한 런타임 상수 풀, 메서드와 필드, static 변수, 메서드 바이트 코드 등을 보관
- 런타임 상수 풀(Runtime Constant Pool) - Method Area영역에 포함되면서도 독자적 중요성을 띈다.
- 각 클래스/인터페이스 파일마다 별도의 constant pool 테이블이 존재하는데, 클래스 생성할때 참조해야할 정보들을 상수로 가지고 있는 영역이다.
- 클래스와 인터페이스 상수, 메서드와 필드에 대한 모든 레퍼런스들이 저장되어있다.
- JVM은 런타임 상수 풀을 통해 해당 메서드나 필드의 실제 메모리 상 주소를 찾아 참조
- 상수 자료형을 저장하여 참조하고, 중복을 막는 역할
- JVM 시작시 생성되며 프로그램 종료시 까지 사용된다.
- 모든 쓰레드에서 공유된다.
- 모든 쓰레드가 공유하는 영역이라 다음과 같은 초기화 코드 정보들이 저장된다.
- Field info : 멤버 변수의 이름, 데이터 타입, 접근 제어자의 정보
- Method info : 메서드 이름, return 타입, 함수 매개변수, 접근 제어자의 정보
- Type info : Class 인지 Interface 인지 여부 저장, Type의 속성과 이름, Super Class의 이름
- 힙 영역 (Heap Area)
- 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 메모리 영역
- New 연산자를 통해 생성한 객체, 또는 인스턴스 변수와 배열 타입 등을 저장
- 메서드 영역에 저장된 클래스만이 생성되어 적재된다.(당연)
- 힙 영역에 생성된 객체와 배열은 Reference Type으로서, JVM 스택영역의 변수나 다른 객체의 필드에서 참조된다.
- 즉, 힙의 참조 주소는 '스택'이 갖고 있고 해당 객체를 통해서만 힙 영역의 인스턴스를 핸들링 가능하다.
- 객체가 더이상 사용되지 않거나, 명시적으로 null 선언시 GC(Garbage Collector) 대상이 되어 힙영역에서 제거된다.
- 모든 쓰레드에서 공유된다.
- 스택 영역 (Stack Area)
- int, long, boolean 등 기본 자료형을 생성할 때 저장하는 공간
- 임시적으로 사용되는 변수나 정보들이 저장되는 영역
- 선입후출(FILO - First in, Last out) 구조, push와 pop기능 사용방식으로 동작한다.(push - 삽입, pop - 추출)
- 메서드 호출 시 생성되는 쓰레드 수행정보를 기록하는 Frame 저장
- stack frame
- 메서드가 호출될 때마다 프레임이 만들어지며, 현재 실행중인 메서드 상태 정보를 저장하는 곳
- 메서드 호출범위가 종료되면 스택에서 제거된다.
- 스택 프레임에 쌓이는 데이터는 메서드의 매개변수, 지역변수, 리턴값, 연산시 결과값 등이 있다.
- 메서드 정보, 지역변수, 매개변수, 연산 등 발생하는 임시 데이터를 저장
- 기본(원시)타입 변수는 스택 영역에 직접 값을 가진다.
- 참조타입 변수는 힙 영역이나 메서드 영역의 객체 주소를 가진다.
- 예) Person p = new Person(); 과 같이 객체를 생성할 경우, new에 의해 생성된 클래스는 Heap Area에 저장되며, Stack Area에는 생성된 클래스의 참조인 p의 주소만 저장된다.
- { } 나 메서드가 끝날 때 종료된다.
- 각 쓰레드별로 하나씩 존재하며, 쓰레드가 시작될 때 할당된다.
- 프로세스가 메모리에 로드될 때 스택 사이즈가 고정되어 있어, 런타임 시에 스택 사이즈를 변경할 수 없다.
- 고정된 크기의 JVM 스택에서 프로그램 실행중 메모리 크기가 충분하지 않다면 StackOverFlowError가 발생한다.(일반적으로 무한 재귀 현상때문에 발생한다.)
- PC Resister
- 쓰레드가 시작될 때 생성되며, 현재 실행중인 JVM 명령어 주소를 저장하는 공간
- JVM 명령의 주소는 쓰레드가 어떤 부분을 무슨 명령으로 실행해야 할지에 대한 기록을 가지고 있다.
- 프로그램의 실행은 CPU 명령어 즉, Instruction을 수행하는 과정이다. 이때 CPU는 연산을 수행하는 동안 필요한 정보를 레지스터라고 하는 CPU내의 기억장치를 이용한다.
- 자바는 CPU에 직접 연산을 수행하도록 하는것이 아닌, 현재 작업하는 내용을 CPU에게 연산으로 제공해야 하며, 이릅 위한 버퍼 공간으로 'PC Register'라는 메모리 영역을 만든다.
- JVM은 스택에서 비연산값을 뽑아 별도의 메모리 공간인 PC Register에 저장한다.
- 연산 및 결과값을 메모리에 전달하기 전 CPU내 기억장치이다.
- 각 쓰레드별로 생성된다. 만약에 스레드가 자바 메서드를 수행하고 있으면 JVM의 명령 주소를 PC Register에 주정하지만, 다른 언어(C언어, 어셈블리)의 메서드를 수행중이라면 Native Method Stack Area에서 처리한다.
- 네이티브 메서드 (Native Method Stack)
- 자바 외 언어(기계어, C, C++, 어셈블리)로 작성된 네이티브 코드를 위한 메모리
- C/C++ 등의 코드를 수행하기 위한 스택
- native 메서드의 매개변수, 지역변수 등을 바이트코드로 저장한다
- JIT 컴파일러에 의해 변환된 Native Code역시 여기에서 실행된다.
- 일반적으로 메서드를 실행하는 경우 JVM 스택메모리에 쌓이다가 해당 메서드 내부에 네이티브 방식을 사용하는 메서드가 있다면 해당 메서드는 네이티브 스택에 쌓인다.
- 네이티브 메서드 수행이 끝나면 다시 자바 스택으로 돌아와 작업을 수행한다.
- native interface 호출및 종료시 생성된다. 인터페이스가 사용되면 네이티브 메서드 스택에 바이트 코드로 전환되어 저장된다.
- 각 쓰레드별로 생성된다.
- JNI - 네이티브 메서드 인터페이스 (Native Method Interface)
- 자바가 다른 언어로 만들어진 애플리케이션과 상호 작용할 수 있는 인터페이스 제공 프로그램.
- JNI는 JVM이 Native Method를 적재하고 수행할 수 있도록 한다.(실질적으로는 C / C++)
- 네이티브 메서드 라이브러리 (Nateve Method Library)
- C, C++로 작성된 라이브러리를 칭한다.
- 만일 헤더가 필요하면 JNI는 이 라이브러리를 로딩해 실행한다.
- 클래스 로더(Class Loader)
- 인터페이스와 추상클래스
- 추상 클래스
- 하위클래스들의 공통점을 모아 추상화하여 만든 클래스이다. 추상화를 하며 중복되는 클래스 멤버들을 통합 및 확장하며, 클래스간의 연관관계를 구축하는것에 초점을 둔다.
- 하위클래스로 기능 확장
- 인터페이스
- 상속관계에 얽메이지 않고, 공통 기능이 필요할 때마다 추상 메서드를 정의하고 구현하는 식으로 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용한다.(xxxxable 로 네이밍한다.)
- 클래스의 목적에 맞게 메서드의 기능을 구현
- 사용 키워드
- 추상 클래스 - abstract / 인터페이스 - interface
- 사용 가능 변수
- 추상 클래스 - 제한 없음 / 인터페이스 - static final (상수)
- 접근 제어자
- 추상 클래스 - 제한 없음(private, protected, default, public) / 인터페이스 - public
- 상속 키워드
- 추상 클래스 - extends / 인터페이스 - implements
- 다중 상속 가능 여부
- 추상 클래스 - 불가능 / 인터페이스 - 가능(클래스에 다중 구현, 인터페이스 끼리 다중 상속 가능)
- 공통점
- 추상 메서드를 가지고 있어야 한다.
- 인스턴스화 할 수 없다.(new 생성자를 통해 객체를 생성할 수 없다.)
- 인터페이스 혹은 추상 클래스를 상속받아 구현한 구현체의 인스턴스를 사용하여야 한다.
- 인터페이스와 추상클래스를 구현, 상속한 클래스는 추상 메서드를 반드시 구현하여야 한다.
- 마커 인터페이스
- 일반적인 인터페이스와 동일하나 사실상 아무 메서드도 선언하지 않은 빈 껍데기 인터페이스
- 오로지 객체의 타입과 관련된 정보만을 제공
- 추상 클래스
- 프로세스와 쓰레드
- Process - 운영체제로부터 자원을 할당받은 작업의 단위
- Thread - 프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위
- 정적 프로그램(static program)
- 프로그램 - Window (.exe), Mac (.dmg)파일과 같은 컴퓨터에서 실행할 수 있는 파일
- 파일을 실행하지 않은 상태이기 때문에 정적 프로그램이라고 부른다(줄여서 프로그램이라 한다.)
- '코드 덩어리'
- 프로세스 - 프로그램이 돌아가고 있는 상태
- 프로그램은 운영체제가 메모리 공간을 시스템 자원(CPU) 할당해 주어야 실행되며, 실행되는 순간 컴퓨터 메모리에 올라간다.
- '메모리에 적재되고 CPU자원을 할당받아 실행된 프로그램'
- 쓰레드
- '과거' 프로그램 실행 시 프로세스 하나만을 사용하였다.(파일을 다운받으면 완료까지 기다려야 한다.) 그렇다고 동일한 프로그램을 여러개의 프로세스로 만들면, 그만큼 메모리를 차지하고 CPU에서 할당받는 자원이 중복된다.
- 하나의 프로세스 내에서 동시에 진행되는 작업 갈래, 흐름의 단위
- 예) 브라우저에서 파일을 다운받으며 동시에 쇼핑, 게임 등이 가능하다.
- 이러한 흐름을 '쓰레드'라고 하고, 여러 쓰레드가 존재하는 것을 멀티(다중)쓰레드라고 부른다.
- 프로세스를 생성하면 기본적으로 하나의 main쓰레드가 생성되며, 개발자가 직접 쓰레드를 늘려주어야 한다.
- 프로세스(Process)의 구조
- 코드 영역(Code / Text)
- 프로그래머가 작성한 프로그램 함수들의 코드가 CPU가 해석 가능한 기계어 형태로 저장되어 있다.
- 데이터 영역(Data)
- 코드가 실행되면서 사용하는 전역변수나 각종 데이터들이 모여있다.
- .data / .rodata / .bss영역으로 세분화되어 있다.
- .data : 전역 변수 또는 static변수 등 프로그램이 사용하는 데이터를 저장
- .rodata : const같은 상수 키워드 선언 된 변수나 문자열 상수가 저장
- .BSS : 초기값 없는 변수, static 변수가 저장
- 스택 영역(Stack)
- 지역 변수와 같은 호출한 함수가 종료되면 되돌아올 임시적인 자료를 저장하는 독립적인 공간이다.
- 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.
- stack영역의 크기를 초과하면 stack overflow에러가 발생한다.
- 힙 영역(Heap)
- 생성자, 인스턴스와 같은 동적으로 할당되는 데이터들을 위해 존재하는 공간이다.
- 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다.
- 코드, 데이터 영역은 크기가 정적이다.
- 스택, 힙 영역은 크기가 동적이다.
- 코드 영역(Code / Text)
- 정규식
- 문자열 데이터 중에서 원하는 조건(패턴)과 일치하는 문자열 부분을 찾아내기 위해 사용하는 것
- java.util.regex
- 람다 표현식(Lambda Expression)
- 함수형 프로그래밍을 구성하기 위한 함수식. 자바의 메서드를 간결한 함수 식으로 표현
- 메서드 표현식을 메서드 타입, 메서드 이름, 매개변수 타입, 중괄호, return 문을 생략하고 화살표 기호를 넣음으로서 코드를 함축한다.
- 이러한 특징으로 람다식을 이름이 없는 함수 '익명함수'라고도 한다.
- int add(int x, int y) / return x+y;
- (int x, int y) -> return x+y;
- (x, y) -> return x + y;
- (x, y) -> x + y;
- 컴파일러 스스로 람다 함수식을 보고 추론하여 타입을 유추한다.
- 람다표현식은 긴 자바 코드를 말끔이 줄이는데 일조하지만, 단점이나 사용하기에 적절치 못한 경우가 존재한다.
- 문서화를 할 수 없다.
- 이름이 없는 함수이기에 메서드나 클래스와 다르게 문서화를 할 수 없다.
- 코드 자체로 동작이 명확하게 설명되지 않거나 람다가 길거나 읽기 어렵다면 쓰지 않는 방향으로 리팩토링하는 것을 고려한다.
- 디버깅이 까다롭다.
- 익명 구현 객체 기반이여서 디버깅시 콜 스택(call stack)추적이 매우 어렵다.
- stream에서 람다를 사용시 for문보다 성능이 떨어진다.
- 남용시 코드가 지저분해진다.
- 재귀로 만들기 부적합하다.
- 문서화를 할 수 없다.
- 제네릭 (Generics)
- 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법
- ArrayList<String> list = new ArrayList(); 에서 '< >' 가 제네릭이다. 괄호 안에는 타입명을 기재한다.
- 변수를 선언시 변수의 타입을 지정하듯, 제네릭은 객체(Object)에 타입을 지정해준다.
- 사용이유와 이점
- 컴파일 타임에 타입 검사를 통해 예외를 방지한다.
- 불필요한 캐스팅을 없애서 성능을 향상한다.
- 주의사항
- 제네릭 타입의 객체는 생성이 불가하다.
- static 멤버에 제네릭 타입이 올 수 없다.
- Collection Framework
- 자료 구조(Data Structure) 종류의 형태들을 자바 클래스로 구현한 모음집
- 원시자료형(int, double 등)은 적재할 수 없다. wrapper타입으로 변환하여 Integer객체나 Double객체로 박싱하여 저장하여야 한다.
- Collection 인터페이스
- Iterable 인터페이스를 상속받는다.
- List
- ArrayList, LinkedList, Vector, Stack
- 저장 순서가 유지되는 컬렉션을 구현하는데 사용
- 같은 요소의 중복 저장을 허용
- 배열과 마찬가지로 index로 요소에 접근, 배여로가 다르게 자료형 크기가 고정이 아니여서 데이터 양에 따라 동적으로 크기가 늘어났다 줄어들 수 있다.(가변성)
- 요소 사이에 빈 공간을 허용하지 않는다. 데이터 삽입 / 삭제시 배열 이동이 일어난다.
- ArrayList, LinkedList의 차이
- 내부구조
- ArrayList : 내부적으로 배열(Array)를 사용하여 요소를 저장한다. 따라서 각 요소에 대한 인덱스를 통해 빠르게 접근 가능하다.
- LinkedList : 내부적으로 노드(Node)들의 연결 리스트를 사용하여 요소를 저장한다. 각 노드는 데이터 요소와 다음 노드를 가르키는 참조(포인터)를 가지고 있다.
- 접근 속도
- ArrayList : 인덱스를 통한 요소 접근이 매우 빠르다. 인덱스를 알고있는 경우 O(1) 시간에 접근할 수 있다.
- LinkedList : 인덱스를 통한 접근이 느리다. 특정 위치의 요소에 접근하려면 첫 번째 요소부터 차례대로 이동해야 하므로 최악의 경우O(n)의 시간이 소요될 수 있다.
- 삽입/삭제 속도
- ArrayList : 배열의 크기를 조정할 필요가 없는 경우에 삽입, 삭제가 빠르다. 하지만 배열의 크기를 조정해야 할 경우에는 비용이 발생한다.
- LinkedList : 특정 위치에 노드를 삽입하거나 삭제하는 작업이 빠르다. 특히 헤드 또는 테일에 대한 삽입/삭제는 O(1)시간에 수행된다.
- 메모리 사용
- ArrayList : 배열의 크기가 고정되어 있으므로 메모리를 미리 할당한다. 따라서 크기가 커질수록 불필요한 메모리를 소비할 수 있다.
- LinkedList : 요소의 삽입과 삭제가 빈번한 경우 메모리를 더 효율적으로 사용할 수 있다. 하지만 각 노드마다 추가적인 포인터를 유지해야하므로 메모리 사용량이 더 크게 될 수도 있다.
- ArrayList는 요소에 빠르게 접근할 수 있고 LinkedList는 삽입, 삭제가 빠르며 메모리사용을 보다 효율적으로 관리할 수 있다.
- 채팅어플리케이션에서 채팅들이 계속 추가되는 삽입 작업은 LinkedList가 유리하다. 이전 메시지를 검색하거나 특정 메시지를 수정하는 작업은 접근이 빠른 ArrayList가 유리하다.
- 내부구조
- Queue
- PriorityQueue, ArrayDeque
- 선입 선출(FIFO)구조이다.
- 자바에서 Queue는 인터페이스이며, 큐 컬렉션을 사용 가능하다.
- Set
- HashSet, LinkedHashSet, TreeSet, EnumSet
- 데이터의 중복을 허용하지 않고 순서를 유지하지 않는 데이터의 집합 리스트이다.
- Multiset은 중복을 허용하긴한다.
- 각 요소의 개수를 세는 등의 연산또한 제공한다.
- 순서 자체가 없으므로 인덱스를 검색할 수 없다.
- 중복 저장이 불가능하므로 null값도 하나만 저장할 수 있다.
- Map 인터페이스
- HashMap, LinkedHashMap, Hashtable, TreeMap
- 키(Key), 값(Value)의 쌍으로 연관지어 이루어진 데이터의 집합
- 값(value)은 중복되어 저장할 수 있지만, 키(Key)는 고유해야 한다.
- 기존의 데이터와 중복된 키와 값을 저장하면 기존의 값은 없어지고 마지막에 저장된 값이 남게된다.
- 저장 순서가 유지되지 않는다.
- 스택, 큐
- 스택(Stack)
- LIFO (Last In First Out), 선입 후출식 데이터 구조이다.
- Iterable - Collection - List - Vector - Stack으로 상속된다.
- 수식계산, 수식 괄호 검사, undo/redo, 웹 브라우저의 뒤로/앞으로 등에서 구현된다.
- JVM에서 Runtime Data Area 에 Stack 메모리로서 사용된다.
- 큐(Queue)
- FIFO (First In First Out), 선입 선출식 데이터 구조이다.
- 한 쪽에선 삭제연산만, 다른 한 쪽에선 삽입 연산만 수행한다.
- 작업 대기열, 이벤트 처리, 네트워크 통신, 버퍼 등에서 구현된다.
- 스택(Stack)
- 동기, 비동기(sync, async)
- 데이터를 주고 받는 방식의 종류이다. 주로 웹 개발에서 나오는 개념이다.
- 동기는 요청과 응답이 동시에 일어난다. 비동기는 요청과 응답이 동시에 일어나지 않는다.
- 동기(Sync)
- 웹 페이지를 새로고침하며 데이터를 불러온다.
- 대표적으로 Form제출 형식이 있다.
- 장점
- 비동기 통신보다 코드를 작성하고 이해하는 것이 쉽다.
- 요청과 응답이 순차적으로 이루어져 코드의 간결성과 직관성을 유지할 수 있다.
- 요청을 보내고 응답을 받은 후에야 다음 작업이 수행되기 때문에 순서가 보장된다.
- 요청과 응답이 연결되어있어 에러 해결이 수월하다.
- 단점
- 응답을 받으면 전체 페이지를 로딩해야하기에 서버와의 통신량이 많아지며, 웹 페이지의 속도 및 성능이 저하된다.
- 요청을 보낸 후에 다른 작업을 수행할 수 없다. (메일을 보내면서 다른 메일을 읽거나 쓸 수 없다.)
- 비동기(Async)
- 웹페이지를 새로고침 하지 않고도 데이터를 불러올 수 있다.
- 대표적으로 Ajax 통신이 있다.(Asynchronous JavaScript And XML)
- 장점
- 전체 페이지를 다시 로딩하지 않고 필요한 부분만 업데이트 하기에 웹페이지의 속도와 성능이 향상된다.
- 서버와의 통신량이 줄어들고 자원과 시간이 절약된다.
- 화면이 부드러워 사용자 경험이 개선된다.
- 요청을 보낸후 응답이 오기 전, 다른 작업 수행이 가능하다.
- 단점
- 동기통신 보다 코드를 작성하고 이해하기 어렵고 복잡하다.
- 요청의 처리속도에 따라 응답이 뒤죽박죽된다.(순서를 보장할 수 없다.)
- 요청과 응답이 분리되어 있어 에러가 발생시 어떤 요청에서 에러가 발생했는지 파악하기 쉽지 않다.
- Ajax - Asynchronous JavaScript And XML
- 자바스크립트를 이용해 웹 서버와 비동기로 통신하며, HTML, XML, JSON등의 다양한 형식의 데이터를 주고받을 수 있다.
- Ajax를 사용하면 웹 페이지가 로딩된 후에도 서버로부터 필요한 데이터만 요청하여 페이지를 동적으로 갱신할 수 있다.
- 동작 원리
- 웹 브라우저에서 사용자의 요청이 발생하면, 자바스크립트로 XMLHttpRequest객체를 생성한다.
- XMLHttpRequest 객체는 서버에 비동기적으로 요청을 보낸다.
- 서버는 요청을 처리하고 응답을 XML이나 JSON형식으로 보낸다.
- XMLHttpRequest 객체는 응답을 받아서 자바스크립트로 처리한다.
- 장점
- 웹 페이지의 속도와 사용성을 향상한다.
- 서버의 리소스를 효율적으로 활용할 수 있다.
- 다양한 데이터 형식을 지원한다.(XML, JSON)
- 단점
- 보안 문제가 있을 수 있다.(카카오페이는 Ajax통신이 불가능하다.)
- 크로스 도메인 문제가 있을 수 있다. (CORS)
- 브라우저 호환성 문제가 있을 수 있다. (IE 브라우저)
- 디자인 패턴
- 객체 지향 프로그래밍 설계를 할 때 자주 발생하는 문제들을 피하기 위해 사용되는 패턴, '모범사례'
- 디자인 패턴은 의사소통 수단의 일종 으로서 다른 사람이 작성한 코드, 기존의 존재하는 코드를 이해하는데 도움이 된다.
- 디자인 패턴은 객체지향 4대 특성(캡슐화, 상속, 추상화, 다형성)과 설계원칙 (SOLID)을 기반으로 구현되어 있다.
- 재사용성 - 반복적인 문제에 대한 일반적인 해결책을 제공하여 유사한 상황에서 코드를 더 쉽게 작성할 수 있다.
- 가독성 - 일정한 구조로 정리하고 명확하게 작성하여 개발자가 코드를 이해하고 유지보수하기 쉽게 만든다.
- 유지보수성 - 코드를 쉽게 모듈화 할 수 있으며, 변경이 필요한 경우 해당 모듈만 수정하여 유지보수가 쉬워진다.
- 확장성 - 새로운 기능을 추가하거나 변경시 디자인 패턴을 활용하여 기존 코드의 변경없이 새 기능을 통합할 수 있다.
- 안정성과 신뢰성 - 수많은 사례로 검증된 솔루션을 제공한다.
- 분류
- 생성 패턴 (Creational Pattern)
- 구조 패턴 (Structural Pattern)
- 행위 패턴 (Behavioral Pattern)
- 로그
- 소프트웨어나 시스템에서 발생하는 이벤트나 정보를 기록하는 기능 또는 기록된 정보 자체를 가르킨다.
- 디버깅, 오류분석, 성능 모니터링, 보안 검사 등 다양한 목적으로 사용된다.
- 텍스트파일 혹은 데이터베이스에 기록한다.
- Logback, Log4j, SLF4J
- SOLID
- 객체 지향 프로그래밍에서 소프트웨어 디자인의 다섯가지 기본원칙을 나타낸다.
- Single Responsibility Principle (단일 책임 원칙)
- 클래스는 단 하나의 책임을 가져야 한다.
- 하나의 클래스는 하나의 기능을 담당하여 하나의 책임을 수행하는데 집중되야 한다.(클래스를 따로따로 여러개 설계하라)
- 하나의 클래스에 기능이 여러개 있다면 수정시 곤란해진다.
- 프로그램의 유지보수성이 높아진다.
- Open / Closed Principle (개방-폐쇄 원칙)
- 소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하지만, 변경에는 닫혀 있어야 한다.
- 기존의 코드를 수정하지 않고 새로운 기능을 추가할 수 있어야 한다.
- 이를 위해 인터페이스와 추상화를 적극 활용하여 구현을 분리하고, 다형성을 통해 확장성을 제공한다.
- Liskov Substitution Principle (리스코프 치환 원칙)
- 상위 타입의 객체를 하위 타입의 객체로 대체 가능하여야 한다.
- 서브 타입은 언제나 슈퍼타입으로 취급될 수 있어야 한다.
- 상속 관계에서 하위 클래스가 상위 클래스의 기능을 모두 수행할 수 있어야 함을 의미한다.
- 다형성의 특징을 이용하기 위해 상위 클래스로부터 조심스럽게 오버라이딩을 해야한다.
- Interface Segregation Principle (인터페이스 분리 원칙)
- 인터페이스를 각각 사용에 맞게 끔 잘게 분리하여야 한다.
- 인터페이스의 단일 책임을 강조한다.
- 인터페이스를 분리하여 구성해놓고 나중에 무언가 수정사항이 생겨서 또 인터페이스를 분리하는 행위를 지양한다.
- Dependency Inversion Principle (의존 역전 원칙)
- 어떤 클래스를 참조하여야 할때 그 대상의 상위 요소 (추상클래스 or 인터페이스로) 참조하라는 원칙
- 구현 클래스가 아닌 인터페이스에 의존하라
- DB 인덱스
- 데이터 저장(Insert, Update, Delete)의 성능을 희생하고 그 대신 데이터의 읽는 속도를 높여 테이블의 동작(조회)속도를 높여주는 자료 구조이다.
- 색인
- 인덱스를 사용하면 select의 성능이 몇분에서 0.초 단위로 줄어들 수 있다.
- 인덱스를 사용하는 SQL을 만들어 효율적으로 사용하면 매우 빠른 응답속도를 얻을 수 있고 쿼리의 부하가 줄어들어 시스템 전체적인 성능이 향상되는 효과가 있다.
- 인덱스 역시 하나의 데이터 덩어리 이기 때문에, 데이터베이스 전체 크기의 10%나 되는 공간을 할당해주어야 한다.
- 데이터 변경이 자주 일어나면 전체적인 성능이 감소한다.
- 인덱스 알고리즘
- B-Tree
- 이진 트리
- 가장 보편적인 알고리즘이다.
- 삽입, 삭제, 검색, 범위 쿼리등의 작업을 효율적으로 처리 가능하다.
- 균형 이진트리 로서 모든 리프노드가 같은 레벨에 있고, 각 노드는 여러 키를 가질 수 있다.
- 해시 인덱스(Hash Index)
- 해시 함수를 사용하여 키와 연관된 위치에 데이터를 저장하는 방식이다.
- 해시 인덱스는 일반적으로 동등 조인(Equijoin) 또는 동등검색(Equi-search)을 위한 인덱싱에 사용된다.
- 동일한 키에 대한 데이터 검색이 매우 빠르지만, 범위 쿼리나 정렬된 검색에는 적합하지 않을 수 있다.
- GIST (Generic Index Search Tree)
- 다양한 데이터 형식에 대한 다양한 쿼리를 지원할 수 있는 유연성을 제공한다.
- 공간 데이터베이스나 전문 검색 엔진에서 다양한 유형의 데이터를 인덱싱 하는데 유리하다.
- B-Tree
- innerjoin, outerjoin
- PK, FK, UK
- 데이터 무결성 제약조건 - 데이터의 정확성 또는 유효성을 의미
- 일관된 데이터베이스 상태를 정의하는 규칙들을 묵시적으로 또는 명시적으로 정의한다.
- PK(Primary Key)
- 기본키라고 하며 엔티티를 식별하는 대표 키 (테이블당 하나만 존재)
- Null일 수 없다.
- Unique index가 자동으로 만들어진다.
- FK(Foreign Key)
- 다른 테이블의 PK를 참조하는 Key
- 동일한 Domain을 갖는다.
- 참조하고자 하는 Column은 PK 또는 UK이여야 한다.
- FK는 null값이 허용된다.(유니크 키를 참조할 수 있기때문이다.)
- 최대한 지양하는게 참조 무결성을 지키는데 좋다.
- 예) 회사의 직원과 부서를 관리하는 DB
- Employess Table
- EmployeeID(PK) - 각 직원을 식별하는 고유한 식별자
- EmployeeName - 직원의 이름
- DepartmentID(FK) - 직원의 소속 부서 ID를 나타내는 외래키
- Departments Table
- DepartmentID(PK) - 각 부서를 식별하는 고유한 식별자
- DepartmentName - 부서 이름
- 신입 직원의 경우 Employees 테이블에 들어가지만 부서가 지정되지 않으면 DepartmentsID값이 NULL일 수 있다.
- Employess Table
- UK(Unique Key)
- 테이블 내에서 해당 Column값은 항상 유일하다.
- PK와 유사하나 다른점은 Null값을 중복 허용한다.
- 내부적으로 Unique Index를 만들어 처리한다.
- 테이블내에 여러개 지정이 가능하다.
- NULL값이 없는 UK와 PK의 차이점은 역할(Role)에 있다.
- 유니크키는 데이터의 일관성을 유지하기 위해 사용디지만
- 기본키는 각 레코드를 식별하기 위해 사용된다.
- 데이터 무결성 제약조건 - 데이터의 정확성 또는 유효성을 의미
- 트랜잭션(Transaction)
- ACID원칙
- Atomicity(원자성)
- 트랜잭션의 모든 작업은 완전한 하나의 단위로 수행되어야 한다.
- 즉, 트랜잭션의 모든 작업이 성공하면 트랜잭션은 커밋되고 하나라도 실패하면 트랜잭션은 롤백된다.
- Consistency(일관성)
- 트랜잭션이 실행되기 전과 후에 데이터베이스는 일관된 상태를 유지해야한다.
- 트랜잭션의 실행은 데이터베이스의 무결성 원칙을 위반해서는 안된다.
- Isolation(고립성)
- 동시에 실행되는 여러 트랜잭션이 서로 영향을 주지 않고 독립적으로 실행되어야 한다.
- 즉 하나의 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 결과가 영향받아서는 안된다.
- Durability(지속성)
- 트랜잭션이 성공적으로 완료된 후에는 그 결과가 영구적으로 저장되어야 한다.
- 시스템이 고장나거나 장애가 발생하더라도 커밋된 트랜잭션의 결과는 영구적으로 보존되어야 한다.
- Atomicity(원자성)
- ACID원칙
- 자료 구조 알고리즘
- 자바와 자바스크립트
- 자바는 프로그래밍 언어고, 자바스크립트는 웹에서 상호작용과 애니메이션을 만들기 위해 사용되었지만 자바스크립트 기술의 발전으로 인해 점점 차이가 모호해졌다.
- 공통점
- 두 언어 모두 객체 지향 프로그래밍이다. 모두 상속, 캡슐화, 폴리모피즘(다형성) 이라는 기법을 사용한다.
- 두 언어 모두 백엔드 개발이 가능해졌다. 예전엔 자바를 사용해왔지만 Node.js가 등장하며 서버쪽에서도 자바스크립트를 사용할 수 있다.
- 차이점
- 실행환경이 다르다. 자바 애플리케이션은 JVM환경에서 실행되지만 자바스크립트는 웹 브라우저에서 실행된다.
- 자바는 프로그래밍 언어이기 때문에 컴퓨터 언어로 컴파일 과정을 거친다. 반면 자바스크립트는 텍스트로 쓰인 코드로 실행될 수 있는 스크립트 언어이다.
- 자바는 거의 모든 환경에서 활용되고 있다. 자바스크립트는 대부분 웹브라우저 사용되며 실행되려면 반드시 CSS와 HTML에 의존한다.
- 공통점
- 자바는 프로그래밍 언어고, 자바스크립트는 웹에서 상호작용과 애니메이션을 만들기 위해 사용되었지만 자바스크립트 기술의 발전으로 인해 점점 차이가 모호해졌다.
- 리액트란
- UI를 만들기 위한 자바스크립트 라이브러리다.
- 단일 페이지 애플리케이션(Single Page Application, SPA) 개발에 주로 사용된다.
- Node.js란
- 자바스크립트 런타임 환경으로, 서버측에서 자바스크립트를 실행할 수 있도록 해준다.
- Http 프로토콜이란
- 서버와 클라이언트간의 TCP/IP 통신위에서 메시지를 교환하기 위해 사용되는 프로토콜(규약)입니다.
- 쿠키, 세션
- HTTP프로토콜의 특징이자 약점을 보완하기 위해 사용된다.
- HTTP프로토콜은 비연결지향적(클라이언트가 서버에 요청했을때 해당하는 응답을 보낸후 연결을 끊음)이며 상태정보를 유지 안한다. 하지만 실제로 데이터 유지가 필요한 경우가 많다.(로그인)
- 서버와 클라이언트가 통신을 연속적으로 하지않고 계속 끊어지면 웹페이지의 로딩이 느려지고 번거로워진다.
- 클라이언트와 서버사이의 정보 유지를 하기 위해 사용하는것이 쿠키와 세션이다.
- 쿠키
- 사용자의 컴퓨터에 저장되는 파일이다.
- 클라이언트가 페이지를 요청하면 웹서버가 쿠키를 생성한다.
- 생성한 쿠키를 정보에 담아 HTTP응답을 할때 같이 보내준다.
- 쿠키는 클라이언트가 로컬PC에 저장하여 다시 서버에 요청하게 될 때 요청과 함께 쿠키를 전송한다.
- 동일 사이트 재방문시 클라이언트의 PC에 해당쿠키가 있는 경우, 요청페이지와 함께 쿠키를 전송한다.
- 세션
- 브라우저가 종료되기 전까지 클라이언트의 요청을 유지하게 해주는 기술.
- 웹 서버에 웹 컨테이너의 상태를 유지하기 위한 정보를 저장한다.
- 웹 서버에 저장되는 큐키(세션 쿠키)이다.
- 클라이언트가 페이지를 요청하면, 서버는 클라이언트의 Request-Header의 쿠키를 확인하여 클라이언트가 해당 session-id를 보냈는지 확인한다.
- session-id가 존재하지 않는다면, 서버는 session-id를 생성해 클라이언트에게 돌려준다.
- 서버에서 클라이언트로 돌려준 세션아이디를 쿠키를 사용해 서버에 저장한다.
- 클라이언트는 재접속시 이 쿠키를 이요하여 세션아이디 값을 서버에 전달한다.
- 쿠키는 용량제한이 있으며 세션은 없다.
- 쿠키는 정보가 PC에 있어 속도가 빠르고 세션은 서버에있어서 비교적 느리다.
- was란
- Web Application Server
- 브라우저(웹)의 구동
- 사용자의 요청이 먼저 이루어집니다. 사용자는 HTTP메시지 형태로 서버에게 요청하게됩니다.
- 웹 서버는 클라이언트의 요청을 web application Server(WAS)로 보냅니다.
- WAS는 관련된 서블릿을 메모리에 올리고 web.xml을 참조하여 해당 서블릿에 대한 쓰레드를 생성합니다.
- HttpServletRequest와 HttpServletResponse객체를 생성하여 서블릿에 전달하고, 쓰레드는 서블릿의 service()메서드를 호출한다.
- service()메서드는 요청에 맞게 doGet() 또는 doPost()메서드를 호출하고 인자에 맞게 생성된 페이지를 Response객체에 담아 WAS로 전달합니다.
- WAS는 Resoponse객체를 HttpResponse형태로 바꿔 WebServer에 전달하고 클라이언트에게 페이지를 HTTP메시지형태로 전송합니다.
- 생성된 쓰레드를 종료하고, HttpServletRequest와 HttpServletResponse객체를 제거합니다.
- 스프링(Spring)의 3대 요소
- IOC(Inversion of Control)
- 제어의 역전
- 객체의 라이프사이클을 개발자가 아닌 프레임워크가 관리하는 방식
- 즉, 개발자는 프레임워크가 제공하는 메서드를 호출하는데 집중하며, 그 외의 일들은 프레임워크가 알아서 처리한다.
- 이를 통해 개발자는 비즈니스 로직 개발에 집중할 수 있다.
- DI(Dependency Injection)
- 의존성 주입
- 객체가 다른 객체에 의존할 때, 그 의존성을 객체 스스로가 아닌 외부에서 주입받는다.
- 이를 통해 코드간의 결합도를 낮추고 코드의 재사용성과 테스트 용이성을 향상시킬 수 있다.
- 의존성 주입
- PSA(Portable Service Abstraction)
- 서비스 추상화
- 로우레벨의 기술적인 상세 내용을 스프링 프레임워크가 대신 처리해준다.
- 예로 데이터베이스 접근 기술의 경우 JPA, Hibernate, MyBatis등 다양한 기술이 존재하는데, 이러한 기술적인 부분을 추상화 하여 개발자는 실제 사용하는 기술에 대해 신경쓰지않고 일관된 방식으로 개발이 가능하다.
- 서비스 추상화
- AOP (Aspect Oriented Programming)
- 관점 지향 프로그래밍
- 공통적으로 사용되는 기능을 분리하여 재사용성을 높인다.
- 로깅 트랜잭션 관리, 보안등의 기능은 여러 객체에서 공통으로 사용되는데, 이러한 기능들을 분리하여 별도의 모듈로 개발하고 필요한 시점에 적용하는것을 말한다.
- 이를 통해 코드의 중복을 줄이고, 유지보수를 용이하게 할 수 있습니다.
- 관점 지향 프로그래밍
- IOC(Inversion of Control)
- 스프링부트과 스프링
- 스프링은 자바기반 애플리케이션 개발을 지원하는 프레임 워크이다.
- 스프링 부트는 스프링의 단점을 해결하였다. 내장형 서버를 사용하여 별도의 WAS를 설치할 필요 없이 애플리케이션을 실행할 수 있으며, 스프링 프레임워크 기능과 라이브러리의 통합을 간편하게 구성가능하다.
- 내장서버
- 의존성 관리 간소화
- 운영 편의성
- 애플리케이션의 상태 모니터링, 로깅, 보안 설정 등 운영에 필요한 기능들을 제공한다.
반응형