| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- #패스트캠퍼스 #국비지원교육 #메가바이트스쿨 #MegabyteSchool #개발자취업부트캠프 #내일배움카드
- group study
- Algorism study
- github
- #javaStudy
- MVC
- View
- 메가바이트스쿨
- 개발자취업부트캠프
- crud
- side project
- array
- 내일배움카드
- 패스트캠퍼스
- Interface
- 게시판 리뷰 만들기
- spring boot
- Spring
- MegabyteSchool
- 게시판 만들기
- GIT
- 국비지원교육
- Sts
- 클래스 상속
- Java
- MVC 패턴
- Entity
- AWS
- 클래스 class
- tomcat
- Today
- Total
tuter77
2023.01.09 TIL 본문
<목차>
<공부계획표>
13:00 ~ 14:00 그룹스터디 과제
엔티티 Review 만들고 연관관계 설정하기
14:00 ~ 18:00 (3시간) 온라인강의 시청.
14:00 ~ 15:00 java 강의 시청
15:00 ~ 16:00 Spring 강의 시청
17:00 ~ 18:00 Spring 강의 시청
18:00 ~ 19:00 식사시간
19:00 ~ 22:00 java 실시간 강의
19:00 ~ 20:00 java 강의 시청
20:00 ~ 21:00 java 강의 시청
21:00 ~ 22:00 java 강의 시청
22:00 ~ 23:00 블로그 작성 및 프로그래머스 문제 풀기.
<Java>
● 추상 클래스(abstract class) 구현하기
▷추상 클래스
- 구현 코드 없이 메서드의 선언만 있는 추상 메서드를 포함한 클래스이다.
- 메서드 선언 : 반환타입, 메서드 이름, 매개변수로 구성한다.
- 메서드 정의 : 메서드 구현과 동일한 의미 구현부를 가진다.
- 예시)
int add(int x, int y);
int add(int x, int y){}
위 처럼 구현부가 있으면 추상 메서드가 아니다.
- abstract 예약어를 사용하며, 추상클래스는 new 할 수 없다.(인스턴스화 할 수 없다.)
▷추상클래스 구현하기
- 메서드에 구현코드가 없으면 abstract로 선언한다.
- abstract로 선언한 메서드를 가진 클래슨느 abstract로 선언한다.
- 모든 메서드가 구현 된 클래스라도 abstract로 선언되면 추상클래스로 인스턴스화 할 수 없다.
- 추상 클래스의 추상 메서드는 하위 클래스가 상속하여 구현하는데, 추상 클래스 내의 추상 메서드는 하위 클래스가 구현해야하는 메서드이고, 추상 클래스 내에 구현된 메서드는 하위클래스가 공통으로 사용하는 메서드이다.
- 필요에 따라 하위클래스에서 재정의한다.
예제)
상위 클래스인 컴퓨터 클래스를 두고 하위 클래스에서 각 기능들을 구현하는 예제.
public abstract class Computer {
public abstract void display();
public abstract void typing();
public void turnOn() {
System.out.println("전원을 켭니다.");
}
public void turnOff() {
System.out.println("전원을 끕니다.");
}
}
추상클래스는 위와 같이 abstract 키워드를 사용하여 선언하는데 아래에 display(), typing() 메서드는 하위 클래스에서 구현되어야 한다.또한 그 아래의 turnOn(), turnOff() 메서드는 구현되어 하위클래스가 공통으로 사용되는 메서드이다.
public class Desktop extends Computer{
@Override
public void display() {
System.out.println("Desktop display");
}
@Override
public void typing() {
System.out.println("Desktop typing");
}
@Override
public void turnOff() {
System.out.println("Desktop turn off");
}
}
첫 번째 하위클래스인 Desktop 에서 Computer 클래스를 상속하면, 추상클래스의 메서드를 구현하라고 표시가 뜬다. 이를 클릭하면 오버라이드 어노테이션과 함께 구현되지않은 메서드들이 나타나는데 여기서 하위클래스에 맞게, 구현한다.
public abstract class NoteBook extends Computer{
@Override
public void display() {
System.out.println("Notebook display");
}
// @Override
// public void typing() {
// System.out.println("Notebook typing");
// }
}
두 번 째 하위클래스인 NoteBook 클래스는 똑같이 Computer 클래스를 상속받았지만, 구현해야하는 메서드 하나를 구현하지 않고 똑같이 추상클래스로 선언했다.
이는 아래의 NoteBook 의 하위클래스에서 구현했다.
public class MyNoteBook extends NoteBook {
@Override
public void typing() {
System.out.println("MyNoteBook typing");
}
}
컴퓨터의 하위클래스 노트북, 그 노트북의 하위클래스인 MyNoteBook클래스에서 구현되지 않았던 남은 메서드를 구현하고 Test 했다.
public class ComputerTest {
public static void main(String[] args) {
Computer desktop = new Desktop();
desktop.display();
desktop.typing();
desktop.turnOn();
desktop.typing();
Computer myNoteBook = new MyNoteBook();
myNoteBook.display();
myNoteBook.typing();
myNoteBook.turnOn();
myNoteBook.typing();
}
}
아래는 결과이다.

