Java 어플리케이션 실행과 Servlet, Applet
Application → java라는 명령어로 컴파일된 byte 코드를 실행되는 프로그램
Servlet → 자바의 서버에서 실행되고 직접 사용하는 경우는 드뭄 하지만 아키텍쳐의 이해를 위해선 학습 필요
●Servlet에 대한 추가 설명
서블릿(Servlet)은 Java 언어를 기반으로 웹 애플리케이션을 개발하기 위한 기술 중 하나로, 클라이언트와 서버 사이에서 동작하는 웹 컴포넌트입니다. 서블릿은 주로 웹 서버에서 동작하며, HTTP 요청과 응답을 처리하여 동적인 웹 페이지나 웹 애플리케이션을 생성하고 관리하는 데 사용됩니다.
서블릿은 자바 클래스로 구현되며, 주로 javax.servlet 패키지와 javax.servlet.http 패키지에 포함된 인터페이스와 클래스들을 사용하여 개발됩니다. 서블릿은 다음과 같은 특징을 가지고 있습니다:
- 동적 콘텐츠 생성: 서블릿은 클라이언트의 요청에 따라 동적인 콘텐츠를 생성할 수 있습니다. 데이터베이스 조회, 계산 등을 통해 동적인 웹 페이지를 생성하거나 수정할 수 있습니다.
- 라이프사이클 관리: 서블릿은 초기화, 서비스, 종료 등의 라이프사이클 메서드를 가지며, 웹 컨테이너(예: Apache Tomcat)에 의해 관리됩니다. 이러한 라이프사이클 메서드를 이용하여 서블릿의 초기화 작업이나 메모리 해제 등을 관리할 수 있습니다.
- 스레드 안전성: 서블릿 컨테이너는 각각의 요청에 대해 별도의 스레드를 생성하여 처리합니다. 이로써 여러 클라이언트 요청을 동시에 처리할 수 있습니다. 개발자는 스레드 안전성에 신경을 써서 코드를 작성해야 합니다.
- HTTP 프로토콜 지원: 주로 HTTP 프로토콜을 통해 통신하는 웹 애플리케이션에서 사용됩니다. 따라서 HTTP 요청 메서드(GET, POST 등)와 응답 상태 코드(200 OK, 404 Not Found 등)를 다루는 데에 특화되어 있습니다.
- 웹 애플리케이션에서의 사용: 서블릿은 주로 웹 애플리케이션의 비즈니스 로직이나 데이터 처리를 담당하며, HTML 생성 및 웹 페이지 렌더링 역할은 JSP(JavaServer Pages)와 같은 다른 기술과 결합하여 사용됩니다.
서블릿의 주요 장점은 높은 확장성과 재사용성을 제공한다는 것입니다. 웹 애플리케이션의 규모가 커지더라도 서블릿을 활용하여 유지보수가 쉽고 효율적인 구조를 구축할 수 있습니다.
Applet → 느려서 사용 X
변수의 이해
변수를 선언할땐 데이터 타입을 항상 선언해줘야 한다.
ex) 기본형 int i = 1; , 참조형 Member member = new Member();
기본형의 타입
논리형 : boolean JVM에 따라 다를 수 있으며, 보통 1 byte로 표현됩니다
정수형 : byte 1, short 2, int 4, long 8
문자형 : char 2
실수형 : float 4, double 8
참조형
String(참조형이지만 기본형처럼 사용), 배열(array[]), 열거(enum), 클래스(class), 인터페이스(interface)
JVM의 메모리 구조
크게 static, stack, heap 3가지의 영역으로 나뉘며
method/static → 클래스 정보, 클래스 변수(static 변수), 메소드 코드 등이 저장되는 영역
stack → 로컬 변수, 매개변수, 임시 데이터 등이 저장되는 영역
heap → 동적으로 할당되는 객체, API들이 저장되는 영역
(자바는 컴파일러 언어임과 동시에 인터프리터 언어이기도 하다. 플렛폼에서 독립적으로 작동하기 위해 JVM에서 해석할 수 있는 바이트 코드로 변환하고 이로 인해 플랫폼 독립성을 갖추게 된다.)
컴파일러 언어와 인터프리터 언어의 차이점
컴파일러 언어와 인터프리터 언어는 프로그램의 실행 방식과 처리 과정에서 차이가 있습니다. 아래는 그 차이점을 설명하는 것입니다:
컴파일러 언어:
- 컴파일 과정: 프로그래머가 작성한 소스 코드를 전체적으로 읽어와 컴파일러에 의해 기계어나 중간 코드로 변환됩니다. 이 변환 과정은 전체 소스 코드를 한 번에 진행됩니다.
- 실행 속도: 컴파일된 프로그램은 기계어나 중간 코드로 변환되어 있으므로 실행 속도가 빠릅니다. 미리 최적화되기 때문입니다.
- 포팅 및 배포: 컴파일러에 의해 변환된 코드는 해당 플랫폼에서 직접 실행되므로 다른 플랫폼으로 이식하려면 다시 컴파일해야 합니다.
- 예시 언어: C, C++, Rust 등
인터프리터 언어:
- 인터프리팅 과정: 프로그래머가 작성한 소스 코드를 한 줄씩 읽어와 인터프리터가 해당 코드를 바로 실행합니다. 따라서 실행 중에 코드를 직접 해석하고 실행합니다.
- 실행 속도: 인터프리터는 실행 중에 코드를 해석하므로 실행 속도가 컴파일러 언어에 비해 상대적으로 느릴 수 있습니다. 최적화와 JIT(Just-In-Time) 컴파일링을 통해 성능을 개선할 수도 있습니다.
- 포팅 및 배포: 인터프리터 언어의 코드는 플랫폼 독립적입니다. 따라서 한 번 작성된 코드를 다양한 플랫폼에서 실행할 수 있습니다.
- 예시 언어: Python, Ruby, JavaScript 등
요약하면, 컴파일러 언어는 미리 소스 코드를 변환하여 기계어나 중간 코드로 만들어 실행하며, 인터프리터 언어는 소스 코드를 한 줄씩 읽어와 바로 실행하는 방식입니다.
자바는 일부 인터프리터 언어의 특징을 내포하고 있습니다. 이는 자바의 실행 방식과 JVM의 역할 때문입니다.
- 인터프리터 언어의 특징 내포: 자바는 컴파일되어 바이트 코드로 변환된 후, 이 바이트 코드는 JVM에서 해석되고 실행됩니다. 이러한 해석 단계는 인터프리터 언어의 특징과 유사하게 보일 수 있습니다. 하지만 실제로 JVM은 바이트 코드를 실행하기 전에 일부 코드를 네이티브 코드로 컴파일하고 최적화하는 JIT(Just-In-Time) 컴파일링을 수행하여 실행 속도를 향상시킵니다.
- 컴파일과 실행 분리: 자바는 일반적인 컴파일러 언어와는 달리, 컴파일과 실행이 분리됩니다. 컴파일러는 자바 소스 코드를 바이트 코드로 변환하며, 이후 해당 바이트 코드는 실행 시에 JVM에서 해석되어 실행됩니다. 이런 점에서 컴파일과 인터프리팅이 분리되어 있는 언어의 특징과 비슷합니다.
따라서 자바는 컴파일러 언어이면서 JVM을 통한 중간 단계의 해석과정을 통해 실행되므로, 컴파일러 언어와 인터프리터 언어의 특징을 모두 가지고 있는 것으로 볼 수 있습니다.
여기서 기본형 데이터 타입과 참조형 데이터 타입의 차이점을 알기 위해 테스트를 진행해봤다.
// 기본형은 stack 영역에 값이 그대로 저장되어 서로 비교했을시
// true를 반환한다
public class VariableTypeTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
System.out.println("=======기본형=======");
if (i == j) {
System.out.println("기본형");
} else {
System.out.println("기본형 다르다");
}
// 참조형은 heap 영역에 객체를 생성하고 그 참조값을
// stack형에 저장하기 때문에 false를 반환한다
String str = new String("test");
String str2 = new String("test");
System.out.println("=======참조형=======");
if (str == str2) {
System.out.println("참조형");
} else {
System.out.println("참조형 다르다");
}
}
하지만 아래 코드와 같이 변수를 선언하면 str3 == str4는 true를 반환한다.
// new 를 선언해주면 참조값으로 비교해 다르다고 나오는데
// new 를 선언하지 않고 변수를 비교하면 참조값이 같다고 나온다
// 왜일까
String str3 = "test";
String str4 = "test";
System.out.println("=======참조형Test=======");
if (str3 == str4) {
System.out.println("참조형?");
} else {
System.out.println("참조형 다르다");
}
}
이는 해당 str 변수가 static 영역에 선언되었기 때문이다
변수와 시스템 입출력
출력
System.out.println, System.out.print, System.out.printf
입력
System.in.read, Scanner
Scanner 사용시 next메소드를 사용하면 엔터와 spacebar 기준으로 줄바꿈을 하기 때문에 띄어쓰기가 불가능하다, 이를 해결하기 위해선 nextLine 메소드를 사용하면 된다.
public class ScannerTest {
public static void main(String[] args) {
Scanner key = new Scanner(System.in);
// Scanner를 이용하면 키보드로 입력하는 값을 읽을 수 있고
// next() 는 spacebar 나 enter를 만나기 전까지 입력된 문자열을 읽어서 리턴
System.out.print("input value1 : ");
String value1 = key.next();
System.out.println("value1 => " + value1);
System.out.print("input value2 : ");
int value2 = key.nextInt();
System.out.println("value2 => " + value2);
System.out.print("input value3 : ");
double value3 = key.nextDouble();
System.out.println("value3 => " + value3);
}
}
객체 지향 프로그래밍(Object-Oriented Programming, OOP)
- 클래스와 객체 (Class and Objects):
- 클래스는 객체를 정의하는 틀 또는 설계도입니다. 데이터와 해당 데이터를 처리하는 메서드를 포함합니다.
- 객체는 클래스의 인스턴스로, 실제로 메모리에 할당된 데이터와 해당 데이터를 다루는 메서드를 가지고 있습니다.
- 캡슐화 (Encapsulation):
- 데이터와 데이터를 처리하는 메서드를 하나의 단위로 묶는 것을 말합니다.
- 외부에서 객체 내부의 데이터에 직접 접근하지 않고, 메서드를 통해 접근하도록 합니다.
- 정보 은닉과 관련하여 객체 내부의 상세한 구현을 외부에 노출하지 않는 것이 목표입니다.
- 상속 (Inheritance):
- 기존 클래스를 확장하여 새로운 클래스를 정의할 수 있는 개념입니다.
- 상위 클래스(부모 클래스 또는 슈퍼 클래스)의 특성을 하위 클래스(자식 클래스 또는 서브 클래스)가 물려받습니다.
- 코드의 재사용성을 높이고 계층 구조를 구성할 수 있습니다.
- 다형성 (Polymorphism):
- 한 객체가 다양한 타입을 가질 수 있는 능력을 말합니다.
- 메서드 오버로딩(하나의 클래스 내에서 같은 이름의 메서드를 여러 개 정의)과 메서드 오버라이딩(하위 클래스에서 상위 클래스의 메서드를 재정의)을 통해 구현됩니다.
- 코드의 유연성과 가독성을 높일 수 있습니다.
- 클래스와 객체 (Class and Objects):
'코딩딩 > Java' 카테고리의 다른 글
Setter Getter Constructor (0) | 2023.08.16 |
---|---|
객체 지향 프로그래밍 (0) | 2023.08.14 |
자바 기초 (0) | 2023.08.09 |
Set 컬렉션 (0) | 2023.07.15 |
List 컬렉션 (0) | 2023.07.15 |