| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 내일배움카드
- tomcat
- GIT
- 게시판 리뷰 만들기
- Sts
- 개발자취업부트캠프
- 메가바이트스쿨
- 국비지원교육
- Interface
- #패스트캠퍼스 #국비지원교육 #메가바이트스쿨 #MegabyteSchool #개발자취업부트캠프 #내일배움카드
- Java
- Algorism study
- side project
- MVC
- array
- 게시판 만들기
- crud
- 패스트캠퍼스
- group study
- github
- 클래스 상속
- Entity
- MVC 패턴
- spring boot
- AWS
- 클래스 class
- MegabyteSchool
- Spring
- View
- #javaStudy
- Today
- Total
tuter77
2023.01.19 TIL 본문
<목차>
<공부계획표>
13:00 ~ 14:00 Spring 강의 시청
14:00 ~ 18:00 (3시간) 온라인강의 시청.
14:00 ~ 15:00 Spring 강의 시청
15:00 ~ 16:00 Spring 강의 시청
17:00 ~ 18:00 Spring 강의 시청
18:00 ~ 19:00 식사시간
19:00 ~ 22:00 실시간 강의 시청
19:00 ~ 20:00 java 강의 시청
20:00 ~ 21:00 java 강의 시청
21:00 ~ 22:00 java 강의 시청
22:00 ~ 23:00 블로그 작성 및 프로그래머스 문제 풀기.
<Spring>
● HTTP 요청과 응답
▷ Base 64
- 64진법을 의미한다.
- 바이너리 데이터를 텍스트 데이터로 변환할 때 사용한다.
- 64진법은 A~Z :26개, a~z:26개, 0~9:10개 62개에 +, / 까지 64개를 나타낸다.
- 이는 2진수 데이터를 2^6으로 6bit씩 잘라서 변환한것. (예 : 16진수는 2^4로 2진수를 4bit씩 자른다.)
- 남는 것은 Padding 데이터(=)로 채운다.
- 이는 바이너리 데이터를 텍스트 데이터로 변화할때 사용한다.
- 이 6비트로 전달을 하면 서로 다른 OS를 가져도 전달에 문제가 없다는 장점이 있다.
- 다만 안전한 만큼 저장 크기가 늘어나는 단점이있다.
예시) 이미지파일을 base64로 인코딩하기
구글에 base64 encode 검색

이 사이트에서 주사위 이미지를 선택하여, encode 버튼으로 텍스트로 인코딩한다.
해당 base64 기반 텍스트를 html로 저장하여 브라우저에서 확인한다.(VSCode 사용)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img src="data:image/jpeg;base64, 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" alt="">
</body>
</html>
우클릭 > Open in Default Browser

위가 브라우저에서 출력되는 화면이고 해당 소스를 확인해보자.
우클릭 > 페이지 원본보기 > 자동 줄바꿈 선택

이처럼 텍스트를 html파일로 안전하게 전달하면, 링크가 꼬이거하는 일 없이 안전하게 보관할 수 있다고 한다.
뒤는 이전에 공부하던 MVC 패턴의 원리에 대해 공부해보겠다.
● 관심사의 분리 MVC 패턴 - 원리
▷ 예제
package com.fastcampus.ch2;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.StringJoiner;
public class MethodInfo {
public static void main(String[] args) throws Exception{
Class clazz = Class.forName("com.fastcampus.ch2.YoilTeller");
Object obj = clazz.newInstance();
Method[] methodArr = clazz.getDeclaredMethods();
for(Method m : methodArr) {
String name = m.getName();
Parameter[] paramArr = m.getParameters();
// Class[] paramTypeArr = m.getParameterTypes();
Class returnType = m.getReturnType();
StringJoiner paramList = new StringJoiner(", ", "(", ")");
for(Parameter param : paramArr) {
String paramName = param.getName();
Class paramType = param.getType();
paramList.add(paramType.getName() + " " + paramName);
}
System.out.printf("%s %s%s%n", returnType.getName(), name, paramList);
}
} // main
}
/* [실행결과]
java.lang.String main(java.lang.String year, java.lang.String month, java.lang.String day, org.springframework.ui.Model model)
boolean isValid(int year, int month, int day)
*/
1. YoilTeller 라는 클래스의 객체를 만든다.2. YoilTeller 의 모든 메서드 정보를 가져와서 배열에 저장한다.3. 반복문으로 메서드 정보를 하나씩 출력한다.
StringJoiner paramList = new StringJoiner(", ", "(", ")"); 여기선 괄호안엔 "구분자 = , ", "접두사 = ( ", "접미사 = )"로 되어있다.
이 메서드 매개변수 목록을 접두사와 접미사안에 구분자로 구분하여 나열하는 코드다.
아래 실행 결과에서 알 수 있듯이 각 매개변수 타입 이름 순으로 나열해준다.
void main(javax.servlet.http.HttpServletRequest arg0, javax.servlet.http.HttpServletResponse arg1)
실제 YoilTeller의 매개변수는 request와 response이지만 여기선 arg0, arg1로 바뀌어있다.
그 이유는 YoilTeller를 컴파일할때 매개변수 타입은 중요하지만 이름은 중요하지않아 저장하지 않기 때문이다.
때문에 매개변수 이름을 저장하려면 컴파일 옵션에 javac -parameters라고 옵션을 줘야한다.
STS 기준 옵션설정.
windows > preference > Compiler 검색 > java Compiler > 옵션중에 Store information - 옵션을 체크하면 된다.
이 기능은 JDK 1.8 이상만 가능하다.
해다 JDK버전을 세팅해둔 11버전으로 바꾸고 pom.xml 파일로 가서 java version을 변경해준다.

