๊ด€๋ฆฌ ๋ฉ”๋‰ด

JiYoung Dev ๐Ÿ–ฅ

[Spring Boot] Spring Boot - react ์—ฐ๋™ ์ค€๋น„ (2023.06.07) ๋ณธ๋ฌธ

์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

[Spring Boot] Spring Boot - react ์—ฐ๋™ ์ค€๋น„ (2023.06.07)

Shinjio 2023. 6. 7. 17:34

 

Spring Boot - React  ์—ฐ๋™ ์ค€๋น„

 

 

1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์ค€๋น„

 

 

 


auto_increment


์ž๋™์œผ๋กœ ์ˆซ์ž ๋“ค์–ด๊ฐ€๋„๋ก ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ!
ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์€ ์ฑ„์šฐ์ง€ ์•Š์œผ๋ฉด ๋จ

 

 

2. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

 

 

 

 

3. application.properties ์ž‘์„ฑ >> ๊ธฐ๋ณธ ์„ค์ •

 

#context-root : ์„œ๋ฒ„์ƒ์—์„œ ๋™์ž‘ํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝ๋กœ
#๋ฌด์กฐ๊ฑด slash๋กœ ์‹œ์ž‘ 
server.servlet.context-path=/shop
#server port number
server.port=8090

#view(jsp) : prefix, suffix
spring.mvc.view.prefix=/WEB-INF/Views/
spring.mvc.view.suffix=.jsp

# EX. DB์—ฐ๊ฒฐ์ •๋ณด  
spring.datasource.url=jdbc:mysql://localhost:3306/Boot?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=fullstack
spring.datasource.password=12345
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

 


4. ๊ธฐ๋ณธ ๊ตฌ์กฐ ๋งŒ๋“ค๊ธฐ

 

4-1. ํŒจํ‚ค์ง€ ์ƒ์„ฑ

 

4-2. mapper ๋งค์นญ์„ ์œ„ํ•œ ํด๋” ์ƒ์„ฑ 

 

4-3. ํด๋ž˜์Šค ํŒŒ์ผ ์ƒ์„ฑ

 

1) ๋ฐ์ดํ„ฐ (๋ชจ๋ธ)

 

package com.smhrd.shop.domain;

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

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Product {

	private String ptype;
	private String pcode;
	private String pname;
	private int price;
	private String color;
	private String img;

}

 

2) ProductController, ProductService, Product mapper ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ XML ํŒŒ์ผ ์ƒ์„ฑ

 

 

2-1) ProductController

 

package com.smhrd.shop.controller;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.smhrd.shop.service.ProductService;

@RestController
//CORS : Cross-Origin
@CrossOrigin("http://localhost:3000")
public class ProductController {
	//1. ๋ชจ๋“  ์ƒํ’ˆ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	//2. ํŠน์ • ์ƒํ’ˆ 1๊ฐœ์— ๋Œ€ํ•œ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	//๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ  ๋ชจ๋ธ๋งŒ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ! (๋ทฐ๋Š” react๋กœ ๋ณด์—ฌ์ค„ ์˜ˆ์ •) >> RestController
	
	@Autowired
	private ProductService service;
	
	//1. ๋ชจ๋“  ์ƒํ’ˆ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	@GetMapping("/")
	public JSONArray productList() {
		JSONArray array = service.productList();
		return array;
	}
	
	//2. ํ•œ๊ฐœ ์ƒํ’ˆ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	@GetMapping("/{pcode}")
	public JSONObject productOne(@PathVariable("pcode") String pcode) {
		JSONObject obj = service.productOne(pcode);
		return obj;
	}
}

 

๋ฆฌ์•กํŠธ์™€ ์—ฐ๋™ํ•˜๊ธฐ ์œ„ํ•ด Cross-Origin ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

 

2-2) ProductService

 

jsonArray๊ฐ€์ ธ๋กœ๋ฉด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ํ•„์š”

      <dependency>
          <groupId>co
