React+Spring Boot

상품목록

작성자
vita
작성일
2023-11-19 21:57
조회
347

상품목록

이제 본격적으로 기능을 구현하겠습니다.

먼저 상품목록 출력 기능입니다.

상품 목록의 전반적인 흐름은 아래와 같습니다.

 

React에서 주소창에 http://localhost:3000 라고 입력하면 상품목록이 출력됩니다.

모든 요청은 항상 Controller를 경유하게 됩니다.

ProductController 는 ProductDAO 에게 자료를 요청합니다.

ProductDAO 는 mybatis mapper인 product.xml 에 있는 sql 명령어를 실행하여 결과를 Controller에 되돌려줍니다.

Controller는 그 자료를 저장하여 React의 ListProduct.js 에 json 형태로 리턴합니다.

React의 ListProduct에서는 서버에서 받은 json 데이터를 변환하여 화면에 반영합니다.

 

 

1. package.json (React)

FrontEnd(React)에서 BackEnd(Spring boot)를 호출하기 위해 프록시 설정을 합니다.

React의 기본 포트는 3000번 입니다. Spring Boot의 기본포트는 8080번 입니다.  포트가 다르므로 호출이 되지 않는 문제가 발생합니다.  이 문제를 해결하기 위해 프록시 설정을 하는 것입니다.

package.json 파일의 끝부분에 아래에 표시된 코드를 추가합니다.

 

[생략]

    ]

  },

  "proxy": "http://localhost"

}

 

2. components 디렉토리 추가

 

React는 한 페이지에 모든 화면구성 요소를 다 표현합니다.  

세부적인 기능들을 만들고 App.js에서 url 에 따라 화면을 조합하는 방식으로 만들 것입니다.

c:/react/frontend/src/ 하위에 components 디렉토리를 만듭니다.

 

3. main.css (React)

 

React에서 사용할 css를 간단히 만듭니다.

c:/react/frontend/src/components/ 디렉토리 하위에 main.css 파일을 생성합니다.

주로 글꼴과 하이퍼링크 관련 스타일만 작성했습니다.  추가적으로 필요한 스타일들을 작성하시면 됩니다.

 

파일 위치: c:/react/frontend/src/components/main.css

@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);

body {

    font-family: 'Nanum Gothic', serif;

    margin: 10px;

}

a:link {

    text-decoration: none;

    color: blue;

}

a:hover {

    text-decoration: underline;

    color: red;

}

 

a:visited {

    text-decoration: none;

}

 

a:active {

    text-decoration: none;

    color: yellow;

}

4. ProductItem.js (React)

개별 상품의 내용을 출력하기 위한 파일을 만듭니다.

c:/react/frontend/src/components 하위에 ProductItem.js 파일을 생성합니다.

 

파일 위치: c:/react/frontend/src/components/ProductItem.js

import React from 'react';

import './main.css'

function ProductItem({ product_code, product_name, price, filename }) {

  let loading = false;

  const url = `http://localhost/static/images/${filename}`;

  if (loading) {

    return (

      <div>loading</div>

    )

  } else {

    let img = '';

    if (filename !== '-') {

      img = `<img src=${url} width='100px' height='100px'/><br />`;

    } else {

      img = '[상품 이미지 미등록]<br />';

    }

    return (

      <div style={{ margin: '5px' }}>

        <span dangerouslySetInnerHTML={{ __html: img }}></span>

          상품명 : {product_name}<br />

          가격: {price}원

        <br /><br />

      </div>

    )

  }

}

export default ProductItem;

 

[해설]

 

import React from 'react';

 

import 명령어로 필요한 외부 기능들을 불러옵니다.

 

import './main.css’

 

현재 디렉토리의 main.css 파일을 불러옵니다.

 

 

function ProductItem({ product_code, product_name, price, filename })

 

함수 선언문입니다.  함수의 형식은 아래와 같습니다.

 

function 함수이름(전달할값) {

 

}

 

 

  let loading = false;

 

서버의 데이터를 불러오는 중이면 true, 모두 불러오면 false 설정할 변수입니다.

 

  const url = `http://localhost/static/images/${filename}`;

 

