csr과 ssr에 대해 하나도 모른다면 아래의 글을 보고 오자.
https://rookie-programmer.tistory.com/203
렌더링이란? CSR, SSR 그게 도대체 뭔데?
💡 CSR, SSR 그게 뭔데? CSR과 SSR에 대해 알기 전에, (1)SPA와 MPA와 (2)브라우저 렌더링에 대해 알아야 한다. 📌 SPA, MPA ✅ SPA == CSR SPA(Single Page Application) : 하나의 페이지로 구성된 웹 애플리케이션이
rookie-programmer.tistory.com
csr과 ssr은 개념은 글과 사진만으로는 개념을 완벽하기 이해하기 어렵다.
아래 실습을 통해 실제 HTML이 어떻게 요청되고, 데이터는 어떻게 반환되고, 화면이 어떻게 다시 띄워지는지 알아보자.
CSR
[ PostRepository.java ]
List에 5개의 Post 데이터가 담겨있다. Post는 [번호, 제목, 내용, 글쓴이]를 저장하는 객체이다.
실습 예제에서는 PostRepository.java 파일을 데이터를 가지고 있는 곳이라고 가정하겠다.
다른 클래스에서 findAll 함수를 사용해 저장된 데이터들을 모두 가져올 수 있다. ex) postRepository.findAll()
public class PostRepository {
List<Post> posts;
PostRepository(){
this.posts = new ArrayList<>();
this.posts.add(new Post(1, "title1", "hello java world1", "ShinYJ1"));
this.posts.add(new Post(2, "title2", "hello java world2", "ShinYJ2"));
this.posts.add(new Post(3, "title3", "hello java world3", "ShinYJ3"));
this.posts.add(new Post(4, "title4", "hello java world4", "ShinYJ4"));
}
List<Post> findAll(){
return this.posts;
}
}
[ PostService.java ]
Service 클래스에서는 Repository에 있는 데이터를 Controller로 가져다주는 역할을 한다.
사용자는 postService.findAll()를 통해 데이터 저장소에 있는 데이터들을 전달받을 수 있다.
public class PostService {
private PostRepository postRepository;
PostService(){
this.postRepository = new PostRepository();
}
List<Post> findAll(){
return this.postRepository.findAll();
}
}
[ PostController.java ]
사용자의 URL 입력값에 따라 특정 함수를 호출해 데이터를 화면에 띄워준다.
사용자가 URL에 http://localhost:8080/csr/json를 치고 들어오면,
PostController 클래스의 @GetMapping과 매핑되어 findAll() 함수가 실행되고,
postService.findAll()을 통해 데이터 저장소에서 데이터를 가져온 후 HTML에 데이터를 넣어준다.
사용자는 데이터가 담긴 HTML을 확인할 수 있다.
//CSR : 사용자에게 data return
@GetMapping("/csr/json") //url에 localhost:8080/csr/json치고 들어오면 해당 함수와 매핑
@ResponseBody //json으로 데이터를 받을 때
public List<Post> findAll(){
return this.postService.findAll();
}
하지만 CORS 정책 위반으로 원하는 화면을 가져오지 못하는 것을 볼 수 있다!!!
💡 CORS (Cross Origin Resource Sharing) 정책이란?
한 도메인 또는 Origin의 웹 페이지가 다른 도메인 (도메인 간 요청)을 가진 리소스에 액세스 할 수 있게하는 보안 메커니즘으로,
동일한 출처의 리소스에만 접근하도록 제한하는 것이다. 여기서 출처는 프로토콜, 호스트명, 포트가 같다는 것을 의미한다.
쉽게 말해, 현재 예제에서 데이터가 있는 URL은 localhost:8080/csr/json
HTML이 있는 URL은 file:///C:/Users/Playdata/Desktop/html_css_javascript/posts/16.js_postlist_axios.html이기 때문에
URL이 달라 소스의 원천(Origin)이 안맞는다고 하는 것이다.
현대적인 프로그래밍에서는 CSR 방식이 많이 사용된다.
프론트 URL : www.encore.com
백엔드 URL : api.encore.com
이런식으로 다른 URL을 가지고 있어 CORS 오류가 뜨는 것이 일반적이다.
이렇게 데이터가 있는 곳과, 데이터를 접근해 보여주는 곳의 URL이 다르면 뜨는 것이 CORS 오류!!
해결방법 1
-> Spring에서 제약을 거는 것이기 때문에 CorsConfig 파일을 추가해 모든(혹은 특정) 포트에 대한 접근을 열어둔다.
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry corsRegistry){
corsRegistry.addMapping("/**")
.allowedOrigins("*") //특정 url에 대해서만 허용
.allowedMethods("*");
}
}
이렇게 설정하게 되면 데이터가 있는 곳과, 데이터를 접근해 보여주는 곳이 같지 않아도 데이터를 정상적으로 보여주게 된다.
해결방법2
data가 있는 Spring Server에 static 폴더 밑에 html 파일을 둔다.
= 데이터가 있는 위치에 HTML 파일을 넣어줘 URL을 맞춰준다.
이렇게 하면 localhost:8080/~~ 으로 URL이 같아지기 때문에, 따로 CORS 파일을 추가하지 않아도 된다.
두 가지 중 한 가지 방법을 선택해 CORS 오류를 해결하고 나면, HTML코드를 통해 데이터가 담긴 화면을 받아볼 수 있다.
이제 CSR 방식으로 데이터를 조회해서 HTML을 띄워보자.
📌 CSR 방식으로 데이터 조회해서 HTML 띄워보기 1 - 별도의 프론트엔드 URL 띄우기
(1) CORS 오류 해결방법 1번으로 CORS 오류를 잡아주고 C:/Users/Playdata/Desktop/html_css_javascript/posts/post_list.html 폴더에 있는 HTML 파일을 연다. (HTML 코드는 2번 방식과 동일하다)
⭐️ CSR로 HTML 가져오기 성공 ⭐️
HTML 위치(html_css_javascript/posts 폴더)와 데이터가 있는 위치(localhost:8080/csr/json)가 다르기 때문에 CORS 오류가 발생하는 것이 일반적이지만, 지금은 CORS 오류 해결방법 1번으로 CORS 오류를 잡아주었기 때문에 데이터를 정상적으로 가져온다.
(+)
aws를 이용한 심화 실습에서도 HTML은 s3에 있고, 데이터는 ec2에 있기 때문에 aws 실습에서도 cors오류가 발생할 것이다.
📌 CSR 방식으로 데이터 조회해서 HTML 띄워보기 2 - static 폴더의 HTML 띄우기
(1) CORS 오류 해결방법 2번으로 CORS 오류를 잡아주고 http://localhost:8080/post_list.html을 입력한다.
[ resuorce > static > post_list.html ]
html 코드에 서버에 데이터를 요청하는 ajax, axios가 있으면 CSR이다.
axios를 통해 /csr/json에서 데이터를 받아 html에 데이터를 넣어준다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css_bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<style>
object {
width:100%;
}
</style>
</head>
<body>
<object type="text/html" data="header.html"></object>
<div class="container">
<div class="page-header"><h1>게시글 목록</h1></div>
<div class="float-end"><a href="./7.css_bootstrap_postregister.html"><button class="btn btn-primary">글쓰기</button></a></div>
<table class="table">
<tr>
<th>id</th>
<th>title</th>
<th>userId</th>
</tr>
</table>
</div>
<script>
async function callBackImp(){
try{
let myTarget = document.getElementsByClassName("table")[0];
const response1 = await axios.get('http://localhost:8080/csr/json');
console.log(response1);
response1.data.forEach(element => {
myTarget.innerHTML += `<tr><td>${element.id}</td><td>${element.title}</td><td>${element.body}</td><td>${element.authorName}</td></tr>`
});
}catch(e){
console.log(e);
}
}
callBackImp();
</script>
</body>
</html>
[ PostController ]
package com.example.demo.post;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;
@Controller
public class PostController {
private PostService postService;
PostController(){
this.postService = new PostService();
}
//CSR : 사용자에게 data return
@GetMapping("/csr/json") //전체 url에다가 localhost:8080/csr/json치고 들어오면 해당 함수와 매핑
@ResponseBody //json으로 데이터를 받을 때
public List<Post> findAll(){
return this.postService.findAll();
}
}
⭐️ CSR로 HTML 가져오기 성공 ⭐️
CSR = @ResponseBody ⭐
-> static 폴더에 있는 html을 넘김
=> 데이터 없는 HTML/CSS/JS 반환 -> 반환된 브라우저가 /csr/json에 data요청 -> 데이터 담긴 최종 화면을 띄워준다.
SSR
📌 SSR 방식으로 데이터 조회해서 HTML 띄워보기 - 타임리프를 통해 데이터가 담긴 HTML 반환
[ resuorce > templates > post_list.html ]
HTML 파일에 있는 타임리프를 통해 가져온 데이터를 삽입한다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css_bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
<object type="text/html" data="header.html"></object>
<div class="container">
<div class="page-header"><h1>게시글 목록</h1></div>
<div class="float-end">
<a href="./7.css_bootstrap_postregister.html"><button class="btn btn-primary">글쓰기</button></a></div>
<table class="table">
<tr>
<th>id</th>
<th>title</th>
<th>body</th>
<th>authorName</th>
</tr>
<tr th:each="post : ${posts}">
<td th:text="${post.id}"></td>
<td th:text="${post.title}"></td>
<td th:text="${post.body}"></td>
<td th:text="${post.authorName}"></td>
</tr>
</table>
</div>
</body>
</html>
[ PostController ]
package com.example.demo.post;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;
@Controller
public class PostController {
private PostService postService;
PostController(){
this.postService = new PostService();
}
//SSR : 사용자에게 data가 들어간 화면 return
@GetMapping("/ssr")
public String findAllSsr(Model model){
List<Post> posts = postService.findAll();
//model을 통해 data를 html에 넣어주기
model.addAttribute("posts", posts); //"key-value" => "posts-posts"
return "post_list";
}
}
SSR = @ResponseBody 없음 ⭐
-> String으로 HTML 파일명을 return하면 templates안에 있는 해당 HTML 파일을 넘김
이때, 데이터들은 model에 넣어서 넘겨주게 되면,
HTML 파일은 넘어온 model에 있는 데이터를 읽어와 알맞은 자리에 넣어준다.
=> 데이터 들어가 있는 HTML/CSS/JS 반환
⭐️ SSR로 HTML 가져오기 성공 ⭐️
'Back-End 공부 > Spring' 카테고리의 다른 글
스프링 DB 연결 및 Transactional 처리 (0) | 2024.01.16 |
---|---|
스프링 용어 쉽게 정리하기 (빈, 싱글톤, DI, 제어의 역전, IoC 컨테이너) (0) | 2024.01.16 |
Controller, Service, Repository에 Dto 객체 추가해 실습하기 (1) | 2024.01.15 |
application.properties와 application.yml 환경 설정 변경 (1) | 2024.01.15 |
렌더링이란? CSR, SSR 그게 도대체 뭔데? (0) | 2024.01.14 |