pom.xml 의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
templates > new > other > AddUser.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<div>
<input class="username">
</div>
<div>
<input class="password">
</div>
<div>
<input class="name">
</div>
<div>
<input class="email">
</div>
<button>등록</button>
<script>
</script>
</body>
</html>
controller > UserPageController.java(class) 생성
코드를 입력하세요
서버 실행은 main 에서 반드시 실행 할것!!!
post
/api/user/addition
요청 JSON UserAdditionDto -> username, password, name, email
응답 UserAdditionDto (@RestController)
dto > request > UserAdditionDto(class) 생성
package com.web.study.dto.request;
import lombok.Data;
@Data
public class UserAdditionDto {
private String username;
private String password;
private String name;
private String email;
}
controller > UserRestController(class) 생성
package com.web.study.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.web.study.dto.DataResponseDto;
import com.web.study.dto.ResponseDto;
import com.web.study.dto.request.UserAdditionDto;
@RestController
public class UserRestController {
@PostMapping("/api/user/addition")
public ResponseEntity<? extends ResponseDto> addUser(@RequestBody UserAdditionDto userAdditionDto) {
System.out.println("서버 전송 성공");
return ResponseEntity.ok().body(DataResponseDto.of(userAdditionDto));
}
}
메서드 정의: public ResponseEntity<? extends ResponseDto> addUser(@RequestBody UserAdditionDto userAdditionDto)는 UserAdditionDto 타입의 객체를 입력으로 받아 ResponseDto 타입의 ResponseEntity를 반환하는 addUser 메서드를 정의
ResponseEntity는 HTTP 응답과 관련된 정보를 포함
@PostMapping
어노테이션: 이 어노테이션은 이 메서드가 HTTP POST 요청을 처리하며, "/api/user/addition" 경로로 매핑. 클라이언트가 이 경로로 POST 요청을 보내면, addUser 메서드가 실행.
@RequestBody
어노테이션: 이 어노테이션은 메서드 인자의 UserAdditionDto 객체가 HTTP 요청 본문에서 변환된 것임을 나타냄. JSON 형태의 HTTP 요청 본문이 자동으로 UserAdditionDto 객체로 변환
ResponseEntity 반환: 요청이 처리된 후, ResponseEntity.ok().body(DataResponseDto.of(userAdditionDto))를 통해 HTTP 응답을 생성하고 반환. 여기서는 HTTP 상태 코드를 '200 OK'로 설정하고 응답 본문에 DataResponseDto 객체를 포함시키며, 이 DataResponseDto 객체는 UserAdditionDto 객체를 이용하여 생성.
결과
AddUser.html 수정
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<div>
<input class="username">
</div>
<div>
<input class="password">
</div>
<div>
<input class="name">
</div>
<div>
<input class="email">
</div>
<button type="button" class="send-button">등록</button>
<script>
window.onload = () => {
addSendButtonEvent();
}
function addSendButtonEvent(){
const sendButton = document.querySelector(".send-button");
sendButton.onclick = () => {
send();
}
}
function send() {
const username = document.querySelector(".username").value;
const password = document.querySelector(".password").value;
const name = document.querySelector(".name").value;
const email = document.querySelector(".email").value;
const userObj = {
username,
password,
name,
email
};
const request ={
type:"post", //method
url: "http://localhost:8080/api/user/addition",
contentType: "application/json", //요청 데이터 타입
data: JSON.stringify(userObj), // 요청 데이터
dataType:"json", // 응답 데이터 타입
// 응답 성공시에 실행될 메서드 정의
success: (response) => {
console.log(response);
},
// 응답 실패시에 실행될 메서드 정의
error: (error) => {
console.log(error);
}
}
$.ajax(request);
}
</script>
</body>
</html>
- AJAX ( Asynchronous JavaScript and XML )는 웹 개발에서 널리 사용되는 기술로 웹 페이지의 일부부만 업데이트할 수 있게 해주는 동시에, 사용자와 상호작용하는 동안 웹 페이지의 전체 로딩이 필요하지 않음, 이로 인해 사용자 경험이 향상되며, 웹 페이지의 응답 속도도 빨라짐
- 웹 페이지에서 서버와 비동기적으로 데이터를 교환하기 위해
JavaScipt
를 사용, 이렇게함으로써 웹 페이지가 다시 로드되지 않고도 서버로부터 데이터를 받아올 수 있으며, 이 데이터를 활용해 페이지의 특정 부분을 업데이트할 수 있음- 원래 AJAX는 XML을 데이터 포맷으로 사용하였지만, 현재는
JSON
(JavaScipt Object Notation)이 더 널리 사용되고 있음, JSON은 가볍고, 가독성이 높으며, JavaScript와 호환성이 좋음
- HTTP(Hypertext Transfer Protocol)는 웹 상에서 정보를 주고받을 수 있는 프로토콜이며 클라이언트(웹 브라우저)와 서버 간에 요청과 응답을 주고받으면서 웹 페이지의 내용이나 리소스를 제공, HTTP는 평문(암호화되지 않은 데이터) 형태로 정보를 전송하기 때문에, 중간에서 데이터가 가로채거나 조작할 수 있는 위험이 있음
- HTTPS(Hypertext Transfer Protocol Secure)는 HTTP에 보안 레이어를 추가한 프로토콜로, 웹 상에서 정보를 안전하게 주고받을 수 있음, HTTPS는
SSL(Secure Sockets Layer)
또는TLS(Transport Layer Security)
라는 암호화 기술을 사용하여 클라이언트와 서버 간의 통신을 암호화 함. 이로 인해 중간자 공격(Man-in-the-middle attack)이나 데이터 유출 등의 보안 위험을 줄일 수 있음
💡요약하면, HTTP는 암호화되지 않은 데이터를 전송하는 반면, HTTPS는 암호화 기술을 사용하여 데이터를 안전하게 전송. 따라서 개인정보, 결제 정보 등 민감한 데이터를 다루는 웹 사이트에서는 HTTPS를 사용하는 것이 권장됨.
Stateless
: 각 요청은 서버에 저장되는 클라이언트의 상태 정보 없이 독립적으로 처리됨, 이를 통해 서버의 확장성이 향상되며, 각 요청이 필요한 모든 정보를 포함해야함Client-Server Architecture
: 클라이언트와 서버는 서로 독립적으로 발전할 수 있는 구조를 가지고 있음. 이로 인해 클라이언트와 서버 간의 의존성이 줄어들고, 각각의 역할이 명확해짐Cacheable
: REST API는 캐시를 사용하여 응답을 저정할 수 있음. 이를 통해 클라이언트가 필요할 때 캐시된 데이터를 재사용할 수 있으며, 서버의 부하를 줄이고 성능을 향상시킬 수 있음Layered System
: REST 아키텍처는 여러 계층으로 구성될 수 있으며, 각 계층은 독립적으로 관리되고 발전할 수 있음. 이를 통해 유연한 시스템 구조를 구축할 수 있음
- 이러한 특성 덕분에 REST API는 웹 서비스 간의 통신을 간편하고 표준화된 방식으로 제공하며, 다양한 플랫폼과 언어에서 쉽게 사용할 수 있음
UserPageController
package com.web.study.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserPageController {
@GetMapping("/page/user/addition")
public String addUser() {
return "AddUser";
}
@GetMapping("/page/user/search")
public String getUser() {
return "FindUser";
}
@GetMapping("/page/users")
public String getUsers() {
return "UserList";
}
}
UserPageController
클래스는 사용자 관련 페이지를 처리하는 컨트롤러로서, 다음과 같은 세가지 엔드 포인트를 제공한다.
1. @GetMapping("/page/user/addition") : 사용자 추가 페이지에 대한 요청을 처리, 이 엔드포인트가 호출되면AddUser
라는 뷰 이름을 반환하며, 이 뷰는 사용자 추가 페이지를 표시하는데 사용
2. @GetMapping("/page/user/search") : 사용자 검색 페이지에 대한 요청을 처리, 이 엔드포인트가 호출되면FindUser
라는 뷰 이름을 반환하며, 이 뷰는 사용자 검색 페이지를 표시하는데 사용
3. @GetMapping("page/users") : 사용자 목록 페이지에 대한 요청을 처리, 이 엔드포인트가 호출되면UserList
라는 뷰 이름을 반환하며, 이 뷰는 사용자 목록 페이지를 표시하는데 사용
@Controller
어노테이션은 해당 클래스가 Spring MVC(Model-View-Controller) 컨트롤러로 사용되어야 함을 나타냄
@GetMapping
어노테이션은 특정 HTTP GET 요청을 해당 메서드에 매핑함을 나타냄. 이러한 방식으로 사용자와 관련된 웹 페이지에 대한 요청을 각 메서드가 처리하고 적절한 뷰를 반환
AddUser.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<div>
<input class="username" placeholder="username">
</div>
<div>
<input class="password" placeholder="password">
</div>
<div>
<input class="name" placeholder="name">
</div>
<div>
<input class="email" placeholder="email">
</div>
<button type="button" class="send-button">등록</button>
<script>
window.onload = () => {
addSendButtonEvent();
}
function addSendButtonEvent(){
const sendButton = document.querySelector(".send-button");
sendButton.onclick = () => {
send();
}
}
function send() {
const username = document.querySelector(".username").value;
const password = document.querySelector(".password").value;
const name = document.querySelector(".name").value;
const email = document.querySelector(".email").value;
const userObj = {
username,
password,
name,
email
};
const request ={
type:"post", //method
url: "http://localhost:8080/api/user/addition",
contentType: "application/json", //요청 데이터 타입
data: JSON.stringify(userObj), // 요청 데이터
dataType:"json", // 응답 데이터 타입
// 응답 성공시에 실행될 메서드 정의
success: (response) => {
console.log(response);
},
// 응답 실패시에 실행될 메서드 정의
error: (error) => {
console.log(error);
}
}
$.ajax(request);
}
</script>
</body>
</html>
<script src="https://code.jquery.com/jquery-latest.min.js">
jQuery 라이브러리를 불러오는 부분
1.HTML : 사용자 입력을 받기 위한 input 요소들과, 이벤트 리스너를 추가할 버튼 요소가 포함
2. JavaScript : 페이지 로드 시 버튼에 이벤트 리스너를 추가하고, 버튼 클릭 시 서버로 데이터를 전송하기 위한AJAX
요청을 구성하고 실행
3. 위 코드에서의 주요 기능은send()
함수 내의$.ajax(request)
를 통해 이루어짐. 이를 통해 서버로 JSON 형태의 사용자 데이터를 전송하고, 서버의 응답을 처리, 이러한 방식을 AJAX를 사용한 클라이언트-서버 통신이라고 부름
UserRestController
package com.web.study.controller;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.web.study.dto.DataResponseDto;
import com.web.study.dto.ErrorResponseDto;
import com.web.study.dto.ResponseDto;
import com.web.study.dto.request.UserAdditionDto;
class UserStore {
public static Map<Integer, UserAdditionDto> userMap = new HashMap<>();
}
@RestController
public class UserRestController {
@PostMapping("/api/user/addition")
public ResponseEntity<? extends ResponseDto> addUser(@RequestBody UserAdditionDto userAdditionDto) {
System.out.println("서버 전송 성공");
Map<Integer, UserAdditionDto> userMap = UserStore.userMap;
int maxKey = 0;
if(!userMap.keySet().isEmpty()) {
maxKey = Collections.max(userMap.keySet());
}
userMap.put(maxKey + 1 , userAdditionDto);
System.out.println(userMap);
return ResponseEntity.ok().body(DataResponseDto.of(userAdditionDto));
}
@GetMapping("/api/user/{id}")
public ResponseEntity<? extends ResponseDto> getUser(@PathVariable int id) {
// userMap에서 id가 해당 id를 가진 객체를 응답
// 만약에 해당 id가 존재하지 않으면 ErrorResponse를 응답으로 준다.
// errorMessage = 존재하지 않는 id입니다.
Map<Integer, UserAdditionDto> userMap = UserStore.userMap;
UserAdditionDto UserAdditionDto = userMap.get(id);
try {
if(UserAdditionDto == null) {
throw new RuntimeException("존재하지 않는 id입니다.");
}
}catch (Exception e) {
return ResponseEntity.badRequest().body(ErrorResponseDto.of(HttpStatus.BAD_REQUEST,e));
}
return ResponseEntity.ok().body(DataResponseDto.of(UserAdditionDto));
}
@GetMapping("/api/users")
public ResponseEntity<? extends ResponseDto> getUsers() {
return ResponseEntity.ok().body(DataResponseDto.of(UserStore.userMap.values()));
}
}
- 해당 코드는 Java로 작성된 Spring Boot 기반의 RESTful API 컨트롤러.
UserRestController
클래스는 사용자 관련 API 엔드포인트를 처리하는 컨트롤러로서 세가지 엔드포인트를 제공
- @PostMapping("/api/user/addition") : 사용자 추가 API 엔드 포인트, 클라이언트로부터 전달받은
UserAdditionDto
객체를 서버 측의UserStore
클래스의userMap
에 저장. 저장이 완료되면 저장된 객체를DataResponseDto
로 감싸서 클라이언트에게 응답- @GetMapping("api/user/{id})" : 특정 사용자의 정보를 반환하는 API 엔드 포인트, 클라이언트로부터 전달받은
id
값을 이용하여UserStore
클래스의userMap
에서 해당 사용자 정보를 조회, 사용자 정보가 존재하면DataResponseDto
로 감싸서 응답하고, 존재하지 않으면ErrorResponseDto
를 반환하여 에러 메시지를 전달- @GetMapping("/api/users") : 모든 사용자 정보를 반환하는 API 엔드 포인트,
UserStore
클래스의userMap
에 저장된 모든 사용자 정보를 가져와DataResponseDto
로 감싸서 클라이언트에게 응답
UserStore
클래스는userMap
이라는 정적HashMap
을 포함하며, 이를 통해 사용자 정보를 메모리에 저장하고 관리ResponseEntity
는 HTTP 응답을 구성하기 위한 클래스로, 이를 사용하여 클라이언트에게 응답을 전송할 때 응답 본문과 함께 상태 코드를 설정할 수 있음. 이 코드에서는ResponseEntity.ok()
와ResponseEntity.badRequest()
를 사용하여 상태 코드를 설정
@RestController
어노테이션은 해당 클래스가 Spring REST 컨트롤러로 사용되어야 함을 나타냄
@PostMapping, @GetMapping 어노테이션은 각각 HTTP POST 및 GET 요청을 해당 메서드에 매핑함을 나타냄,
→ 이러한 방식으로 사용자와 관련된 API 요청을 각 메서드가 처리하고 적절한 응답을 반환
URL
. 즉, 엔드포인트는 API의 각 기능에 대한 경로를 나타내며, 이를 통해 클라이언트와 서버 간 데이터를 교환 할 수 있음. 일반적으로 엔드포인트는 HTTP메서드와 함께 사용되어 CRUD(Create, Read, Update, Delete)작업을 수행UserAdditionDto
package com.web.study.dto.request;
import lombok.Data;
@Data
public class UserAdditionDto {
private String username;
private String password;
private String name;
private String email;
}
@@@
조회 성공
조회 실패