상품 이미지를 표시할 서버의 url 입니다.

 

 




  if (loading) {

    return (

      <div>loading</div>

    )

  }

 

서버의 데이터를 불러오는 중이면 화면에 표시할 내용입니다.

 

  } else {

 

서버의 데이터를 모두 불러오면

 

    let img = '';

    if (filename !== '-') {

      img = `<img src=${url} width='100px' height='100px'/><br />`;

    } else {

      img = '[상품 이미지 미등록]<br />';

    }

 

상품 이미지가 등록된 경우이면 이미지를 표시하고 그렇지 않으면 [상품 이미지 미등록] 메시지를 출력합니다.

 

    return (

      <div style={{ margin: '5px' }}>

        <span dangerouslySetInnerHTML={{ __html: img }}></span>

          상품명 : {product_name}<br />

          가격: {price}원

        <br /><br />

      </div>

    )

 

React에서는 변수에 태그를 사용할 경우 태그를 단순한 텍스트로 화면에 출력합니다.  <xmp> <script> 등의 위험한 태그를 막기 위해서입니다.  여기서는 단순히 이미지만을 표시하기 위한 것이므로 위험을 감수하고 사용하겠다는 것입니다.

 

사용 방법은 아래와 같습니다.

 

dangerouslySetInnerHTML={{ __html: 변수명 }}

 

export default ProductItem;

 

지금까지 작성한 ProductItem.js 기능을 외부에서 사용할 수 있도록 설정합니다.

 

5. ListProduct.js (React)

 

개별 상품 출력 내용들을 묶어서 상품 목록을 출력하는 기능을 만듭니다.

 

파일 위치: c:/react/frontend/src/components/ListProduct.js

import React, { useRef, useEffect, useState } from 'react';

import './main.css';

import ProductItem from './ProductItem';

 

function ListProduct() {

  const [items, setProductList] = useState([]);

 

 

  function getList(url) {

    fetch(url)

      .then(response => { return response.json(); })

      .then(data => { setProductList(data); });

  }

  useEffect(() => { getList('/list'); }, []);

 

  return (

    <>

      <h2>상품목록</h2>

      등록된 상품수: {items.length}

      <br /><br />

      <div style={{

        display: 'grid',

        gridTemplateRows: '1fr',

        gridTemplateColumns: '1fr 1fr 1fr 1fr 1fr',

      }}>

 

        {items.map(

          ({ product_code, product_name, price, filename }) => (

            <ProductItem

              product_code={product_code}

              product_name={product_name}

              price={price}

              filename={filename}

              key={product_code}

            />

          )

        )}

      </div>

    </>

  );

};

export default ListProduct;

 

 

[해설]

 

  const [items, setProductList] = useState([]);

 

상품목록을 items 변수에 저장합니다.

상품목록을 세팅하는 함수는 setProductList 함수입니다.

상품목록은 수시로 변경될 수 있으므로 useState를 사용했습니다.

 

 

    fetch(url)

      .then(response => { return response.json(); })

      .then(data => { setProductList(data); });

 

fetch 함수는 서버에 데이터를 요청하여 받는 함수입니다.

아래의 형식대로 작동합니다.

 

fetch(서버주소).then( 클라이언트에서 실행할 동작 )

 

서버에 상품 목록 데이터를 요청합니다.

데이터가 도착하면 json 형식으로 바꿉니다.

json 데이터를 setProductList 함수에 입력하여 items 변수에 저장합니다.

 

  useEffect(() => { getList('/list'); }, []);

 

ListProduct.js 를 모두 불러오면 서버에 데이터를 요청하는 코드입니다.

 

  return (

    <>

    </>

  )

 

return() 함수에는 제일 바깥쪽에 하나의 태그만 쓸 수 있습니다.

<></>를 사용하여 2개 이상의 태그를 감쌀 수 있습니다.

 

      등록된 상품수: {items.length}

 

items는 상품 리스트입니다.

items.length는 상품 리스트의 데이터가 몇개인지 표시합니다.

 

  <div style={{

    display: 'grid',

    gridTemplateRows: '1fr',

    gridTemplateColumns: '1fr 1fr 1fr 1fr 1fr',

  }}>

 

상품목록을 한 줄에 5개씩 표현하기 위하여 fr(fraction)을 사용했습니다.  

 

gridTemplateRows: '1fr

 

한 줄에 하나의 row를 사용합니다.

 

gridTemplateColumns: '1fr 1fr 1fr 1fr 1fr’

 

한 줄에 5개의 컬럼을 사용합니다.  5개의 컬럼의 비율은 모두 같습니다.

 

        {items.map(

          ({ product_code, product_name, price, filename }) => (

            <ProductItem

              product_code={product_code}

              product_name={product_name}

              price={price}

              filename={filename}

              key={product_code}

            />

          )

        )}

 

map 함수는 반복 처리를 해주는 함수입니다.

아래와 같은 형식으로 사용합니다.

 

{집합변수.map( 입력데이터 => 출력데이터 ) }

 

집합변수 자리에 items가 들어갔습니다.

상품리스트에서 첫번째 상품부터 마지막 상품까지 반복하여 출력하라는 뜻입니다.

 


 

            <ProductItem

              product_code={product_code}

              product_name={product_name}

              price={price}

              filename={filename}

              key={product_code}

            />

 

앞에서 미리 작성한 ProductItem.js 컴포넌트를 불러와서 출력시킵니다.  이렇게 컴포넌트를 미리 작성하면 복잡한 코드를 단순화시킬 수 있습니다.

 

6. App.js (React)

React에서 메인 역할은 App.js 가 담당합니다.

App.js 에서 ListProduct.js 를 불러와야 합니다.

앞으로 추가할 컴포넌트들을 구분하기 위하여 url 을 기반으로 정리할 것입니다.

vscode의 터미널에서 패키지를 추가 설치합니다.

 

npm install react-router --save

 

npm install react-router-dom --save

 

패키지를 설치할 때는 npm install 패키지이름 명령어를 사용합니다.

react-router 와 react-router-dom 2가지를 설치합니다.

 

파일 위치: c:/react/frontend/src/App.js

import React from 'react';

import { Routes, Route } from 'react-router';

import { BrowserRouter } from 'react-router-dom';

 

import ListProduct from './components/ListProduct';

 

function App() {

  console.warn = function no_console() { };

  return (

    <>

      <BrowserRouter>

        <Routes>

          <Route path='/' element={<ListProduct />} />

        </Routes>

      </BrowserRouter>

    </>

  );

}

export default App;

 

[해설]

 

  console.warn = function no_console() { };

 

React 는 문법이 엄격한 편입니다. 콘솔창에 많은 경고와 에러 메시지가 출력됩니다. 효율적인 디버깅을 위해 경고는 출력하지 않게 하는 옵션입니다.

 

 

          <Route path='/' element={<ListProduct />} />

 

App.js 에서 라우터를 이용하여 여러개의 컴포넌트를 선택하여 화면에 출력할 수 있습니다.

http://localhost:3000/   이렇게 시작 페이지를 입력하면 ListProduct.js 내용이 화면에 출력됩니다.

 



 

7. Spring Starter 프로젝트 만들기 (Spring Boot)

Spring Boot 애플리케이션을 만들기 위해서 File > New > Other 를 클릭합니다.  


 

Spring Starter Project를 클릭합니다.

 


 

프로젝트 이름, 패키지 이름, 자바 버전을 입력합니다.

 

프로젝트 이름 : product

Type : Maven

패키지 이름 : com.example.product

Java Version : 8

 


 

Spring Boot Version은 2.7.17 로 하겠습니다.

프로젝트에서 사용할 라이브러리들을 추가합니다.

SQL 에서 JDBC API, Mybatis Framework, MariaDB Driver 를 체크합니다.

Web 에서 Spring Web 을 체크합니다.

 


 

8. jsp 사용을 위한 디렉토리 추가 (Spring Boot)

Spring Starter Project 는 기본적으로 템플릿 사용을 권장하고 있습니다.  타임리프 등의 템플릿을 사용하려면 새로운 문법을 익혀야 합니다.  여기서는 jsp에 익숙하신 분들이 이해하기 쉽도록 템플릿 대신 jsp 를 사용하겠습니다.

jsp를 사용하기 위해서는 src/main 하위에 디렉토리들을 직접 추가해야 합니다.

추가할 디렉토리들은 아래와 같습니다.

 

src/main/webapp

src/main/webapp/static

src/main/webapp/static/css

src/main/webapp/static/images

src/main/webapp/WEB-INF

src/main/webapp/WEB-INF/views

 

src/main 하위에 아래의 구조대로 디렉토리들을 추가합니다.

 


 

9. pom.xml 라이브러리 추가 (Spring Boot)

Spring Boot는 메이븐 빌드 도구를 사용하고 있습니다.  프로젝트 맨 아래에 있는 pom.xml 을 열어서 dependencies 태그 하위에 3개의 라이브러리들을 추가하겠습니다.

 

<?xml version="1.0" encoding="UTF-8"?>

[생략]

<dependencies>

        <dependency>

            <groupId>commons-fileupload</groupId>

            <artifactId>commons-fileupload</artifactId>

            <version>1.4</version>

        </dependency>

        <dependency>

            <groupId>org.apache.tomcat.embed</groupId>

            <artifactId>tomcat-embed-jasper</artifactId>

            <scope>provided</scope>

        </dependency>

</dependencies>

 

commons-fileupload 는 파일 업로드를 지원하는 라이브러리입니다.

tomcat-embed-jasper 는 jsp를 지원하는 라이브러리입니다.

 

10. mybatis mapper 디렉토리 생성 (Spring Boot)

Spring Boot 에서 sql 명령어를 실행시킬 때 많이 사용하는 기술은 mybatis 입니다.  

mybatis 는 주로 xml 파일에 SQL 명령어를 작성합니다.  이 파일을 mapper 라고 합니다.

mybatis mapper xml 파일을 저장하기 위하여 src/main/static 하위에 mappers 패키지를 생성합니다.

 


 


 

11. application.properties (Spring Boot)

src/main/resources 디렉토리에 있는 application.properties 파일을 편집합니다.  이 파일에 데이터베이스 연결 정보 등 웹애플리케이션의 중요한 설정 정보를 작성합니다.

 

파일 위치: src/main/resources/application.properties

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver

spring.datasource.url=jdbc:mariadb://localhost:3306/web

spring.datasource.username=user

spring.datasource.password=1234

 

server.port=80

 

spring.mvc.view.prefix=/WEB-INF/views/

spring.mvc.view.suffix=.jsp

 

server.error.whitelabel.enabled=false

 

spring.servlet.multipart.maxFileSize=10MB

spring.servlet.multipart.maxRequestSize=10MB

 

[해설]

 

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver

 

먼저 Spring 에서 MariaDB 데이터베이스에 연결하기 위한 설정을 합니다.  org.mariadb.jdbc.Driver.Driver 는 MariaDB 드라이버 클래스의 이름입니다.

 

 

spring.datasource.url=jdbc:mariadb://localhost:3306/web

 

MariaDB 데이터베이스 연결 문자열입니다.  

jdbc:mariadb://호스트:포트/데이터베이스 형식으로 되어 있습니다.

MariaDB는 3306번을 기본 포트로 사용합니다.

데이터베이스 이름은 web으로 하겠습니다.

 

spring.datasource.username=user

spring.datasource.password=1234

 

MariaDB 접속에 필요한 아이디는 user 이고 비밀번호는 1234 입니다.

 

server.port=80

 

Spring Boot에는 웹서버 프로그램인 아파치 톰캣이 내장되어 있습니다.  웹서비스 포트 번호는 기본적으로 80번을 사용하는 것이 좋습니다.  

포트번호가 80번이면 http://localhost:80 에서 포트번호를 생략하여 http://localhost 로 입력합니다.

포트번호가 8080이라면 http://localhost:8080 이라고 입력합니다.  포트번호가 80이 아닌 경우 반드시 포트번호를 입력해야 합니다.

포트번호를 80번으로 설정하겠습니다.  다른 프로그램에서 이미 80 포트를 사용하고 있다면 에러가 발생합니다.  그럴 경우 포트번호를 다른 번호로 변경하고 다시 실행해야 합니다.

 

spring.mvc.view.prefix=/WEB-INF/views/

spring.mvc.view.suffix=.jsp

 

우리는 웹페이지 출력을 위해 템플릿을 사용하지 않고 jsp 를 사용할 것입니다.  jsp 페이지의 경로는 /WEB-INF/views/ 디렉토리에 있는 jsp 파일로 설정할 것입니다.  /WEB-INF/views/index.jsp , /WEB-INF/views/list.jsp 등으로 입력할 것입니다.

spring.mvc.view.prefix 는 jsp 경로의 접두사이고 spring.mvc.view.suffix 는 접미사입니다.

나중에 컨트롤러에서 return “index”; 라고 하면

/WEB-INF/views/index.jsp  페이지로 이동을 하게 됩니다.

복잡한 페이지의 경로를 짧게 작성하고자 하는 방법입니다.

 

server.error.whitelabel.enabled=false

 

에러가 발생할 경우에 기본적으로 표시되는 에러 페이지를 사용하지 않는 옵션입니다.

 

 

spring.servlet.multipart.maxFileSize=10MB

spring.servlet.multipart.maxRequestSize=10MB

 

파일 업로드의 최대 용량을 10 메가 바이트로 설정하겠습니다.  사이즈는 조정할 수 있습니다.  

maxFileSize와 maxRequestSize 2개의 속성을 같은 값으로 설정하면 됩니다.

 

12. ProductApplication.java(Spring Boot)

Spring Starter Project 의 시작 클래스는 프로젝트이름+Application.java 클래스입니다.  이번 실습에서는 ProductApplication.java 클래스가 시작 클래스입니다.

mybatis 관련 설정을 하기 위하여 method 를 추가하겠습니다.  빨간색으로 표시된 부분만 작성하시면 됩니다.

 

파일위치: src/main/java/com/example/product/ProductApplication.java

package com.example.product;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.mybatis.spring.SqlSessionTemplate;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.core.io.Resource;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

@SpringBootApplication

public class ProductApplication {

    public static void main(String[] args) {

        SpringApplication.run(ProductApplication.class, args);

    }

    @Bean

    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();

        bean.setDataSource(dataSource);

        Resource[] res = new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml");

        bean.setMapperLocations(res);

        return bean.getObject();

    }

    @Bean

    public SqlSessionTemplate sqlSession(SqlSessionFactory factory) {

        return new SqlSessionTemplate(factory);

    }

}

 