재정의된 기능들과 공통으로 사용하는 기능들이 잘 작동하는 것을 확인할 수 있다.
● 추상 클래스(abstract class)의 응용 - 템플릿 메서드 패턴.
▷템플릿 메서드
- 추상 메서드나 구현된 메서드를 활용하여 코드의 흐름(시나리오)를 정의하는 메서드이다.- final 로 선언하여 하위 클래스에서 상속하거나 재정의 할 수 없게 하는데, Frame Work에서 많이 사용되는 설계 패턴이다.- 추상 클래스로 선언된 상위 클래스에서 템플릿 메서드를 활용하여 전체적인 흐름을 정의하고 하위클래스에서 다르게 구현되어야 하는 부분은 추상메서드로 선언하여 하위클래스에서 구현하도록 한다.
- 예시)
앞의 Desktop 예시와 거의 유사하게 Car 추상 클래스와 하위클래스들을 구현한다. 단, 시나리오를 가진 메서드는 final로 선언한다.

public abstract class Car {
public abstract void drive();
public abstract void stop();
public abstract void wiper();
public void startCar() {
System.out.println("시동을 켭니다.");
}
public void turnOff() {
System.out.println("시동을 끕니다.");
}
public void washCar() {} //구현부는 있으나 구현내용이 없는것. 때문에 오류가 안난다.
//필요한 경우에 재정의를 하면된다. 추상 메소드가 아닌, 구현된 메소드.
final public void run() {
startCar();
drive();
wiper();
stop();
turnOff();
washCar();
}
}
위의 코드에서 보면 추상 메서드로 3개가 선언되었고, 가장 아래에 있는 run() 메서드가 시나리오(흐름)을 가진 메서드이므로 final로 선언되어 재정의할 수 없게끔 되어있다.
run() 메서드 위의 washCar() 메서드는 구현부가 있지만 내용이 없는 것으로 추상메서드가 아닌, 구현된 메서드이다.
보통 하위클래스에서 재정의해서 사용해야할 때 쓴다고 한다.
public class AICar extends Car{
@Override
public void drive() {
System.out.println("자율 주행을 합니다.");
System.out.println("자동차가 스스로 방향을 바꿉니다.");
}
@Override
public void stop() {
System.out.println("장애물 앞에서 스스로 멈춥니다.");
}
@Override
public void wiper() {
System.out.println("비가오면 스스로 와이퍼를 작동합니다.");
}
@Override
public void washCar() {
System.out.println("자동 세차를 합니다.");
}
}
AICar 클래스에서 추상 메서드를 포함해 필요한 메서드들을 모두 구현했다.
public class ManualCar extends Car{
@Override
public void drive() {
System.out.println("사람이 운전합니다.");
System.out.println("사람이 핸들을 조작합니다.");
}
@Override
public void stop() {
System.out.println("장애물 앞에서 브레이크를 밟아서 정지합니다.");
}
@Override
public void wiper() {
System.out.println("비가 와서 사람이 와이퍼를 작동합니다.");
}
}
마찬가지로 ManualCar 클래스에서도 메서드가 구현되어있다.
public class CarTest {
public static void main(String[] args) {
Car aiCar = new AICar();
aiCar.run();
System.out.println("======================");
Car manualCar = new ManualCar();
manualCar.run();
}
}
이를 실행해보면 아래와 같은 결과가 나온다.

