1. 객체지향 시작 : 22.12.19
- 우리는 일단 용어보다는 필요성에 꽂혀야 한다.
1) [함수의 필요성]
- 집중화, 코드를 잘라서 사용, 코드의 재사용, 구현 코드 숨김 가능
2) [구조체]
-
구조체 :데이터들을 구조화 해서 만드는 것
- 데이터를 구조화하지 않았을 때 생기는 이유
- 변수명의 충돌상황을 모면할 수 있다,
- 우리는 공통분모의 내용 주석을 달아야 하는데 의미를 공통화하여 부여할 수 있다.
- 그래서, 우리는 데이터는 구조화를 만들어 왔다.
3) [객체지향이 나온 이유]
-
기존의 함수를 나누는 기준이 명확하지 않다.
-
함수의 고립화를 무너트린다.(??) : 외부에서 문제가 발생한것이 영향을 끼침!!
4) [캡슐화]
- 함수들을 모아두는 것이 캡슐화의 동기를 만들었다. 그냥 함수들을 모아두는 것은 캡슐화가 아니다.
5) [객체지향 프로그래밍(OOP)]
- 개발자의 자세 : 기획!!!, 설계, 건축, 유지 관리
- 객체지향은 우리가 말한대로 만들어지는 프로그램이다.
- 즉, 행위, 대상, 주체가 있다.(오목 게임 생각)
6) [객체지향 프로그래밍(OOP) - 예시]
- 우리는 구조를 만들때, 인문학적인 생각이 가장 중요하다. ( ex) 그림보고 객체-행위 생각해보기 )
- 하지만, 행위를 하지 않으면 객체가 아니다. ( ex) 그림에서 달, 구름, 나무 등등 )
- 즉, 객체 지향에서 객체는 무조건 행위여야 한다!!!
- ex) 개체는 메뉴판의 자장면, 객체는 메뉴를 주문 후 실제로 만들어진 자장면이다.
7) [객체의 속성]
- 자바에서는 객체를 “Class”라고 부른다. 객체의 속성은 중요하다.( ex) 비행기의 위치 상태값과 같다.)
8) [객체지향의 목적]
-
우리의 머릿속에 있는 것을 그대로 표현할 줄 알아야 한다.
-
이제는 객체 지향에서 함수처럼 코드를 잘라내는 것이 아니라 접근 방법이고 역할이라서 “메서드”라고한다.
-
기존의 방식처럼은 실세계에서 만들어지는 방식과 달라서 메서드 방식처럼 우리가 사고하는 그 방식 그대로 사용한다.
printExam(exam); // 기존 방식(함수)
exam1.input(); // 새로운 방식(메서드)
- 객체지향은 기존의 방식에서 표현식이 바뀐다.
package ex5.capsule;
public class Exam {
int kor;
int eng;
int math;
public void input() {
}
public void print() {
int kor = this.kor;
int eng = this.eng;
int math = this.math;
System.out.printf("kor: %d\n", kor);
System.out.printf("eng: %d\n", eng);
System.out.printf("math: %d\n", math);
System.out.printf("-----------------------\n\n");
}
}
}
package ex5.capsule;
public class CapsuleTest {
public static void main(String[] args) {
//성적 객체를 준비한다.
//실제 뉴렉 = new 성적();
Exam exam1 = new Exam();
// 성적을 입력받는다.
// =>뉴렉 성적.입력();
inputExam(exam1);
exam1.input();
// 성적을 출력한다.
// =>뉴렉 성적.출력;
printExam(exam1); // 이전 방식!!
exam1.print(); // 새로운 방식!! : 객체나 실체나 인스턴스에다가 이 객체(exam1)가 print()를 넘겨 받는다.
// 정리: 우리는 인스턴스에 print() 메서드를 붙여주므로 인스턴스 메서드라고 부른다.
}
private static void inputExam(Exam exam1) { // static을 써주는 이유는 인스턴스 메서드와 구별해주기 위해서 static을 써준다.
}
private static void printExam(Exam exam1) {
int kor = 30;
int eng = 20 ;
int math = 10;
System.out.printf("kor: %d\n", kor);
System.out.printf("eng: %d\n", eng);
System.out.printf("math: %d\n", math);
System.out.printf("-----------------------\n\n");
}
}
}
}
9) [인스턴스 메서드]
package ex5.capsule;
public class Exam {
int kor;
int eng;
int math;
public void input() {
}
public void print() {
int kor = this.kor;
int eng = this.eng;
int math = this.math;
System.out.printf("kor: %d\n", this.kor);
System.out.printf("eng: %d\n", this.eng);
System.out.printf("math: %d\n", this.math);
System.out.printf("-----------------------\n\n");
}
}
}
- 특징
- 인스턴스 메서드는 넘겨 받는 값이 없다. 또한, this 객체를 사용한다.
- 먼저, 지역변수를 찾아보고 / 넘겨받고 this의 객체를 찾아서 그안의 속성에 kor이 있는지 확인한다.
- 우선 순위(중요!!) : 지역 변수 > this 변수
- this.kor에서 this는 되도록 안 쓰는 것이 좋다. 하지만, 지역변수가 있어서 우선 순위에 밀리는 경우에는 this를 꼭 써주어야 한다.
10) [캡슐의 의미]
- 내가 만든 함수는 꼭 그 구조안에 들어가야 한다.
- static 함수는 만들어지는 위치가 정해져 있지 않다.
- 코드의 캡슐화를 위해서 요소들을 뽑아서 쓰지말아야 한다.
- 은닉성 : 캡슐화를 위해서 은닉성을 지켜주어야 한다!!! 캡슐 밖에서는 캡슐안의 코드를 사용할 수 없게 해야 한다.(외부에서 영향을 주면, 에러가 발생한다.)
- 캡슐화를 위해 private으로 작성한다. public은 반대 개념!!
- 추가적으로, 변수 초기화 함수를 위해 .init() 함수를 만들자!
11) [init() 함수]
public class Exam {
private int kor;
private int eng;
private int math;
public void init() { // init은 초기화가 아니라 reset에 가깝다..
// init 함수는 객체가 만들어지자 마자 제일 먼저 실행되어야 한다.
int kor = 30;
int eng = 40;
int math = 50;
}
}
}
public class CapsuleTest {
public static void main(String[] args) {
//성적 객체를 준비한다.
//실제 뉴렉 = new 성적();
Exam exam1 = new Exam();
exam1.init();
}
|
- init은 초기화가 아니라 reset에 가깝다.
- init 함수는 객체가 만들어지자 마자 제일 먼저 실행되어야 한다.
- new Exam();에서 new Exam을 “()”로 넘겨주는 것이다. “()”는 이름이 없고 갓 생성된 한번도 쓴적이 없는 함수다.
12) [생성자]
- 원래는 생성자는 이름이 없다.(생성자 함수라고 쓰면 안된다.)
public ?() {
int kor = 30;
int eng = 40;
int math = 50;
}
- 이름 생성을 다음과 같이 생성해주면, Exam() 형식만 생성자를 호출 할 수 있다.(한정사 느낌)
public Exam() {
int kor = 30;
int eng = 40;
int math = 50;
}
22.12.19 실습 코드
package ex5.capsule;
public class CapsuleTest {
public static void main(String[] args) {
//성적 객체를 준비한다.
//실제 뉴렉 = new 성적();
Exam exam1 = new Exam();
//exam1.init();
// 성적을 입력받는다.
// =>뉴렉 성적.입력();
Exam.inputExam(exam1);
exam1.input();
// 성적을 출력한다.
// =>뉴렉 성적.출력;
Exam.printExam(exam1); // 이전 방식!!
exam1.print(); // 새로운 방식!! : 객체나 실체나 인스턴스의 개념인 객체(exam1)가 메서드(print())를 넘겨 받는다.
// 정리: 우리는 인스턴스에 print() 메서드를 붙여주므로 인스턴스 메서드라고 부른다.
}
}
package ex5.capsule;
import java.util.Scanner;
public class Exam {
private int kor;
private int eng;
private int math;
public Exam() {
kor = 0;
eng = 0;
math = 0;
}
// public void init() { // init은 초기화가 아니라 reset에 가깝다..
// // init 함수는 객체가 만들어지자 마자 제일 먼저 실행되어야 한다.
// int kor = 0;
// int eng = 0;
// int math = 0;
// }
public void input() {
Scanner scan = new Scanner(System.in);
System.out.println("┌──────────────┐");
System.out.println("│ 성적 입력 │");
System.out.println("└──────────────┘");
do {
System.out.print("kor : ");
kor = scan.nextInt();
if(kor < 0 || kor > 100)
System.out.println("kor은 0~100 의 값을 입력해주세요.");
} while (kor < 0 || kor > 100);
do {
System.out.print("eng : ");
eng = scan.nextInt();
if(eng < 0 || eng > 100)
System.out.println("eng은 0~100 의 값을 입력해주세요.");
} while (eng < 0 || eng > 100);
do {
System.out.print("math : ");
math = scan.nextInt();
if(math < 0 || math > 100)
System.out.println("math은 0~100 의 값을 입력해주세요.");
} while (math < 0 || math > 100);
}
public void print() {
System.out.printf("kor: %d\n", this.kor); // 우선순위 생각!!(앞의 지역변수 때문에 this를 써야한다.)
System.out.printf("eng: %d\n", this.eng);
System.out.printf("math: %d\n", this.math);
System.out.printf("-----------------------\n\n");
}
static void inputExam(Exam exam1) { // static을 써주는 이유는 인스턴스 메서드와 구별해주기 위해서 static을 써준다.(static 함수)
exam1.kor = 30;
exam1.eng = 20 ;
exam1.math = 10;
}
static void printExam(Exam exam1) {
System.out.printf("kor1: %d\n", exam1.kor);
System.out.printf("eng1: %d\n", exam1.eng);
System.out.printf("math1: %d\n", exam1.math);
System.out.printf("-----------------------\n\n");
}
}
Daily Test : 22.12.20
-프로그램 제작 시,
- 개발 일지 제작 하기 : 개발 목적, 키워드, 어려웠던 부분, 다른 방법?, 개선 부분!! 적기
package day.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
public class test_221220_1_1 { // 코드는 단계별로 주석처리로 진행했다.
public static void main(String[] args) throws IOException {
// 문제 10 : 다음 각 절차를 따라 작성하시오. 키워드 힌트가 필요하다면 열어보기!
// 1. canvas라는 이름으로 문자 20x20개를 저장할 수 있는 배열 객체를 생성한다.
// 2. canvas 배열을 다음처럼 ‘┼’ 문자로 채우는 코드를 작성하시오.
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// 3. ‘○’ 문자를 이용해서 canvas에 선을 그리는 함수를 작성하시오.
// 함수의 호출 예
// 위의 결과는 다음과 같다.
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼○┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼○┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼○┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼○┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼○┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼○┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼○┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼○┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼○┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼○┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼○┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
// ┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼
char[][] canvas = new char[20][20];
{
// 코드를 작성하는 공간
for (int j = 0; j < 20; j++) {
for (int i = 0; i < 20; i++) {
canvas[j][i] = '┼';
System.out.printf("%c", canvas[j][i]);
}
System.out.println();
}
System.out.println("board 초기화 완료\n");
}
{
// 2번 문제 코드
// 3번 문제풀이로 작성된 함수를 호출하는 코드
int x1 = 10;
int y1 = 5;
int x2 = 13;
int y2 = 13;
drawLineOnCanvas(canvas, x1, y1, x2, y2);
}
}
static void drawLineOnCanvas(char[][] canvas, int x1, int y1, int x2, int y2) {
for (int j = 0; j < 20; j++) {
for (int i = 0; i < 20; i++) {
canvas[j][i] = '┼';
if (x2 > x1 && y2 > y1)
if ((j - y1) == ((y2 - y1) / (x2 - x1)) * (i - x1) && i <= x2 - 1 && i >= x1 - 1 && j <= y2 - 1
&& i >= y1 - 1)
canvas[j][i] = '○';
else if (x2 < x1 && y2 > y1)
if ((j - y1) == ((y2 - y1) / (x2 - x1)) * (i - x1) && (i >= x2 - 1 && i <= x1 - 1) && (j <= y2 - 1
&& i >= y1 - 1))
canvas[j][i] = '○';
System.out.printf("%c", canvas[j][i]);
}
System.out.println();
}
}
}
객체 지향 프로그래밍 2일차 : 22.12.20
1) [수업 전 내용]
-
Data 분석에 관심이 있으면, 확률과 통계 공부하기(선형 대수 등등)
- 캡슐화의 의미 : 구조화된 데이터, 그것을 사용하는 함수들을 묶어놓는 것.
- 즉, 의미가 있고 목적을 가지고 있는 것
-
자바에서는 카멜 표기로 변수명 사용해야 한다, 변수명은 의미가 명확해야 한다.
- 일반적인 책의 내용에서 왜, 어떻게 사용해야하는지를 모두 믿지 말고 참고만 하기.
2) [캡슐화의 이해]
-
우리는 프로그램에서 캡슐이 깨지면 안 된다.
- 캡슐이 깨지는 것을 막기 위해서 도구(접근 제어자)가 필요하다.(private, public, protected, default, internal)
- ex) 윈도우의 창을 이동하거나 닫거나 열거나 하는 행위는 모두 객체로 설정되어 있다.
-
생성자는 함수가 아니며 이름으로 호출되는 것이 아니라 Exam 형식이여야만 ()로 호출된다.
- private int kor은 형식이다.(메뉴판 느낌), 전역 변수도 아니다.
package ex5.capsule;
import java.util.Scanner;
public class Exam {
private int kor;
private int eng;
private int math;
3) [오버로드 함수 개념], [오버로드 생성자 개념], [생성자 설정법]
- 자바에서 예전은 같은 이름의 함수은 에러가 발생했다. 인자를 추가로 받기 때문에 적재된 것이 많아서 “오버로드 함수”라고 부른다.
package ex5.capsule;
import java.util.Scanner;
public class Exam {
private int kor;
private int eng;
private int math;
public Exam() { // 이클립스에서는 생성자를 안 만들어주어도
// 기본적으로 0으로 세팅되는 생성자를 만들어준다.
// kor = 0;
// eng = 0;
// math = 0;
//Exam(0,0,0); // 중요!! 생성자는 이름이 없기 때문에 호출될 방법이 없구나. 그래서 this(0,0,0)로 호출한다.
this(0,0,0); // this(0,0,0); 는 객체가 단 한번도 실행되기 전에 실행되어야 한다.
} // kor = 0;를 먼저 생성했으면 에러가 발생해버린다.
public Exam(int kor, int eng, int math) { // 오버로드 생성자 이다. 오버로드 생성자는 기본적으로
this.kor = kor; // 이클립스가 생성자에 의해서 0.0.0이 입력된다..
this.eng = eng; // 밑의 print() 오버로드 함수와 같은 역할이다.(기본값 setting)
this.math = math; // main함수에서 사용자가 임의의 값(Exam exam1 = new Exam(1,2,3))으로 설정해줄 수도 있다.
}
// public void init() { // init은 초기화가 아니라 reset에 가깝다..
// // init 함수는 객체가 만들어지자 마자 제일 먼저 실행되어야 한다.
// int kor = 30;
// int eng = 40;
// int math = 50;
// }
public void input() {
Scanner scan = new Scanner(System.in);
System.out.println("┌──────────────┐");
System.out.println("│ 성적 입력 │");
System.out.println("└──────────────┘");
do {
System.out.print("kor : ");
kor = scan.nextInt();
if(kor < 0 || kor > 100)
System.out.println("kor은 0~100 의 값을 입력해주세요.");
} while (kor < 0 || kor > 100);
do {
System.out.print("eng : ");
eng = scan.nextInt();
if(eng < 0 || eng > 100)
System.out.println("eng은 0~100 의 값을 입력해주세요.");
} while (eng < 0 || eng > 100);
do {
System.out.print("math : ");
math = scan.nextInt();
if(math < 0 || math > 100)
System.out.println("math은 0~100 의 값을 입력해주세요.");
} while (math < 0 || math > 100);
}
public void print() { // 오버로드 메서드는 구현된 메서드에게 넘겨준다.
print('-',30);
}
public void print(char c) {
print(c,30);
}
public void print(char c, int length) {
System.out.printf("kor: %d\n", this.kor); // 우선순위 생각!!(앞의 지역변수 때문에 this를 써야한다.)
System.out.printf("eng: %d\n", this.eng);
System.out.printf("math: %d\n", this.math);
for(int i = 0; i<length; i++)
System.out.printf("%c", c);
}
static void inputExam(Exam exam1) { // static을 써주는 이유는 인스턴스 메서드와 구별해주기 위해서 static을 써준다.(static 함수)
exam1.kor = 30;
exam1.eng = 20 ;
exam1.math = 10;
}
static void printExam(Exam exam1) {
System.out.printf("kor1: %d\n", exam1.kor);
System.out.printf("eng1: %d\n", exam1.eng);
System.out.printf("math1: %d\n", exam1.math);
System.out.printf("-----------------------\n\n");
}
}
- this는 객체이며 인스턴스라서 객체를 대신 해주는 역할을 해준다.
4) [상속]
-
상속 : 캡슐 덩어리를 엮어내고 단계를 만들어 내는 것, 조립하는 것
-
캡슐이 하나 나오면서 main함수가 점점 가벼워진다.
-
의존(Dependency) 객체 : 부품처럼 객체를 사용한다. 부품을 이용해서 Program이 만들어진다.
-
그래서 우리는 데이터를 분리하고 입/출력을 따로 분리한다.
package ex6.has_a;
public class CapsuleTest {
public static void main(String[] args) {
//성적 객체를 준비한다.
//실제 뉴렉 = new 성적();
//Exam newlec = new Exam(1,2,3);
ExamConsole console = new ExamConsole();
console.input();
console.print(); // 새로운 방식!! : 객체나 실체나 인스턴스의 개념인 객체(exam1)가 메서드(print())를 넘겨 받는다.
// 정리: 우리는 인스턴스에 print() 메서드를 붙여주므로 인스턴스 메서드라고 부른다.
}
}
package ex6.has_a;
import java.util.Scanner;
public class ExamConsole {
private Exam exam; // 이 구문을 통해 결합이 되는 것이다.
// 여기서 exam은 단순히 참조명이 아니라 이 console의 부품명이 된다.
// 분리가 되면 한쪽은 부품이 되고 다른쪽은 제품이 된다.
// Exam에서는 그냥 사용하고
// ExamConsole에서는 Exam 객체의 exam을 구성하는 관계가 존재한다.(Composition Has A 관계로 사용하고 있다. = 부품이나 멤버(this)를 가지고 있다.).
// main 함수에서는 member가 아니라 그냥 쓴다. 구성하는 관계가 아니다.(Has A 관계)
// Composition Has A 관계 : 객체를 a로 관계를 갖고 있다. 객체를 갖고는 있는데 각자 꽂아야하고 부품들을 무조건 생성해야한다.
// 부품들을 생성만하고 끝날 수도 있다. "일체형 관계"이다. 즉, "완성품"이다.
// 부품이 그 안에 있는지도 모르는 관계
// Association Has A 관계 : 우리 코드를 따로 결합해주어야 한다. 핸드폰과 부품을 결합해주는 관계. 분리형 관계
// Aggregation Has A 관계 :
// *** 데이터 구조를 유연하게 하기위해서 데이터 속성의 값을 노출해도 되지만 데이터 구조를 노출하면 안된다.
public ExamConsole() {
exam = new Exam(); // 콘솔에서는 부품을 자기가 직접 만들어서 자급자족한다. 이것이 Composition Has A 관계이다.
// 즉, 데이터를 통으로 넘겨주는 격이다.
} // 오전의 문제 푼 것에서 배열에서 생성자의 메모리 할당 생성자와 같다.
// Composition Has A은 부품을 바꿔낄 수 없고 Association Has A는 부품을 바꿔낄 수 있다.
// 따라서, Association Has A는 유연한 코드이다.
public void input() {
Scanner scan = new Scanner(System.in);
System.out.println("┌──────────────┐");
System.out.println("│ 성적 입력 │");
System.out.println("└──────────────┘");
int kor, eng, math;
do {
System.out.print("kor : ");
kor = scan.nextInt();
if(kor < 0 || kor > 100)
System.out.println("kor은 0~100 의 값을 입력해주세요.");
} while (kor < 0 || kor > 100);
// 이것이 Association Has A 관계
exam.setKor(kor); // this.exam.setKor는 국어 성적을 setting 해주는 역할이며 이것을 간단히 exam.setKor(kor)라고 사용하며 setter 메서드라고 부른다.
do {
System.out.print("eng : ");
eng = scan.nextInt();
if(eng < 0 || eng > 100)
System.out.println("eng은 0~100 의 값을 입력해주세요.");
} while (eng < 0 || eng > 100);
exam.setEng(eng); // this.exam.setEng는 영어 성적을 setting 해주는 역할이며 이것을 exam.setEng(eng)라고 사용하며 setter 메서드라고 부른다.
do {
System.out.print("math : ");
math = scan.nextInt();
if(math < 0 || math > 100)
System.out.println("math은 0~100 의 값을 입력해주세요.");
} while (math < 0 || math > 100);
exam.setMath(math); // this.exam.setMath는 수학 성적을 setting 해주는 역할이며 이것을 exam.setMath(math)라고 사용하며 setter 메서드라고 부른다.
}
public void print() { // 오버로드 메서드는 구현된 메서드에게 넘겨준다.
print('-',30);
}
public void print(char c) {
print(c,30);
}
public void print(char c, int length) {
int total = exam.total(); // total과 avg를 출력 이외에도 사용하기 위해서 메서드로 만들기
double avg = exam.avg();
// System.out.printf("kor: %d\n", exam.getKor());
// System.out.printf("eng: %d\n", exam.getEng());
// System.out.printf("math: %d\n", exam.getMath());
System.out.printf("kor: %d\n", exam.getKor());
System.out.printf("eng: %d\n", exam.getEng());
System.out.printf("math: %d\n", exam.getMath());
for(int i = 0; i<length; i++)
System.out.printf("%c", c);
}
}
package ex6.has_a;
public class Exam {
//private Subject subject; // Subject를 추가해줘도 구조는 바뀌지만 구성은 바뀌지 않는다.(중요!! exam : subject.exam.kor)
// 데이터 구조를 숨겨주는 역할을 해주는 것이 getter와 setter이다.(구성은 같다.)
private int kor; // 외부 파일의 접근을 위해서 private는 사용할 수 없다.
private int eng;
private int math;
public Exam() { // 이클립스에서는 생성자를 안 만들어주어도
// 기본적으로 0으로 세팅되는 생성자를 만들어준다.
// kor = 0;
// eng = 0;
// math = 0;
//Exam(0,0,0); // 중요!! 생성자는 이름이 없기 때문에 호출될 방법이 없구나. 그래서 this(0,0,0)로 호출한다.
this(0,0,0); // this(0,0,0); 는 객체가 단 한번도 실행되기 전에 실행되어야 한다.
} // kor = 0;를 먼저 생성했으면 에러가 발생해버린다.
public Exam(int kor, int eng, int math) { // 오버로드 생성자 이다. 오버로드 생성자는 기본적으로
this.kor = kor; // 이클립스가 생성자에 의해서 0.0.0이 입력된다..
this.eng = eng; // 밑의 print() 오버로드 함수와 같은 역할이다.(기본값 setting)
this.math = math; // main함수에서 사용자가 임의의 값(Exam exam1 = new Exam(1,2,3))으로 설정해줄 수도 있다.
}
public double avg() {
return total() / 3.0;
}
public int total() {
return kor + eng + math;
}
public void setKor(int kor) { // 데이터 구조를 숨겨주는 역할을 해주는 것이 getter와 setter이다.(구성은 같다.)
this.kor = kor; // this는 객체를 대신 써주는 것
}
public void setEng(int eng) { // getter와 setter는 자동적으로 만들수 있다.
this.eng = eng;
}
public void setMath(int math) {
this.math = math;
}
public int getKor() {
return kor;
}
public int getEng() {
return eng;
}
public int getMath() {
return math;
}
}
3. 상속(객체 지향 3) : 22.12.21
0) 들어가기전, 객체 배열 정리
-
항상, 새로 만들어진 객체에 배열을 사용하기 위해서 2단계의 과정을 무조건 진행해야한다.
-
1단계 : 배열 참조
Student[] students = new Student[10]; // 중요!! 배열 참조(나는 생성자에서 만드려고 했다.)
-
2단계 : 배열 할당
students[j] = new Student(); // 중요!! 배열 할당!!(내가 이해하지 못한 부분) // 그 만들어진 공간에 이름 붙여주는 역할
-
package day.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class Room {
Student[] students = new Student[10]; // 중요!! 배열 참조(나는 생성자에서 만드려고 했다.)
// 이건 공간만 만들어줌.
public void load(String path) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(path);
Scanner scan = new Scanner(fis);
while(scan.hasNext()) { // 데이터의 크기를 세는 방법 : 파일을 두번 읽어서 첫번째는 데이터 크기 세고 나머지는 그 크기는 배열 생성
// 두번째 방법은 : 가변배열 방법 이용
for(int j=0; j<10; j++) {
// line.replaceAll(",|\n", " "); // 이 방법으로도 나중에 해보기
String line = scan.nextLine();
String[] tokens = line.split(","); // 이부분은 위의 line과 같은 방식으로 String[]으로 생성한 부분이다.
// 참조 변수명이 여러개 값을 받으면 복수로 변수명 만들기
students[j] = new Student(); // 중요!! 배열 할당!!(내가 이해하지 못한 부분)
// 그 만들어진 공간에 이름 붙여주는 역할
int num = Integer.parseInt(tokens[0]);
students[j].setId(num);
students[j].setName(tokens[1]);
}
}
}
1) [관계 구분]
-
Has A 관계 : 결합관계를 의미한다.(부품과 제품 사이의 관계)
-
Is A 상속 : “상속”이라고 부른다.
-
Aggregation 관계 : 필요할 때마다 객체를 만든다.(집합 관계, 1:N 관계), 처음에는 메서드가 없다.
-
Composition 관계 : 이미 객체를 만들어 놓고 사용한다. (1:1 관계), 메서드를 한번에 다 갖고 있다.
-
Associaion 관계 : 객체를 각각 만들어주고 서로 연결해주는 과정이 있다.
-
정리** :
- Composition 관계는 생성자에 이미 데이터에 값을 다 설정 해놓고 사용한다.
- Aggregation은 필요할 때마다 set과 get을 통해서 값을 저장하여 사용한다.
- Associaion은 객체를 각각 만들어주고 서로 연결해주는 과정이 있다.
2) [Injection의 의미]
-
Setter Injection : Association에서 사용, set을 이용하는 경우
-
Construction Injection : 생성자를 통해서 결합하는 경우
-
DI(Dependency Injection = 의존성 주입) : “부품을 결합한다.”는 의미이다.
-
Is A 상속 : 틀을 만들어 놓고 가져다가 사용. 이러한 틀을 “framework” 라고 부른다.
3) [재사용의 의미]
-
재사용의 의미 : 배포되어서 바이너리 파일을 가지고 소스코드를 얻는것이다.
-
재사용은 기존의 코드를 건드리면 안된다.
4) [상속의 개념]
- 상속을 관계해주는 방법, 첫번째 방법 : extends 이용
package ex7.is_a;
public class NewlecExam extends Exam { // 이부분
private int com;
}
- Exam은 부모클래스, NewlecExam은 자식클래스
- 상속을 관계해주는 방법, 두번째 방법 : Exam exam 이용
- 2가지 방식을 같이 쓰진 못한다.
package ex7.is_a;
public class NewlecExam {
private Exam exam; // 이부분
private int com;
}
5) [super의 개념]
- super() : 부모의 틀을 가져온다.(부모의 생성자를 가져온다.), super도 집중화 가능(재사용이랑 의미는 다르다.)
6) [Override의 개념]
package ex7.is_a;
public class NewlecExam extends Exam {
private int com;
public NewlecExam() {
//setKor = 1;
super();
this.com = 0;
}
public NewlecExam(int kor, int eng, int math, int com) {
//setKor = 1;
super(kor, eng, math); // 부모의 생성자를 받아오는 경우
this.com = com;
}
@Override // 부모가 갖고 있는 메서드를 Override 방식으로 수정했다.(덮어 씌움)
public int total() {
return super.total() + com;
}
@Override
public double avg() { // 틀을 만드는 것은 생성자를 쓰거나 Override를 통해 고쳐쓴다.
//return super.avg()*3/total();
return total()/4.0;
}
}
7) [객체와 참조 형식의 개수의 개념]
Exam exam = new Exam(); // 가능.
NewlecExam exam = new NewlecExam(); // 가능.
NewlecExam exam = new Exam(); // 불가능.
Exam exam = new NewlecExam(); // 가능. NewlecExam은 자식이라서 부모 범위로 포함해서 더 큰 범위로 생성된다. 더 큰 범위(NewlecExam)에서는 작은 범위인 Exam을 사용할 수 있다.
// new로 객체가 만들어지기 때문이다.
8) [객체와 참조 형식의 개수의 개념]
- 부모에 메서드가 없다면 오버라이드 메서드를 호출할 수 없다.
8) [객체와 참조 형식의 개수의 개념]
-
자식 메서드인 Override가 우선시 된다.
-
Framework도 만들어지는 과정이 이것과 같다. 내가 만든 프로그래밍 순서를 거쳐서 원래 프로그래밍 순서로 되돌아간다. 하지만, 되돌아가는 것은 순회하는 느낌으로 돌아가는 것이며 되돌아가는 것도 내가 선언을 따로 해줘야 한다.
package ex7.is_a;
public class InheritanceTest {
public static void main(String[] args) {
NewlecExam exam1 = new NewlecExam(1,1,1,1);
System.out.println(exam1.total());
System.out.println(exam1.avg());
Exam exam2 = new NewlecExam(1,1,1,1);
System.out.println(exam2.total());
// Exam exam3 = new Exam(1,1,1);
// System.out.println(exam3.total());
}
}
package ex7.is_a;
public class NewlecExam extends Exam {
private int com;
public NewlecExam() {
//setKor = 1;
super(); // 초기화 부분이라서 이런식으로 아무 값 없이 가져온다.
this.com = 0;
}
public NewlecExam(int kor, int eng, int math, int com) {
//setKor = 1;
super(kor, eng, math); // 부모의 생성자를 받아오는 경우, 기존의 입력값을 가져오는 것이므로 변수명으로 받아온다.
this.com = com;
}
@Override // 부모가 갖고 있는 메서드를 Override 방식으로 수정했다.(덮어 씌움)
public int total() {
return super.total() + com;
}
@Override
public double avg() { // 틀을 만드는 것은 생성자를 쓰거나 Override를 통해 고쳐쓴다.
//return super.avg()*3/total();
return total()/4.0;
}
}
package ex7.is_a;
public class Exam {
//private Subject subject; // Subject를 추가해줘도 구조는 바뀌지만 구성은 바뀌지 않는다.(중요!! exam : subject.exam.kor)
// 데이터 구조를 숨겨주는 역할을 해주는 것이 getter와 setter이다.(구성은 같다.)
private int kor; // 외부 파일의 접근을 위해서 private는 사용할 수 없다.
private int eng;
private int math;
public Exam() { // 이클립스에서는 생성자를 안 만들어주어도
// 기본적으로 0으로 세팅되는 생성자를 만들어준다.
// kor = 0;
// eng = 0;
// math = 0;
//Exam(0,0,0); // 중요!! 생성자는 이름이 없기 때문에 호출될 방법이 없구나. 그래서 this(0,0,0)로 호출한다.
this(0,0,0); // this(0,0,0); 는 객체가 단 한번도 실행되기 전에 실행되어야 한다.
} // kor = 0;를 먼저 생성했으면 에러가 발생해버린다.
public Exam(int kor, int eng, int math) { // 오버로드 생성자 이다. 오버로드 생성자는 기본적으로
this.kor = kor; // 이클립스가 생성자에 의해서 0.0.0이 입력된다..
this.eng = eng; // 밑의 print() 오버로드 함수와 같은 역할이다.(기본값 setting)
this.math = math; // main함수에서 사용자가 임의의 값(Exam exam1 = new Exam(1,2,3))으로 설정해줄 수도 있다.
}
public double avg() {
return total() / 3.0;
}
public int total() {
return kor + eng + math;
}
public void setKor(int kor) { // 데이터 구조를 숨겨주는 역할을 해주는 것이 getter와 setter이다.(구성은 같다.)
this.kor = kor; // this는 객체를 대신 써주는 것
}
public void setEng(int eng) { // getter와 setter는 자동적으로 만들수 있다.
this.eng = eng;
}
public void setMath(int math) {
this.math = math;
}
public int getKor() {
return kor;
}
public int getEng() {
return eng;
}
public int getMath() {
return math;
}
}
package ex7.is_a;
import java.util.Scanner;
public class ExamConsole {
private Exam exam; // 이 구문을 통해 결합이 되는 것이다.
// 여기서 exam은 단순히 참조명이 아니라 이 console의 부품명이 된다.
// 분리가 되면 한쪽은 부품이 되고 다른쪽은 제품이 된다.
// Exam에서는 그냥 사용하고
// ExamConsole에서는 Exam 객체의 exam을 구성하는 관계가 존재한다.(Composition Has A 관계로 사용하고 있다. = 부품이나 멤버(this)를 가지고 있다.).
// main 함수에서는 member가 아니라 그냥 쓴다. 구성하는 관계가 아니다.(Has A 관계)
// Composition Has A 관계 : 객체를 a로 관계를 갖고 있다. 객체를 갖고는 있는데 각자 꽂아야하고 부품들을 무조건 생성해야한다.
// 부품들을 생성만하고 끝날 수도 있다. "일체형 관계"이다. 즉, "완성품"이다.
// 부품이 그 안에 있는지도 모르는 관계
// Association Has A 관계 : 우리 코드를 따로 결합해주어야 한다. 핸드폰과 부품을 결합해주는 관계. 분리형 관계
// Aggregation Has A 관계 :
// *** 데이터 구조를 유연하게 하기위해서 데이터 속성의 값을 노출해도 되지만 데이터 구조를 노출하면 안된다.
public ExamConsole() {
exam = new Exam(); // 콘솔에서는 부품을 자기가 직접 만들어서 자급자족한다. 이것이 Composition Has A 관계이다.
// 즉, 데이터를 통으로 넘겨주는 격이다.
} // 오전의 문제 푼 것에서 배열에서 생성자의 메모리 할당 생성자와 같다.
// Composition Has A은 부품을 바꿔낄 수 없고 Association Has A는 부품을 바꿔낄 수 있다.
// 따라서, Association Has A는 유연한 코드이다.
public void input() {
Scanner scan = new Scanner(System.in);
System.out.println("┌──────────────┐");
System.out.println("│ 성적 입력 │");
System.out.println("└──────────────┘");
int kor, eng, math;
do {
System.out.print("kor : ");
kor = scan.nextInt();
if(kor < 0 || kor > 100)
System.out.println("kor은 0~100 의 값을 입력해주세요.");
} while (kor < 0 || kor > 100);
// 이것이 Association Has A 관계
exam.setKor(kor); // this.exam.setKor는 국어 성적을 setting 해주는 역할이며 이것을 간단히 exam.setKor(kor)라고 사용하며 setter 메서드라고 부른다.
do {
System.out.print("eng : ");
eng = scan.nextInt();
if(eng < 0 || eng > 100)
System.out.println("eng은 0~100 의 값을 입력해주세요.");
} while (eng < 0 || eng > 100);
exam.setEng(eng); // this.exam.setEng는 영어 성적을 setting 해주는 역할이며 이것을 exam.setEng(eng)라고 사용하며 setter 메서드라고 부른다.
do {
System.out.print("math : ");
math = scan.nextInt();
if(math < 0 || math > 100)
System.out.println("math은 0~100 의 값을 입력해주세요.");
} while (math < 0 || math > 100);
exam.setMath(math); // this.exam.setMath는 수학 성적을 setting 해주는 역할이며 이것을 exam.setMath(math)라고 사용하며 setter 메서드라고 부른다.
}
public void print() { // 오버로드 메서드는 구현된 메서드에게 넘겨준다.
print('-',30);
}
public void print(char c) {
print(c,30);
}
public void print(char c, int length) {
int total = exam.total(); // total과 avg를 출력 이외에도 사용하기 위해서 메서드로 만들기
double avg = exam.avg();
// System.out.printf("kor: %d\n", exam.getKor());
// System.out.printf("eng: %d\n", exam.getEng());
// System.out.printf("math: %d\n", exam.getMath());
System.out.printf("kor: %d\n", exam.getKor());
System.out.printf("eng: %d\n", exam.getEng());
System.out.printf("math: %d\n", exam.getMath());
for(int i = 0; i<length; i++)
System.out.printf("%c", c);
}
}
4. 객체 지향 4 : 22.12.22
1) 이전 강의의 객체지향
-
구조화 : 수납공간을 어떻게 만들건지 고민하는 것(객체지향)
-
행위도 넣어주고 행위의 주체도 넣어 주어야 한다.
-
남이 만든 프레임워크를 가져다가 사용한다.
-
일반적으로 초급 개발자는 UI를 만드는 일을 많이 한다. 객체 설계를 하지 않는다. 데이터 설계를 위한 이해가 필요하다. 전체 시스템에 대한 이해가 필요하다.
-
배운 기술(스프링 부트)을 사용할 수 있어야 하고 사수의 유무가 아니라 책임의 유무이다. 사수는 가르쳐 주지 않는다.
-
연봉보다 신입을 빨리 없애고 회사에서는 어울릴 수 있는 사람인가가 중요하다. 실력은 중요하지 않다. 인성이 중요하다. 오만함을 없애라.
-
궁하지 않을 때, 면접을 많이 봐라. 자신감이 아직 있을 때, 편하게 면접 볼 수 있다. 주눅 들지않고
2) Is_A 상속 설명 : 기존의 프레임워크를 이용하는 방법
-
기존의 프레임워크를 통해 extends로 상속받을 때, 커스터마이징을 할 수 있도록 해야 한다.
-
ex) 그림 그리는 로직을 내가 Override를 통해 로직을 바꿀 수 있다.(paint 메서드)
-
점차 브라우저에서 모든 것을 해결하려고 한다. 브라우저에서 인스톨하려고 한다.
-
앞으로는 서블릿 클래스, html 이용
3) 다형성
-
다형성 : 캡슐을 분리해서 만들고 결합력을 느슨하게 만든다. 인터페이스와 관련 있는 내용
-
아직 다형성은 개념 이해가 안 가서 간단히 게임 개발하고나서 나중에 다시 공부하자. 앞으로는 서블릿 공부, 백엔드, 프론트 엔드 개발 공부할 것임.
5. 자바 웹 개발 시작 (Servlet, Tomcat) : 22.12.22
-
입/출력 도구가 이제부터 달라진다. 기존의 콘솔, 파일에서 웹이 추가된다.
-
서블릿 – JSP – JSP MVC – Spring MVC 순서로 진행되었다.
-
이전에는 서블릿이 중요했지만 앞으로는 중요한 기술들이 바뀌어서 이러한 내용들은 빠르게 훑고 Spring까지 배워야 한다.
1) [강의 진행 방향]
-
미니프로젝트 : Servlet, Json, JS 맛보기
-
1차 프로젝트 스프링부트, Thymeleaf(JSP 안 쓰고) 이용
-
2차 프로젝트 : 프론트 엔드(vue js 이용)
2) [Servlet] 시작
3) [인터넷 vs 웹]
- 인터넷 : ex) “도로”와 같은 통로를 의미한다.
- 웹 : www 형식으로 문서를 서비스하기 위한 시스템이다. (ex) 배달을 해주는 시스템)
4) [인터넷 등장 배경]
- LAN : local area network (전세계적으로 공유할 수 있는 공간이 생김.)
- 이러한 network끼리 물리적인 장치를 연결시켜주는 것이 “inter network”라고 부름
- 게이트웨이 : network가 서로 나갈 때, 갈아타기 위한 장소.
- 이렇게 internet이 만들어짐.(지나다니는 통로) 이제는 배달시켜주는 것이 필요하다.
5) [서버 vs 클라이언트]
- 한쪽은 서버가 되고 다른 한쪽은 클라이언트가 된다.
-
서버 : 핫 스왑의 개념,
- 클라이언트 : 파일을 전송하기 위해서 일련의 약속이 필요하다.
- 이러한 약속을 프로토콜(FTP)이라고 부른다.
- HTTP(하이퍼텍스트로 파일을 보내줌), SMTP(메일링으로 파일을 보내줌)
- 이제는 웹으로 도로가 되는 역할이 된다. 하지만, 웹은 문서를 전달하는 시스템에 불과하다.
-
6) [웹 프로그래밍 VS 자바 프로그래밍]
- IP : inter network에서 다른 network로 전송할 때, 식별되는 번호이다.
- 192.168.0.1
- MAC address : 웹에서는 LAN Port Address(랜카드)에 의해 식변된다.(Media Access Control Address를 구별해주기 위해서 MAC address를 붙여준다.)
- MAC주소를 보고 통신해야 할 포트를 지정해 내보낼 수 있다.
- MAC Address를 이용하여 구별해줘서 우리는 송신할 수 있다.
- 192.168.0.1에서 1은 host 번호이고 1에 의해서 MAC Address가 정해진다.
-
Broad casting : 그래서, MAC address가 너무 많아서 그에 맞는 Media Access를 찾기 위해서 방송 같은 것을 한다. Network 환경 설정에서 32번으로 설정되어 있으면 이것이 Host 번호이다.
- Port : 아직은 밖에 있는 데이터가 컴퓨터까지만 와서 추가적으로 데이터가 있는데 이것이 port라고 부르며 이것은 사서함과 같다.
- http에서 8080이라는 포트번호를 사용에서 포트번호는 각 역할을 부여해준다.
-
정리** : 데이터가 올 때는, 웹에서 IP로 오지만 Port 번호가 있어서 사서함에 데이터를 전해준다. IP는 문턱까지, MAC address는 디테일까지, Port는 각 역할까지(MAC주소를 보고 통신해야 할 포트를 지정해 내보낼 수 있다. )
-
네트워크 소켓 : 네트워크 데이터를 연결해주는 IP Address, Port의 정보를 갖고 데이터를 주고 받는다.
-
API : 사서함의 데이터를 꺼내 쓰고 네트워크로 수거해가는 것이다.(send, receive)
- RPC(Remote Procedure Call) : 아래 한글 처럼 업데이트할 때, 항상 지웠다가 다시 설치해야 한다. 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 리모트의 함수나 프로시저를 실행 할 수 있게 해주는 프로세스간 통신입니다. 즉, 위치에 상관없이 RPC를 통해 개발자는 위치에 상관없이 원하는 함수를 사용
6) [웹이란?]
- 이제는 웹을 브라우저를 통해 동적으로 만들어 준다.
- 백엔드 개발 : 서버에서 코드를 이용해서 문서를 만들고(문서화) 이러한 문서는 클라이언트에서 요청이 있을 때마다 문서를 전달해준다.(동적 개발)
- 프론트 개발 : 클라이언트 프로그램을 만들지 않지만 요즘에는 프론트 개발쪽에서 데이터를 직접 사용하므로 살아났다.
7) [WAS의 개념]
- “server app” : 문서화 하기 위해 코드를 모아두는 공간이다.
- “Web server” : 서버를 실행해주는 실행환경 그자체이다.
- “WAS” : 그것에 대한 코드를 실행하여 그 결과를 돌려주는 서버라고 한다. WAS는 서버의 타입명이다. 그 중에서 제품명은 “Tomcat”이 있다.
- apache는 돌아가 해주는 범용도구이다. 예를 들어, tomcat, php 등이 있다.
8) [Tomcat의 개념]
-
Tomcat을 실행하기 위해서 Tomcat은 java를 이용하므로 “JAVA_HOME”이라는 환경 변수를 추가로 설정해야 한다.
-
apcahe.org 홈페이지에서 Tomcat을 설치하면 설치 파일의 bin 폴더의 startup.bat 파일이 있다. 해당 파일을 키면, 브라우저와 클라이언트를 연결할 수 있다. 즉, startup.bat 파일은 서버와 같은 역할을 한다.
-
D:\Setup\apache-tomcat-10.0.27\webapps\ROOT 경로의 폴더에서 만들어지는 파일은 브라우저에서 사용되며 표시된다.
- 따라서, ROOT 폴더에서 nana.txt를 만들고나서 http://localhost:8080/nana.txt의 url로 브라우저 이동하면, txt 파일의 내용을 브라우저에서 출력하여 서비스할 수 있다.
5. 톰캣, 서블릿 : 22.12.23
0) [들어가기 전]
-
참조는 사용하기 위한 참조형을 정하는 것이 좋다.
-
자식은 확장하는 기능도 있고 확장하는 기능이 아니라 부모의 수준에서 사용하고 싶으면,
-
자식 이름을 쓰게되면 참조하는 영역이 줄어든다.
-
Frame(부모)이 아니라 GameFrame(자식)으로 이름으로 쓰면 사용하는 기능이 줄어들어서 사용하게 된다. 굳이, GameFrame(Override된 형태만)이라고 범위를 한정시킬 필요는 없다.
-
그래서 Frame를 사용한다.
1) [네트워크 기본 강의] : 추가로 공부하기(성공과 실패를 결정하는 1% 의 네트워크 원리)
-
웹은 기본적으로 port 번호를 80으로 이용해서 톰캣의 포트번호를 8080으로 설정하기. 따라서, http에서 port 번호 80을 입력하면 생략된다.(server.xml에서 변경 가능)
-
http의 port는 80번으로 default port이므로 묵시적으로 입력된다.
-
Tomcat은 “index.html”, “index.jsp”, “index.htm”의 순서로 다음의 파일이 없으면 404 에러가 발생한다.
- 네트워크 연결 방법
-
1) 구리선 이용
- 2) LAN 이용 : 공유선(전기선)이 가운데 존재하고 가지로 가지를 친다. 네트워크가 더 줄어들게 된다. ex) 버스형, 링형, 스타형(효율적인다, 스위치를 이용하므로) 등등
- 요즘에는 허브로 공유기를 사용한다. 버스형이라고도 부른다.
- 3) 공중파 이용 : 와이파이
-
-
스니핑 개념 : 보안 관련된 내용
- 네트워크 네이밍 : 도메인이라고 부른다.
- 예전에는 C:\Windows\System32\drivers\etc 경로에서 hosts 파일에 ip와 DNS를 적으면 그게 도메인으로 적용되어서 DNS를 조작할 수 있다.(호스트 파일 조작 방식)
- 하지만, 요즘에는 윈도우 업데이트로 불가
- 도메인은 보통 요청하면, 원격의 도메인에서 DB에서 찾지 않고 일일이 찾아준다.
2) [Context 사이트의 이해]
- Context 사이트 추가 : 문맥을 이어주는 역할, 밖에서 보면 하위 디렉토리 처럼 보이게 해준다.
-
server.xml에서 수정(오타 주의) :
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="" privilleged="true"/>
-
- 하지만, 요즘에는 Context를 도메인 앞으로 쓰게 바뀌어 가고있다. 그렇지만 우리는 Context로 만든다.
3) [Servlet의 개념]
-
Server + let : 서버 어플리케이션의 조각
-
앞으로 어플리케이션은 조각(Servlet)들을 모아서 만들게 된다.
-
서블릿을 이용하기 위한 툴은 톰캣이 만든 프레임워크이다.
-
Tomcat 10 버전부터 패키지명이 자카르타(jakarta)로 달라졌다.(Tomcat 9 이전의 버전은 패키지가 javax로 동일하다.)
-
WEB-INF : WEB ROOT를 의미한다. WEB-INF 폴더의 파일은 사용자가 요청해도 접근할 수 없다.
-
WAS : 코드를 실행하여 그 결과를 돌려주는 서버
-
Web Server : Tomcat이라는 웹 서버 기능, 서버가 맞는지 판단 기능이 필요하다.
4) [Servlet의 실행 방법]
- “Tomcat”에게 일하라고 요청해주는 역할을 web.xml파일에서 설정해준다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="5.0">
<display-name>webprj</display-name>
<servlet> <!-- 메모리에 올리고 객체화한다. 객체화하고 이름을 달아줘야하는데 이것이 servlet-name이다. -->
<servlet-name>nana</servlet-name>
<servlet-class>com.newlecture.Nana</servlet-class>
</servlet>
<servlet-mapping> <!-- url-parrtern이다. 오타 주의!! -->
<servlet-name>nana</servlet-name>
<url-pattern>/hello.txt</url-pattern>
</servlet-mapping>
- HttpServlet로부터 상속받아서 service 메서드를 구성한다.(HttpServletRequest와 HttpServletResponse를 인자로 받기 때문에 서블릿으로 브라우저와 송수신해준다.)
package com.newlecture;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.*;
public class Nana extends HttpServlet
{
public void service(HttpServletRequest request
, HttpServletResponse response)
throws IOException, ServletException
{
for(int i =0; i<10; i++)
System.out.println("hello Servlet");
}
}
- http://localhost/news/hello.txt 이동하면, 브라우저에서는 흰 화면이 나오지만, server.bat의 콘솔에서 출력된다.