이후 맨 아래쪽에 가면 Plugin이 있는데 그 쪽에는 이 자바 버전을 가져올 수 있게 변수명으로 바꿔준다.
기존 1.6 > ${java version}

이 pom.xml 파일을 변경해주면 프로젝트를 업데이트 해주어야한다.

프로젝트를 우클릭해서 maven > Update Project (pom 파일은 maven 설정파일이다.)
void main(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
위는 결과창으로 옵션과 버전 변경 후, 정상적으로 매개변수 명을 가져오는 것을 볼 수 있다.
- 매개변수 이름을 Spring이 얻는 방법이 2가지 있다.
1. Reflection API를 이용하는 것.(방금 실행한 -parameters 옵션 설정 방식.)
2. Class file을 직접 읽어오는 것.(위 과정이 실패하면 이 방법으로 매개변수 이름을 얻어와야한다.)
이 2번째 방식을 실행하려면 패키지 exploorer말고 다른것으로 봐야 클래스 파일을 볼 수 있다고 한다.
Windows > Show View > other > navi 검색 > navigator

여기서 target의 경로로 가면 클래스 파일을 볼 수 있고, 파일을 더블 클릭하면 해석된 내용을 볼 수있다.(STS의 Open with의 Class file Viewer 기능)

해석된 클래스파일의 맨 아래에 Local variable table에서 해당 메서드와 매개변수명을 찾을 수 있다.
다른 예시)
package com.fastcampus.ch2;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
class ModelController {
public String main(HashMap map) {
map.put("id", "asdf");
map.put("pwd", "1111");
return "txtView2";
}
}
public class MethodCall {
public static void main(String[] args) throws Exception{
HashMap map = new HashMap();
System.out.println("before:"+map);
ModelController mc = new ModelController();
String viewName = mc.main(map);
System.out.println("after :"+map);
render(map, viewName);
}
static void render(HashMap map, String viewName) throws IOException {
String result = "";
// 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
Scanner sc = new Scanner(new File(viewName+".txt"));
while(sc.hasNextLine())
result += sc.nextLine()+ System.lineSeparator();
// 2. map에 담긴 key를 하나씩 읽어서 template의 ${key}를 value바꾼다.
Iterator it = map.keySet().iterator();
while(it.hasNext()) {
String key = (String)it.next();
// 3. replace()로 key를 value 치환한다.
result = result.replace("${"+key+"}", (String)map.get(key));
}
// 4.렌더링 결과를 출력한다.
System.out.println(result);
}
}
메인메서드에서 map을 만든다.
map의 모델 컨트롤러의 main 메서드한테 map을 넘겨준다.
그 다음 map에 Key : id / valuew : asdf 순으로 저장(map.put)한다.
다음 viewName(txtView2)을 반환한다.
(youtube에 참조형 매개변수 ch6- 24, 25 참조)
이 반환된 map(저장된 데이터)과 viewName을 render()라는 메서드에게 넘기는데 render()의 기능은 map의 데이터를 view에 보여주는 기능을 한다.
render() 메서드 내에서 viewName.txt (예 : ${id})를 iterator로 한줄씩 읽어 값을 반환해준다.
현재는 console에 출력하지만, response객체로 클라이언트에 출력할 수 있다.
txtView1, txtView2를 생성하여 실행해주면, 아래의 결과가 나온다.
(txtView의 내용 > id:${id}, pwd:${pwd})