[해설]

 

@Bean

    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

 

@Bean 어노테이션은 Java 객체를 만드는 명령어입니다.  웹서버가 시작될 때 이 method가 실행되면서 SqlSessionFactory 객체가 만들어지게 됩니다.

 

Resource[] res = new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml");

 

여기서의 classpath는 src/main/resources 디렉토리를 의미합니다.

src/main/resources/mappers 패키지 하위에 xml 파일을 작성할 것입니다.  mapper xml 파일에는 sql 명령어들이 저장됩니다.    

 

13. mybatipse 플러그인 설치 (Spring Boot)

mybatis의 mapper는 xml 문서 형식으로 작성합니다.  작성을 좀더 편리하게 하기 위하여 mybatipse 플러그인을 설치하겠습니다.

STS의 Help > Eclipse Marketplace 메뉴의 검색란에 mybatipse 를 입력하여 조회합니다.

MyBatipse 1.2.5 를 설치합니다.  Install 버튼을 누릅니다.

 


 

I accept the terms of the license agreement 를 선택하고 [Finish] 버튼을 누릅니다.(버전에 따라서 이 화면이 나타나지 않을 수도 있습니다.)

 


 

위의 화면이 아닌 아래와 같은 화면이 표시될 수 있습니다.  Unsigned 체크박스에 체크한 후 Trust Selected 버튼을 누릅니다.

 


 