위는 AICar이고 아래는 ManualCar인데, 각자 오버라이딩된 메서드들이 run이라는 상위 클래스의 메서드로 실행된 것이다.
▷ final 예약어
- final 변수는 값이 변경될 수 없는 상수이다.
public static final double Pi = 3.14;
- final 메서드는 하위 클래스에서 재정의 할 수 없는 메서드이다.
- final 클래스는 상속할 수 없는 클래스이다.
● 인터페이스(interface)
- 모든 메서드가 추상 메서드로 선언되어있다.(public abstract)
- 모든 변수는 상수로 선언된다.(public static final)
- 예시)
interface 인터페이스 이름{
public static final float pi = 3.14f;
public void makeSonthing();
}
- 자바 8 부터 Default method와 static method 기능의 제공으로 일부 구현코드가 있다.
예시)

public interface Calc {
double Pi = 3.14;
int ERROR = -99999999;
int add(int num1, int num2);
int substarct(int num1, int num2);
int times(int num1, int num2);
int divide(int num1, int num2);
}
Class가 아닌 Interface로 선언되어있으며, 각 변수는 고정된 값인 상수, 메서드는 구현코드가 없는 형태로 선언된다.
public abstract class Calculator implements Calc{
@Override
public int add(int num1, int num2) {
return num1 + num2;
}
@Override
public int substarct(int num1, int num2) {
return num1 - num2;
}
}
Calc 인터페이스를 implements 키워드를 사용하여 받아오고 구현해야하는 메서드 중 2가지만 구현한 뒤 추상 클래스로 선언하여, 남은 메서드는 하위클래스에 구현을 맡긴다.
public class CompleteCalc extends Calculator {
@Override
public int times(int num1, int num2) {
return num1 * num2;
}
@Override
public int divide(int num1, int num2) {
if(num2 == 0)
return ERROR;
return num1/num2;
}
public void showInfo() {
System.out.println("모두 구현했습니다.");
}
}
추상클래스를 상속받아 남은 두 가지의 메서드를 구현하고 하위클래스 고유의 메서드인 showInfo() 메서드도 구현했다.나누기(divide) 메서드에선 분모가 0일경우 에러가 뜨기 때문에 인터페이스에서 선언한 에러변수를 반환하게 해준다.
▷ 인터페이스 구현과 형 변환
- 인터페이스를 구현한 클래슨느 인터페이스 형으로 선언한 변수로 형 변환 할 수 있다.- 상속에서의 형 변환과 동일한 의미이며, 클래스 상속과 달리 구현코드가 없으므로 여러 인터페이스를 구현할 수 있다.- 형 변환되는 경우 인터페이스에 선언된 메서드만 사용가능하다. (위의 예시에서 showInfo()는 사용불가한 점.)
▷ 인터페이스는 왜 사용하는지.
- 인터페이스가 하는 일
1. 클래스나 프로그램이 제공하는 기능을 명시적으로 선언한다.
2. 일종의 클라이언트 코드와의 약속이며, 클래스나 프로그램이 제공하는 명세(specification)이다.
3. 클라이언트 프로그램은 인터페이스에 선언된 메서드의 명세만 보고 이를 구현한 클래스를 사용할 수 있다.

4. 어떤 객체가 하나의 인터페이스 타입이라는 것은 그 인터페이스가 제공하는 모든 메서드를 구현했다는 의미이다.
5. 인터페이스를 구현한 다양한 객체를 사용한다.(다형성)
예시) JDBC 인터페이스
다음 강의에서 인터페이스의 역할, 다형성, 요소, 구현 및 상속에 대해 다룰 예정이다.
<Spring>
● 클라이언트와 서버
▷톰캣 설정파일 (server.xml, web.xml)
- server.xml : tomcat 서버 설정 파일
- 톰캣설치경로/conf/web.xml : 톰캣의 모든 web app의 공통설정(톰캣이 먼저하는 것.)
- 웹앱이름/WEB-INF/web.xml : web app의 개별설정(그 다음으로 하는 것)
- Server.xml 파일을 STS로 보면 Server안에 Service > Conect순으로 확인할 수 있다. 그 conector안에서 포트를 8080에서 80으로 바꾸면 80포트를 쓸 수 있다.그 아래 Engine이 있고, 더 내려가면 Host를 확인할 수 있다.
제일 아래에 context를 볼 수 있다.
- web.xml 파일은 server에 하나있고(공통설정) 사용중인 프로젝트의 src > main > webapp > web-inf 안에서 하나를 더 볼 수 있다. 이는 프로젝트 내 개별설정을 하는 파일이다.
이 파일을 살펴 보면