처음 map을 생성했을 땐 키와 밸류가 비어있지만, 해당 메서드들이 동작하고 나서는 키와 배류의 값을 출력해주고, 맨 아래는 map을 view에 뿌려서 콘솔에 찍어내지만 실제로는 클라이언트에 렌더링해주는 결과가 된다.
그룹스터디에서 각 view를 생성하여 db의 데이터를 보여주는 과정과 같다.
컨트롤러에서 클라이언트의 url로 요청을 받아 service로 전달하고 전달된 값은 repository를 호출하는 service의 기능으로 데이터를 가져와 view 파일들에게 뿌려져 다시 클라이언트로 반환된다.
원래는 이 과정에 DTO 객체로 한번 감싸져서 주고받아져야하지만 아직까지 이해도가 떨어지는 관계로 엔티티를 직접 전송하고 있다.
<Group Study>
● Review CRUD 구현.
▷ 구현하기 전 정보
review는 앞서 엔티티를 구현할 때 각 게시글(healthInfo)의 id값을 참조로 가져 해당 id값을 게시글의 리뷰형태로 구현해야한다.
이 때문에 데이터를 view에 보여주는 것부터 고민이었는데, 일단 상세페이지에서 healthinfo id 값을 통해 리뷰를 불러오는 형태로 가기로 했다.
id값은 review 엔티티에 healthinfo 객체에 저장되는데, db에서 이름이 health_id로 지정이 되어있다.
앞서 review 엔티티를 구현할 때 healthinfo 엔티티에 리뷰를 추가하는 메서드를 구현해 놓았는데 이를 이용할 수 있을지.. 해봐야한다.
복습해보면, review 엔티티에서 manytoone의 관계를 healthinfo 엔티티와 가지고, 반대로 healthInfo에서는 onetomany의 관계를 가진다. 이는 양방향 관계로 JoinColomn과 mappedBy 로 관계의 주인이 참조값을 저장하는 review엔티티임을 명시했었다.n+1의 문제를 lazy로딩방식으로 대처했고, 엔티티의 상태변화가 cascade로 관계된 엔티티로 전달되게 했다.review 엔티티의 멤버 변수들은 review의 id, title, contents, health_id(참조값)이다.
먼저 필요한 클래스와 파일들을 나열하자면, 클라이언트의 요청을 받을 reviewController, 컨트롤러의 요청을 처리할 reviewService, 값이 저장되는 엔티티와 db와 데이터를 주고받을 repository는 이미 만들어두었고, 그 값을 감싸주는 DTO클래스는 미숙해서 당장은 생성하지 않을 예정이다.또한 review를 보여줄 view.html파일과 각 저장, 수정 기능이 구현될 save, modify html 파일도 필요할것이다.당장은 이렇게만 구성되어있지만, MVC패턴을 제대로 이용하려면 DTO와 객체생성을 맡은 Factory도 필요할 것이다.
데이터를 주고 받는 기능자체에서 이해도가 많이 떨어지기 때문에 차근차근 공부해보면서 진행할 것이다.
▷Review 컨트롤러
package com.example.demo.controller;
import com.example.demo.domain.HealthInfo;
import com.example.demo.domain.Review;
import com.example.demo.repository.ReviewRepository;
import com.example.demo.service.ReviewService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequiredArgsConstructor
@Slf4j
public class ReviewController {
public final ReviewService reviewService;
@GetMapping("/review")
public String healthView(Model model,@RequestParam Long id){
model.addAttribute("review", reviewService.findReview(id));
return "review";
}
@GetMapping("/review/write") // 저장 페이지.
public String writePage(@RequestParam Long id){
return "reviewWrite";
}
@PostMapping("/review/writer") //저장 기능 구현.
public String reviewSave(HealthInfo healthInfo, Review review){
reviewService.reviewWrite(healthInfo, review);
return "redirect:/review"; //prg패턴.
}
@GetMapping("/review/delete")
public String reviewDeleter(@RequestParam Long id){
reviewService.reviewDelete(id);
return "redirect:/review";
}
}
기존에 만들었던 형태와 유사하게 만들었다.
homeContoller에서 repository와 직통으로 연결되는 의존의 형태를 최대한 service를 이용해 완화할 생각이다.
일단 리뷰 페이지는 healthInfo.id를 매개변수로 받아 해당 값을 가진 리뷰들이 모두 찾아지도록 만들 예정이다.
저장기능을 대충이나마 구현했는데, healthInfo.id는 자동으로 저장되게끔 해야하는데 객체자체를 저장해야할지, Long id로 저장해야할지 모르겠다.
엔티티에는
@ManyToOne
@JoinColumn(name = "health_id")
private HealthInfo healthInfo;
healthInfo라는 HealthInfo타입의 변수가 선언되어있기는하지만, id값만 딱 저장되는건지는 모르겠다.
▷ReviewService
먼저 인터페이스를 보면 필요한 기능들을 명시해놓았다.
package com.example.demo.service;
import com.example.demo.domain.HealthInfo;
import com.example.demo.domain.Review;
import java.util.Optional;
public interface ReviewService {
public void reviewWrite(HealthInfo healthInfo, Review review);
public Review findReview(Long id) ;
public Optional<Review> reviewList(HealthInfo healthInfo);
//수정기능 값이 저장이 안됨.
void reviewModify(Long id);
public boolean reviewDelete(Long id);
}
저장, 삭제, 값찾아오기, 수정 등을 정의하고 구현체로 가보겠다.
package com.example.demo.service.impl;
import com.example.demo.domain.HealthInfo;
import com.example.demo.domain.Review;
import com.example.demo.repository.ReviewRepository;
import com.example.demo.service.ReviewService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class ReviewServiceImpl implements ReviewService {
private final ReviewRepository reviewRepository;
@Override
public Review findReview(Long id) {
return reviewRepository.findById(id).orElseThrow(IllegalArgumentException::new);
}
@Override
public Optional<Review> reviewList(HealthInfo healthInfo) {
Long health_id = healthInfo.getId();
Optional<Review> list = reviewRepository.findById(health_id);
return list;
}
@Override
public void reviewWrite(HealthInfo healthInfo, Review review) {
healthInfo.getId();
healthInfo.addReview(review);
}
@Override
public void reviewModify(Long id) {
}
@Override
public boolean reviewDelete(@RequestParam Long id) {
reviewRepository.deleteById(id);
return true;
}
}
삭제기능은 동일하게 id값으로 지우면되는데, 저장과 데이터 찾아오기에서 고민이다.
▷html파일들
- review
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>헬스장 리뷰 페이지</title>
</head>
<body>
<table>
<thead>
<tr>
<h1>ReviewPage</h1>
</tr>
<a th:href="@{/review/write(id=${healthInfo.id})}">리뷰 쓰기</button>
</thead>
<tbody>
<tr th:each = "review:${list}">
<td th:text="${review.id}"></td>
<td>
<a th:text="${review.title}"></a>
<a th:text="${review.contents}"></a>
<a type="hidden" th:text="${review.healthInfo}"></a>
<a th:href="@{/review/delete(id=${review.id})}">삭제</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
- review 저장 view
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>헬스장 정보 저장 페이지</title>
</head>
<body>
<table>
<form th:action="@{/review/writer}" method="post">
<p>아래에 자료를 입력하세요.</p>
<tr>
<td><input type="text" name="title"></td>
</tr>
<tr>
<td><input type="text" name="contents"></td>
</tr>
<a name="health_id" type="hidden" th:href="@{healthInfo.id}></a>
<tr>
<td><input type="reset" value="취소"></td>
<td><button type="submit">저장</button></td>
</tr>
</form>
</table>
</body>
</html>
'TIL' 카테고리의 다른 글
| 2023.01.20 TIL (0) | 2023.01.20 |
|---|---|
| 2023.01.17 TIL (0) | 2023.01.18 |
| 2023.01.16 TIL (0) | 2023.01.16 |
| 2023.01.13 (0) | 2023.01.13 |
| 2023.01.12 TIL (0) | 2023.01.12 |