설치가 완료되면 [Restart Now] 버튼을 눌러서 STS를 재시작합니다.

 


 

14. product.xml (Spring Boot)

src/main/resources 하위의 mappers 패키지에 product.xml 파일을 생성합니다.

 


 

검색란에 mybatis를 입력하여 MyBatis XML Mapper를 선택하고 [Next] 버튼을 누릅니다.

 


 

File name에 product.xml 을 입력하고 [Finish] 버튼을 누릅니다.

 


 

아래의 코드를 입력합니다.

<mapper namespace=“mappers.product”> 부분을

<mapper namespace=“product”>로 수정합니다.

 

파일 위치: src/main/resources/mappers/product.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 

<mapper namespace="product">

 

    <select id="list" resultType="java.util.Map">

        select * from product

        order by product_name

    </select>

    

</mapper>    

 

[해설]

 

<?xml version="1.0" encoding="UTF-8"?>

 

이 파일이 xml 문서임을 나타내는 구문입니다.

xml은 Extended Markup Language의 약자입니다.  html과 달리 xml은 태그를 자유롭게 만들고 사용할 수 있습니다.  xml은 주로 데이터를 주고 받을 때 표준 형식으로 사용합니다.  또는 프로그래밍의 환경설정, 화면 구성 등의 다양한 용도로 사용됩니다.

 