m.googlecode.json-simple
</groupId>
          <artifactId>json-simple</artifactId>
          <version>1.1.1</version>
      </dependency>

 

package com.smhrd.shop.service;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import com.smhrd.shop.converter.ImageToBase64;
import com.smhrd.shop.converter.imageConverter;
import com.smhrd.shop.domain.Product;
import com.smhrd.shop.mapper.ProductMapper;

@Service
public class ProductService {
	
	@Autowired
	private ProductMapper mapper;
	
	@Autowired
	private ResourceLoader resourceLoader; //ํŠน์ • ๊ฒฝ๋กœ์— ์žˆ๋Š” ํŒŒ์ผ ๊ฐ€์ ธ์˜ค๊ธฐ
	
	//product ์ „์ฒด ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	public JSONArray productList() {
		List<Product> list = mapper.productList();
		
		//ํ˜„์žฌ list์•ˆ์˜ img๋Š” ํŒŒ์ผ๋ช…๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์Œ(์‹ค์ œํŒŒ์ผX). 
		//์‹ค์ œ ํ”„๋ก ํŠธ์— ๋„˜๊ฒจ์ค„ ๋•Œ๋Š” ์ด๋ฏธ์ง€ ์ž์ฒด๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•จ!
		//๋ถ€ํŠธ ์„œ๋ฒ„์— ์ด๋ฏธ์ง€ ์ €์žฅ >> ์ด๋ฏธ์ง€ ์ž์ฒด๋ฅผ ๋ฆฌ์•กํŠธ๋กœ ๋„˜๊ธธ ์˜ˆ์ • 
		//Product์— ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ ํŒŒ์ผ ์ด๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์‹ค์ œ ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ์™€์•ผํ•จ (static/img/...)
		//์Šคํ”„๋ง์—์„œ ๋ฆฌ์•กํŠธ๋กœ ํŒŒ์ผ์„ ์‘๋‹ตํ•ด์ค„ ๋•Œ ํŒŒ์ผ์˜ ํ˜•ํƒœ๊ฐ€ ๊ต‰์žฅํžˆ ์ค‘์š”ํ•จ!
		//ํŒŒ์ผ ์ž์ฒด๋ฅผ ๋„˜๊ธธ ์ˆ˜๋Š” ์—†์Œ
		//์–ด๋–ป๊ฒŒ ๋ณด๋‚ด์•ผ ํ•˜๋ƒ, ์ปดํ“จํ„ฐ๊ฐ€ ์•Œ์•„๋“ค์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ž(๋ฐ”์ดํŠธ) ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•จ
		//์ด๋ฏธ์ง€ ์ž์ฒด๋Š” ๋ฌธ์ž๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ!
		//์ตœ์ข…์ ์œผ๋กœ๋Š” Product์˜ img ํ•„๋“œ ๊ฐ’(ํŒŒ์ผ ์ด๋ฆ„)์„ ์ด๋ฏธ์ง€๋ฅผ byte๋กœ ๋ณ€ํ™˜๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พผ๊ฑธ๋กœ ์ˆ˜์ •ํ•ด์•ผํ•จ
		
