각진 세상에 둥근 춤을 추자

[Spring Boot] REST 웹 서비스 + 실습 본문

Spring

[Spring Boot] REST 웹 서비스 + 실습

circle.j 2023. 1. 17. 12:13
API (Application Programming Interface)

 

  • API는 프로그램과 프로그램 사이의 연결이다.
  • 일종의 소프트웨어 인터페이스이며 다른 종류의 소프트웨어에 서비스를 제공한다.
  • 일반적으로 API는 애플리케이션에서 요청을 보내고 응답을 받기 위해 정의된 명세(URL)를 의미한다.

 

 

 


REST API (Representational State Transfer API)

 

  • REST는 2000년 Roy Fielding의 박사가 제안한 네트워크에서 클라이언트와 서버 사이의 통신을 구현하는 방법에 대한 이론으로 하나의 자원은 여러 형태의 Representation(json, xml, text, rss 등)으로 전달할 수 있다는 개념이다.
  • REST API는 URI + Method를 의미하고 URI를 통해 제어할 자원을 명시하고, Method를 통해 해당 Resource를 제어하는 명령을 내리는 방식의 아키텍처를 의미한다.

 

 

웹은 기본적으로 클라이언트 요청에 대한 응답으로 화면 중심의 HTML을 제공하는 시스템이기 때문에 단순히 데이터를 주고받고자 하는 서비스에는 적합하지 않다.

이에 따라 확장성이 뛰어나고 경량의 데이터 구조인 JSON이 주목을 받기 시작한다. 

REST는 현재 HTTP와 JSON을 함께 사용하여 Open API를 구현하는 형태로 많이 사용된다. 

일반적으로 REST 원칙을 따르는 서비스를 RESTful 서비스라고 말한다. 

 

 

 


Spring REST 웹 서비스 실습

 

  ▷ 순서

  1. 프로젝트 생성
  2. application.properties
  3. index 페이지
  4. MainController 
  5. pom.xml 
  6. VO
  7. xml
  8. JS
  9. DAO
  10. Service
  11. Controller 

 

1. 프로젝트 생성

 

New - Spring Starter Project

 

  • Name: 프로젝트명
  • Type: Maven
  • Packaging: Jar
  • Java Version: 11
  • Language: Java
  • Group, Package: kr.co.패키지명

 

 

 

  • Spring Boot Version: 2.7.7
  • Selected: Lombok, MyBatis FrameWork, MySQL Driver, Spring Boot DevTools, Spring Web, Spring Data JPA, Thymeleaf

 

 


2. application.properties

 

프로젝트 - src/main/resources - application.properties

# 기본 개발설정
server.servlet.context-path=/Ch09
spring.thymeleaf.cache=false

# DataSource 설정
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/java2db
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# MyBatis Mapper 경로설정
mybatis.mapper-locations=classpath:mappers/**/*.xml

# JPA 설정
spring.jpa.database=mysql
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.hibernate.ddl-auto=update

 

 


3. index 페이지 생성

 

프로젝트 - src/main/resources - templates - index.html 생성

// 구글 JQuery 추가
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="UTF-8">
		<title>index</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
		<script th:src="@{/js/user1.js}"></script>
	</head>
	<body>
		<h3>Ch09. 스프링 REST 웹서비스 실습</h3>
		
		<h4>user1</h4>
		<button class="user1 list1">user1 목록1</button>
		<button class="user1 list2">user1 목록2</button>
		<button class="user1 register">user1 등록</button>
		<button class="user1 modify">user1 수정</button>
		<button class="user1 delete">user1 삭제</button>

	</body>
</html>

 

 


4. MainController

 

프로젝트 - src/main/java - kr.co.ch09 - controller 패키지 생성 - MainController.java 생성

package kr.co.ch09.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MainController {
	
	@GetMapping(value= {"/", "/index"})
	public String index() {
		return "/index";
	}
}

 

 


5. pom.xml 수정

 

현재 상태로 바로 실행하면 에러가 뜬다. 

프로젝트의 pom.xml에서 mysql-connector-j의 <scope>runtime</scope>내용을 지워 활성화 시킨다. 

 

 

수정 후 실행(프로젝트 우클릭 - Rus As - Spring Boot App)하면, 다음과 같은 화면을 구성할 수 있다. 

http://localhost:8080/Ch09/

 

 


6. VO 

 

프로젝트 - src/main/java - kr.co.ch09 - vo 패키지 생성 - User1VO.java 생성

package kr.co.ch09.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;


@Builder
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
public class User1VO {

	private String uid;
	private String pass;
	private String name;
	private String hp;
	private int age;
	
}

 

 


7. xml 

 