<mapper namespace="product">

 

현재 작성하고 있는 파일을 mapper 라고 합니다.  데이터베이스의 레코드와 Java 클래스를 매핑시켜 주는 역할을 하기 때문입니다.  

namespace는 SQL 명령어들을 구분하기 위해서 붙이는 식별자입니다.  

 

앞의 ProductDAO 에서 작성했던 코드를 다시 보겠습니다.

 

public List<Map<String, Object>> list() {

        return sqlSession.selectList("product.list");

}

 

여기서 product.list 는 namespace가 product 이고 id가 list 인 sql 명령어를 실행시키라는 뜻입니다.

 

<mapper namespace="product">

<select id="list" resultType="java.util.Map">

 

resultType="java.util.Map" 은 sql 명령어를 실행했을 때 1개의 레코드를 저장할 Java 자료형으로 Map을 지정한 것입니다.

 

 

<select id="list" resultType="java.util.Map">

        select * from product

        order by product_name

</select>

 

sql 명령어의 실행 결과가 Map에 저장되어 dao로 리턴되고 다시 Controller에 리턴됩니다.

 

public List<Map<String, Object>> list() {

  return sqlSession.selectList("product.list");

}

 

 

Controller의 list() method는 React의 ListProduct.js 에 자료를 넘기게 됩니다.

 

    @RequestMapping("/list")

    public List<Map<String, Object>> list(@RequestParam(defaultValue = "") String product_name, ModelAndView mav) {

        return productDao.list(product_name);

    }