		//JsonArray์— JsonObject๊ฐ€ ๋“ค์–ด์žˆ๋Š” ํ˜•์‹์œผ๋กœ ์‘๋‹ต
		//List >> JsonArray
		JSONArray jsonArray = new JSONArray();
		//List์•ˆ์˜ Product >> JsonObject
		imageConverter<File,String> converter = new ImageToBase64();
		for(Product p : list) {
			//1. img ํ•„๋“œ๊ฐ’ ์ˆ˜์ • (ํŒŒ์ผ์ด๋ฆ„ >> ์ด๋ฏธ์ง€ ๋ฐ”์ดํŠธ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜)
			//1-1. ๋ณ€ํ™˜ํ•  ํŒŒ์ผ ์‹ค์ œ ๊ฒฝ๋กœ ์ •์˜
			String filePath = "classpath:/static/img/" + p.getImg();
			Resource resource = resourceLoader.getResource(filePath); //ํŒŒ์ผ์— ๋Œ€ํ•œ ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
			String fileStringValue = null;
			try {
				fileStringValue = converter.convert(resource.getFile());
			}catch(IOException e) {
				e.printStackTrace();
			}
			
			//๊ฐ€์ง€๊ณ  ์˜จ product img๋ฅผ ๋ณ€ํ™˜๋œ ๋ฐ”์ดํŠธ ๋ฌธ์ž์—ด๋กœ ๋ณ€๊ฒฝ
			p.setImg(fileStringValue);
			
			//2. Product ๊ฐ์ฒด๋ฅผ JSONObject ํ˜•ํƒœ(key:value)๋กœ ๋ณ€ํ™˜
			JSONObject obj = new JSONObject(); //๋น„์–ด์žˆ๋Š” jsonObject ์ƒ์„ฑ
			obj.put("product", p); //jsonObject์— ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ product ๊ฐ์ฒด ์ €์žฅ
			jsonArray.add(obj); //JsonArray์— JsonObject ์ถ”๊ฐ€
		}
		return jsonArray;
	}
	
	public JSONObject productOne(String pcode) {
		Product product = mapper.productOne(pcode);
		
		imageConverter<File,String> converter = new ImageToBase64();
		
		String filePath = "classpath:/static/img/" + product.getImg();
		Resource resource = resourceLoader.getResource(filePath);
		String fileStringValue = null;
		try {
			fileStringValue = converter.convert(resource.getFile());
		}catch(IOException e) {
			e.printStackTrace();
		}
		
		product.setImg(fileStringValue);
		
		JSONObject obj = new JSONObject();

		obj.put("product", product);
		
		return obj;
	}
}

 

 

2-3) Product mapper ์ธํ„ฐํŽ˜์ด์Šค

 

package com.smhrd.shop.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.json.simple.JSONObject;

import com.smhrd.shop.domain.Product;

@Mapper
public interface ProductMapper {

	//Product ์ „์ฒด ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	public List<Product> productList();
	
	//Product ํ•œ ๊ฐœ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
	public Product productOne(String pcode);
	
}

 

2-4) Product mapper.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 ์ž‘์„ฑ
  namespace๋Š” mapper ์žˆ๋Š” ๊ฒฝ๋กœ ๊ทธ๋Œ€๋กœ ์ž‘์„ฑ -->
  <mapper namespace="com.smhrd.shop.mapper.ProductMapper">
  	<select id="productList" resultType="com.smhrd.shop.domain.Product">
  		select * from product;
  	</select>
  	
  	<select id="productOne" resultType="com.smhrd.shop.domain.Product">
  		select * from product where pcode = #{pcode}
  	</select>
  </mapper>

 

 

4-4. img ํŒŒ์ผ ๋ณ€ํ™˜์„ ์œ„ํ•œ ํด๋ž˜์Šค ํŒŒ์ผ ์ƒ์„ฑ

 

//ํ˜„์žฌ list์•ˆ์˜ img๋Š” ํŒŒ์ผ๋ช…๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์Œ(์‹ค์ œํŒŒ์ผX).

//์‹ค์ œ ํ”„๋ก ํŠธ์— ๋„˜๊ฒจ์ค„ ๋•Œ๋Š” ์ด๋ฏธ์ง€ ์ž์ฒด๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•จ!

//๋ถ€ํŠธ ์„œ๋ฒ„์— ์ด๋ฏธ์ง€ ์ €์žฅ >> ์ด๋ฏธ์ง€ ์ž์ฒด๋ฅผ ๋ฆฌ์•กํŠธ๋กœ ๋„˜๊ธธ ์˜ˆ์ •

//Product์— ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ ํ†ตํ•ด์„œ ์‹ค์ œ ํŒŒ์ผ ์ด๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์‹ค์ œ ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ์™€์•ผํ•จ (static/img/...)