src/main/resources - mappers 폴더 생성 - user1.xml 생성

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.co.ch09.dao.User1DAO">
	<insert id="insertUser1">
		INSERT INTO `user1` VALUES (#{uid}, #{pass}, #{name}, #{hp}, #{age});
	</insert>
	<select id="selectUser1" resultType="kr.co.ch09.vo.User1VO">
		select * from `user1` where `uid`=#{uid};
	</select>
	<select id="selectUser1s" resultType="kr.co.ch09.vo.User1VO">
		select * from `user1`;
	</select>
	<update id="updateUser1">
		update `user1` set
			`name`=#{name},
			`hp`=#{hp},
			`age`=#{age}
		where
			`uid`=#{uid};		
	</update>
	<delete id="deleteUser1">
		delete from `user1` where `uid`=#{uid};
	</delete>
</mapper>

 

 

 


8. jQuery (js)

 

프로젝트 - src/main/resources - static (정적) - js 폴더 생성 - user1.js 생성

[Java script] 기본 구조 

$(document).ready(function(){
    $('.user1.list1').click(function(){});
    $('.user1.list2').click(function(){});
    $('.user1.register').click(function(){});
    $('.user1.modify').click(function(){});
    $('.user1.delete').click(function(){});
});

 

[user1.js]

/**
 * 
 */
$(document).ready(function(){
	
    // list1: 유저 목록 가져오기 
	$('.user1.list1').click(function(){
		$.ajax({
			url: '/Ch09/user1',
			method: 'GET',
			dataType: 'json',
			success: function(data){
				console.log(data);
			}
		});
	});
	
    // list2: 유저(1명) 정보 가져오기 
	$('.user1.list2').click(function(){
		
		let uid = 'j103';
		
		$.ajax({
			url: '/Ch09/user1/'+uid,
			method: 'GET',
			dataType: 'json',
			success: function(data){
				console.log(data);
			}
		});	
	});
	
    // register: 유저 등록하기 
	$('.user1.register').click(function(){
		
		let jsonData = {
			"uid": "s101",
			"name": "홍길동",
			"hp": "010-1234-1101",
			"age": 19
		};
		
		$.ajax({
			url: '/Ch09/user1/',
			method: 'POST',
			data: jsonData,
			dataType: 'json',
			success: function(data){
				console.log(data);	
			}						
		});
		
	});
	
	// modify: 유저 수정하기 
	$('.user1.modify').click(function(){
		
		let jsonData = {
				"uid": "s101",
				"name": "홍길동",
				"hp": "010-1234-2220",
				"age": 29
			};
			
			$.ajax({
				url: '/Ch09/user1/',
				method: 'PUT',
				data: jsonData,
				dataType: 'json',
				success: function(data){
					console.log(data);	
				}						
			});
		
	});
	
	// delete: 유저 삭제하기 
	$('.user1.delete').click(function(){
		let uid = 's101';
		
		$.ajax({
			url: '/Ch09/user1/'+uid,
			method: 'DELETE',
			dataType: 'json',
			success: function(data){
				console.log(data);	
			}						
		});
		
	});

});

 

 


9. DAO 

 

프로젝트 - src/main/java - kr.co.ch09 - dao 패키지 생성 - User1DAO.java 생성

package kr.co.ch09.dao;

import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import kr.co.ch09.vo.User1VO;

@Mapper
@Repository
public interface User1DAO {

	public int insertUser1(User1VO vo);
	public User1VO selectUser1(String uid);
	public List<User1VO> selectUser1s();
	public int updateUser1(User1VO vo);
	public int deleteUser1(String uid);
	
}

 

 


10. Service

 

src/main/java - kr.co.ch09.service 생성 - User1Service 생성

package kr.co.ch09.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.co.ch09.dao.User1DAO;
import kr.co.ch09.vo.User1VO;

@Service
public class User1Service {

	@Autowired
	private User1DAO dao;
	
	public int insertUser1(User1VO vo) {
		return dao.insertUser1(vo);
	};
	public User1VO selectUser1(String uid) {
		return dao.selectUser1(uid);
	};
	public List<User1VO> selectUser1s(){
		return dao.selectUser1s();
	};
	public int updateUser1(User1VO vo) {
		return dao.updateUser1(vo);
	};
	public int deleteUser1(String uid) {
		return dao.deleteUser1(uid);
	};
	
}

 

 


11. Controller

 

src/main/java - kr.co.ch09.controller - User1Controller.java 생성

package kr.co.ch09.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import kr.co.ch09.service.User1Service;
import kr.co.ch09.vo.User1VO;

@Controller
public class User1Controller {
	
	@Autowired
	private User1Service service;

	@ResponseBody
	@GetMapping("/user1")
	public List<User1VO> list1() {
		List<User1VO> users = service.selectUser1s();
		return users;
	}
	
	@ResponseBody
	@GetMapping("/user1/{id}")
	public User1VO list2(@PathVariable("id") String uid) {
		return service.selectUser1(uid);
	}
	
	@ResponseBody
	@PostMapping("/user1")
	public Map<String, Integer> register(User1VO vo) {
		int result = service.insertUser1(vo);
		
		Map<String, Integer> resultMap = new HashMap<>();
		resultMap.put("result", result);
		
		return resultMap; 
	}
	
	@ResponseBody
	@PutMapping("/user1")
	public Map<String, Integer> modify(User1VO vo) {
		int result = service.updateUser1(vo);
		
		Map<String, Integer> resultMap = new HashMap<>();
		resultMap.put("result", result);
		
		return resultMap; 
	}
	
	@ResponseBody
	@DeleteMapping("/user1/{id}")
	public Map<String, Integer> delete(@PathVariable("id") String uid) {
		
		int result = service.deleteUser1(uid);
		
		Map<String, Integer> resultMap = new HashMap<>();
		resultMap.put("result", result);
		
		return resultMap; 
	}

}

 

 


실행

 

[user1 목록1] 선택 시 

 

[user1 목록2] 선택 시 

 

[user1 등록] 선택 시 

 

[user1 수정] 선택 시