이렇게 서블릿을 등록하는 코드를 볼 수 있다.
원격 프로그램을 등록할 때 1. 서블릿을 먼저 등록하고 2. url연결을 하는데 1번에 해당하는것이다.
이게 여기서 @Controller로 바뀐것이다.(2번은 @RequestMapping 으로 바뀜)
(사실 @Controller와 @RequestMapping은 스프링에서만 사용하고, 서블릿에서는 @WebServlet을 사용한다고한다.)
* 이 web.xml로 설정하던 것들이 애노테이션으로 간단히 설정할 수 있게 바뀐것이라고 한다.

더 내려가면 이렇게 mapping 부분을 확인할 수 있는데, default서블릿을 아래 "/ "주소와 맵핑한 것이다.
- 개별설정 파일로 들어가면, context설정, listener설정 등을 확인할 수있다.

여기서 appServlet이라고 적힌 부분이 아까의 @Controller에 해당한다.
그리고 그 아래 appServlet이 @RequestMapping에 해당한다.
● HTTP 요청과 응답
▷프로토콜
- 서로간의 통신을 위한 약속, 규칙이다.
- 컴퓨터에서는 주고 받을 데이터에 대한 형식을 정의한 것이다.
▷HTTP(Hyper Text Transfer Protocol)
- http는 이 프로토콜의 하나로 텍스트기반의, 텍스트를 전송하기 위한 프로토콜이다.
- 단순하고 읽기 쉬우며, 여기서 하이퍼 텍스트는 html을 의미한다.
- 상태를 유지하지 않는다(stateless) > 클라이언트 정보를 저장하지 않는다.(실제로 같은 클라이언트가 요청을 두 번 보내도 서버는 구분하지 못한다.)때문에 이 부분을 보완하기 위해 쿠키와 세션을 이용한다.
- 확장이 가능하다.(커스텀 헤더 추가 가능)
(헤더 > 헤더이름: 값\n 공백, 대소문자 무시)
예시) 편지와 똑같다. 헤더 - 바디의 구조.
클라이언트에서 url로 요청하면, 브라우저가 HTTP 요청메시지를 자동으로 생성해준다.
http://111.22.33.44:8080/ch2/hello

이 메세지가 서버로 요청되면, 서버는 응답 메세지를 반환한다.

이 내용은 브라우저에서 해석되어 Hello라고 나온다.
▷HTTP 응답메시지
HTTP/1.1 200 OK
Content-Length : 44
Content-Type : text/html
Date : Sat, 20 Oct 2021 19:03:38 GMT
<html>
<head></head>
<body>
Hello
</body>
</html>
첫 줄의 200은 상태코드로 성공을 의미한다.
(300번대는 다른 url을 재요청하라는 것이고, 400(클라이언트에러)-500번대(서버에러)는 에러다. 이 중 404 not found가 가장 유명하다. 그리고 100번대는 정보교환이 목적이다.)
헤더는 몇 줄인지 안나와 있기 때문에 헤더와 바디를 구분하는 빈줄을 넣는다.
바디에는 실제 응답내용이 나와있다.
▷HTTP 요청메시지
이 요청 메시지는 GET과 POST로 구분되어있다.(요청 메서드)
GET/ch2/getYoil?year=2023&month=10&day=1 HTTP/1.1
Host:111.22.33.44:8080
User-Ahent: Mozilla/5.0 (Windows NT 10.0)
Accept : text/html
Connection : keep-alive
POST/ch2/getYoil HTTP/1.1
Host:111.22.33.44:8080
User-Ahent: Mozilla/5.0 (Windows NT 10.0)
Accept : text/html
Connection : keep-alive
year=2023&month=10&day=1
위는 GET(READ)과 POST(WRITE) 메서드의 예시이다.
첫 줄은 요청라인이고, 두번째줄은 헤더 이후 빈줄이나오고 바디가 나온다.
Get은 리소스를 얻어오기 위한 요청이라 바디가 없다.
쿼리스트링을 통해 데이터를 전달하고 소용량이다.
url에 데이터가 노출되어있지만 전달에는 유리하다.
반면 Post는 바디가 있다.
데이터를 요청 메세지의 바디에 담아 전송한다.
그냥 보안에 유리한 것이아니라 HTTP에 TLS(암호화) 방식이 적용되어야 보안에 유리하다.
이는 HTTPS로 나타낸다.