//์Šคํ”„๋ง์—์„œ ๋ฆฌ์•กํŠธ๋กœ ํŒŒ์ผ์„ ์‘๋‹ตํ•ด์ค„ ๋•Œ ํŒŒ์ผ์˜ ํ˜•ํƒœ๊ฐ€ ๊ต‰์žฅํžˆ ์ค‘์š”ํ•จ!

//ํŒŒ์ผ ์ž์ฒด๋ฅผ ๋„˜๊ธธ ์ˆ˜๋Š” ์—†์Œ

//์–ด๋–ป๊ฒŒ ๋ณด๋‚ด์•ผ ํ•˜๋ƒ, ์ปดํ“จํ„ฐ๊ฐ€ ์•Œ์•„๋“ค์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ž(๋ฐ”์ดํŠธ) ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•จ

//์ด๋ฏธ์ง€ ์ž์ฒด๋Š” ๋ฌธ์ž๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ!

//์ตœ์ข…์ ์œผ๋กœ๋Š” Product์˜ img ํ•„๋“œ ๊ฐ’(ํŒŒ์ผ ์ด๋ฆ„)์„ ์ด๋ฏธ์ง€๋ฅผ byte๋กœ ๋ณ€ํ™˜๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พผ๊ฑธ๋กœ ์ˆ˜์ •ํ•ด์•ผํ•จ

 

1) ์ด๋ฏธ์ง€ ํŒŒ์ผ ์„œ๋ฒ„์— ์˜ฌ๋ฆฌ๊ธฐ

resources > static ํด๋” ์•„๋ž˜์— ์˜ฌ๋ฆฌ๊ธฐ

 

 

์ด๋ฏธ์ง€ ํŒŒ์ผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ํด๋ž˜์Šค ์ž‘์„ฑ

 

4-2) ํŒจํ‚ค์ง€ ์ƒ์„ฑ

 

4-3) ํด๋ž˜์Šค ์ƒ์„ฑ

imageConverter

file์„ String์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ

 

package com.smhrd.shop.converter;

import java.io.IOException;

//F : ํŒŒ์ผ
//S : ํŒŒ์ผ์„ ์–ด๋–ค ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•  ์ง€ ์ง€์ • (๋ฐ”์ดํŠธ ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด : String)
public abstract class imageConverter<F, S> {
	//<> : Generic, ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”ํ•  ๋•Œ ํ˜•ํƒœ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
	
	//์‹ค์ œ ๋ณ€ํ™˜ํ•  ๋•Œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•  ์ถ”์ƒ ๋ฉ”์„œ๋“œ ์ •์˜
	public abstract S convert(F f) throws IOException;
}

 

ImageToBase64

imageConverter์˜ converter๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ 

Base64 ๋ผ๋Š” ํด๋ž˜์Šค ํ™œ์šฉํ•˜์—ฌ ๋ณ€ํ™˜

 

commons-io ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ >> File ๋‹ค๋ฃฐ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
      </dependency>

 

package com.smhrd.shop.converter;

import java.io.File;
import java.io.IOException;
import java.util.Base64;

import org.apache.commons.io.FileUtils;

public class ImageToBase64 extends imageConverter<File, String> {

	@Override
	public String convert(File f) throws IOException {
		
		//ํŒŒ์ผ์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ฝ”๋“œ
		//1. ํŒŒ์ผ ๊ฐ€์ง€๊ณ  ์™€์„œ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ฝ๊ธฐ
		byte[] fileContent = FileUtils.readFileToByteArray(f);
		
		//2. ๋ฐ”์ดํŠธ๋ฐฐ์—ด ํ˜•ํƒœ๋ฅผ ์ธ์ฝ”๋”ฉํ•˜์—ฌ ๋ฌธ์ž์—ด๋กœ ๋ณ€๊ฒฝ(Base64)
		String result = Base64.getEncoder().encodeToString(fileContent);
		
		return result;
	}
}

 

 

๊ฒฐ๊ณผํ™”๋ฉด

 

 

add Request