15. ProductDAO.java (Spring Boot)

com.example.product 패키지에서 우클릭하고 New > Class를 클릭합니다.  클래스 이름은 ProductDAO 입니다.  

 


 

클래스를 만든 후 아래의 코드를 작성합니다.

 

 



파일위치: src/main/java/com/example/product/ProductDAO.java

package com.example.product;

import java.util.List;

import java.util.Map;

import org.apache.ibatis.session.SqlSession;

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

import org.springframework.stereotype.Repository;

 

@Repository

public class ProductDAO {

    @Autowired

    SqlSession sqlSession;

 

    public List<Map<String, Object>> list() {

        return sqlSession.selectList("product.list");

    }

}

 

[해설]

 

@Repository

public class ProductDAO

 

@Repository 어노테이션은 현재 클래스를 Spring Framework에서 관리하는 데이터 처리를 위한 bean으로 등록시키는 역할을 합니다.  

 

@Repository 어노테이션이 없다면 아래와 같이 ProductDAO 클래스의 객체를 만드는 작업을 직접 해야 합니다.

 

ProductDAO productDao=new ProductDAO();

 

@Repository 어노테이션이 있으므로 아래와 같이 @Autowired 어노테이션을 사용하여 간단히 사용할 수 있습니다.

 

@Autowired

ProductDAO productDao;

 

 

@Repository

public class ProductDAO

 

DAO는 Data Access Object의 약자입니다.  주로 데이터 처리를 하는 클래스에 DAO라는 이름을 붙입니다.

 