위 표를 참조해 이해할 수 있다.
get요청의경우 우클릭 > 검사 > network > ctrl R(새로고침) 으로 요청한 헤더를 볼 수있다.
post는 Post man 크롬 확장프로그램을 크롬에 추가하여 필요한 사이트의 url만 복사해서Post방식으로 입력하면 볼 수 있다.
preview를 누르면 해당 메세지를 볼 수 있다.
<Group Study>
● Review 엔티티 만들기
▷ HealthInfo 엔티티
@Id
@Column(name = "healthInfo_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// ..
@Builder.Default
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "healthInfo")
private List<Review> reviews = new ArrayList<>();
public void addReview(Review review, String title, String contents){
reviews.add(review);
review.setTitle(title);
review.setContents(contents);
}
먼저 일대다의 관계가 될, 기존의 healthInfo 엔티티에는 위와 같이 id값을 PK로 지정하고 column 어노테이션과 이름을 달아 Review 엔티티에서 참조할 수 있게 했다.
그리고 아래에, @Builder.Default 어노테이션은 초기화에 사용하기위해 넣었는데, 초기화 값을 정하지도 못하고 명확히 이해하지 못해서 일단 두었다.
그리고 연관관계 설정을 위한 Onetomany 어노테이션을 통해 Review 엔티티와 일대다의 관계를 맺었다.
괄호 안의 옵션은 n+1문제를 위해 로딩방식을 lazy로 설정하고, 엔티티의 상태 변화를 전이하기 위해(영속성 관리) cascade.all을 넣었다.
이어 mappedBy옵션으로 Review에 생성될 healthInfo라는 변수가 관계의 주인임을 표기했다.
아래 List 구문은 Review 를 리스트로 받게끔 선언한 내용이다.
addReview 메서드는 아직 사용하진 않았는데, 후에 Review를 작성하면 타이틀과 set 메서드를 이용해 내용을 추가해서
review 리스트에 더해주는 내용이다. 매개변수로 위 3가지를 받고있다.
▷ Review 엔티티
@Entity
@Getter
@Setter
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String contents;
@ManyToOne
@JoinColumn(name = "healthInfo_id")
private HealthInfo healthInfo;
}
Review 엔티티는 healthInfo 엔티티와 다대일의 관계를 맺는 연관관계의 주인으로 만들었다.
데이터가 각 헬스장의 정보이므로, 헬스장에 대한 리뷰가 여러개 달릴 수 있다는 의미이다.
id는 기본값으로 가지고 title과 content를 멤버변수로 가진다. 위에 getter와 setter 어노테이션이 있어 다른 클래스에서 get(), set() 메서드로 값을 받거나 변경할 수 있다.
맨 아래에 Manytoone 어노테이션으로 다대일의 관계임을 선언하고, JoinColumn어노테이션에 앞서 설정한 healthInfo의 id값을 참조 값으로 사용함을 선언했다.
참조 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=sonicheroes1&logNo=220676215649
'TIL' 카테고리의 다른 글
| 2023.01.11 TIL (0) | 2023.01.11 |
|---|---|
| 2023.01.10 TIL (0) | 2023.01.10 |
| 2023.01.06 TIL (0) | 2023.01.06 |
| 2023.01.05 TIL (0) | 2023.01.05 |
| 2023.01.04 TIL (0) | 2023.01.04 |