sql 명령어를 실행시킬 때 많이 사용하는 기술은 mybatis입니다.  

시작 클래스인 ProductApplication.java 클래스의 sqlSession() method를 다시 보겠습니다.

 

    @Bean

    public SqlSessionTemplate sqlSession(SqlSessionFactory factory) {

        return new SqlSessionTemplate(factory);

    }

 

@Bean 어노테이션은 Java 객체를 만드는 어노테이션입니다.  Spring Framework이 시작될 때 method 이름인 sqlSession bean이 만들어집니다.

 

    @Autowired

    SqlSession sqlSession;

 

@Autowired 어노테이션을 사용하여 서버가 시작될 때 이미 만들어진 sqlSession bean을 연결시킵니다.

 

 

public List<Map<String, Object>> list(String product_name) {

        return sqlSession.selectList("product.list", "%" + product_name + "%");

}

 

다음에 작성하게 될 product.xml의 쿼리를 호출하는 코드입니다.

상품이름을 전달하여 해당되는 상품의 리스트를 리턴합니다.  상품이름이 빈값일 경우 모든 상품들을 리턴하게 됩니다.

 

16. ProductController.java (Spring Boot)

 

com.example.product 패키지에서 우클릭하고 ProductController 클래스를 생성합니다.  아래의 코드를 입력합니다.

 

파일위치: src/main/java/com/example/product/ProductController.java

package com.example.product;

 

import java.util.List;

import java.util.Map;

 

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

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class ProductController {

 

    @Autowired

    ProductDAO productDao;

 

    @RequestMapping("/list")

    public List<Map<String, Object>> list() {

        return productDao.list();

    }

 

}

 

[해설]

 

@RestController

public class ProductController

 

@RestController 어노테이션이 붙은 클래스는 Spring Framework에서 관리하는 bean입니다.  bean은 Java 클래스의 객체를 의미합니다.  웹애플리케이션이 시작될 때 @RestController 어노테이션이 붙은 클래스가 자동으로 실행되고 메모리에 로딩됩니다.  @RestController 는 호출한 곳으로 데이터를 넘길 수도 있고 jsp 화면으로 넘길 수도 있는 기능입니다.

 

 

@Autowired

ProductDAO productDao;

 

@Autowired 어노테이션은 ProductDAO 클래스의 객체를 productDao 참조변수에 연결시켜주는 역할을 합니다.   이것을 어려운 용어로 의존관계 주입이라고 합니다.

 

아래와 같은 코드는 참조변수만 있고 실제로 가리키는 내용이 없으므로 아무 일도 할 수 없는 변수입니다.

 

ProductDAO productDao;

 

우변에 ProductDAO 클래스의 객체가 생성되어 있어야 참조변수를 통해 method를 호출할 수 있습니다.

 

ProductDAO productDao=new ProductDAO();

 

ProductDAO 클래스에는 @Repository 라는 어노테이션이 붙어 있습니다.  서버가 시작될 때 ProductDAO도 자동으로 실행되고 메모리에 로딩이 된 상태입니다.

 

@Repository

public class ProductDAO

 

 

    @RequestMapping("/list")

    public List<Map<String, Object>> list() {

        return productDao.list();

    }

 

dao가 보내준 데이터를 React 쪽으로 다시 보내는 코드입니다.

 

 

17. 상품 목록 실행 결과 확인

프로젝트에서 우클릭을 하고 Run As > spring boot app을 클릭하면 웹서버가 시작됩니다.

또는 com.example.product 패키지의 ProductApplication.java 클래스를 우클릭한 후 Run As > Spring Boot App 메뉴를 클릭합니다.

 


 

스프링 부트가 성공적으로 실행되었습니다.

Console에 에러가 없으면 정상적으로 실행된 것입니다.

Tomcat 서비스가 80번 포트에서 실행중임을 알 수 있습니다.

 


 

웹브라우저를 실행하신 후 주소창에 http://localhost를 입력하면 상품목록을 볼 수 있습니다.

아직은 아무 상품도 등록된 것이 없습니다.

상품 등록 기능까지 만든 후에 아래와 같은 화면을 볼 수 있습니다.

 

Scroll to Top