세션 저장
LoginForm.jsx
withCredentials: true 추가하기
if(!id)
setIdDiv('아이디를 입력해주세요');
else if(!pwd)
setPwdDiv('비밀번호를 입력해주세요')
else{
axios.get(`http://localhost:8080/spring/member/login?id=${id}&pwd=${pwd}`, {
withCredentials: true
})
.then(res => {
if (res.data === 'success') {
alert('로그인에 성공하였습니다.')
navigaete('/')
} else {
setLoginDiv('아이디 또는 비밀번호가 틀렸습니다')
}
})
}
MemberController.java
@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true") 추가하기
package member.controller;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import member.bean.MemberDTO;
import member.service.MemberService;
@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
@Controller
@RequestMapping(value="member")
public class MemberController {
@Autowired
private MemberService memberService;
//@RequestMapping(value="login", method = RequestMethod.GET)
@GetMapping(value = "login")
@ResponseBody
public String login(@RequestParam("id") String id, @RequestParam("pwd") String pwd) {
return memberService.login(id, pwd);
}
}
MemberServiceImpl.java
package member.service.impl;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import member.bean.MemberDTO;
import member.dao.MemberDAO;
import member.service.MemberService;
@Service
@Transactional
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberDAO memberDAO;
@Autowired
private HttpSession session;
@Override
public String login(String id, String pwd) {
Map<String, String> map = new HashMap<>();
map.put("id", id);
map.put("pwd", pwd);
MemberDTO memberDTO = memberDAO.login(map);
System.out.println("memberDTO = " + memberDTO);
if(memberDTO != null) {
session.setAttribute("memId", memberDTO.getId());
session.setAttribute("memName", memberDTO.getName());
session.setAttribute("memEmail", memberDTO.getEmail1() + "@" + memberDTO.getEmail2());
System.out.println("session = " + session.getAttribute("memId"));
return "success";
}
else
return "fail";
}
}
입력: axios.post( )
출력: axios.get( )
수정: axios.put( )
삭제: axios.delete( )
frontend
src
css
style.css
components
Main.jsx
member
LoginForm.jsx
board
boardWriteForm.jsx
App.js
코드 추가하기
<li><Link to='board/boardWriteForm' >글쓰기</Link></li>
<li><Link to='board/boardListForm' >글목록</Link></li>
<Route path='board/boardWriteForm' element={ <BoardWriteForm/>} />
<Route path='board/boardListForm' element={ <BoardListForm/>} />
import React from 'react';
import {BrowserRouter, Routes, Route, Link} from 'react-router-dom';
import Main from './components/main/Main';
import LoginForm from './components/member/LoginForm';
import './css/style.css';
import BoardWriteForm from './components/board/BoardWriteForm';
import BoardListForm from './components/board/BoardListForm';
const App = () => {
return (
<BrowserRouter>
<>
<nav className='menunav'>
<ul>
<li><Link to='/' >메인화면</Link></li>
<li><Link to='/loginForm' >로그인</Link></li>
<li><Link to='board/boardWriteForm' >글쓰기</Link></li>
<li><Link to='board/boardListForm' >글목록</Link></li>
</ul>
</nav>
{/* 화면에 보이는 영역 */}
<Routes>
<Route path='/' element={ <Main/>} />
<Route path='/loginForm' element={ <LoginForm/>} />
<Route path='board/boardWriteForm' element={ <BoardWriteForm/>} />
<Route path='board/boardListForm' element={ <BoardListForm/>} />
</Routes>
</>
</BrowserRouter>
);
};
export default App;
글쓰기
boardWriteForm.module.css
.board-write-container {
display: flex;
justify-content: center;
align-items: center;
height: 50vh; /* 필요에 따라 높이 조정 */
flex-direction: column;
}
.board-write-box {
border: 1px solid #ccc;
padding: 20px;
border-radius: 8px;
width: 400px; /* 너비를 적절히 조정 */
box-shadow: 0px 4px 10px rgba(82, 80, 80, 0.1);
}
.board-write-title {
margin-bottom: 10px;
font-weight: bold;
}
.board-write-input {
width: 100%;
padding: 8px;
box-sizing: border-box;
border-radius: 4px;
border: 1px solid #ddd;
margin-bottom: 10px;
}
.board-write-button {
width: 50%;
padding: 10px;
border-radius: 4px;
border: none;
background-color: #FFDFF6;
color: black;
font-weight: bold;
cursor: pointer;
}
.board-write-button:hover {
background-color: #f5b7e3;
}
.div {
color: red;
font-size: 10pt;
margin-bottom: 10px;
}
.button-container {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.board-reset-button {
width: 48%;
padding: 10px;
border-radius: 4px;
border: 1px solid #ddd;
background-color: #EDE1FF;
color: black;
font-weight: bold;
cursor: pointer;
}
.board-reset-button:hover {
background-color: #e0e0e0;
}
BoradWriteForm.jsx
import React, { useState } from 'react';
import axios from 'axios';
import styles from '../../css/BoardWriteForm.module.css';
import { useNavigate } from 'react-router-dom';
const BoardWriteForm = () => {
const [subject, setSubject] = useState('');
const [content, setContent] = useState('');
const [subjectDiv, setSubjectDiv] = useState('');
const [contentDiv, setContentDiv] = useState('');
const navigate = useNavigate();
const onSubmit = (e) => {
e.preventDefault();
setSubjectDiv('');
setContentDiv('');
if (!subject)
setSubjectDiv('제목을 입력해주세요');
else if (!content)
setContentDiv('내용을 입력해주세요');
else {
axios.get(`http://localhost:8080/spring/board/write?subject=${subject}&content=${content}`)
.then(res => {
if (res.data === 'success') {
alert('게시글 작성에 성공하였습니다.');
navigate('/board/boardListForm');
} else {
alert('게시글 작성에 실패하였습니다.');
}
});
}
};
const onReset = () => {
setSubject('');
setContent('');
setSubjectDiv('');
setContentDiv('');
};
나는 axios.get 방식으로 해서 했는데
이런식으로 게시글 작성하는 입력은 axios.post 방식으로 하는게 맞다고 하셨다 !!
수정해보자~!!
axios
.post(
'http://localhost:8080/spring/board/write?subject',
null,
{ params : {subject: subject, content: content}})
import React, { useState } from 'react';
import axios from 'axios';
import styles from '../../css/BoardWriteForm.module.css';
import { useNavigate } from 'react-router-dom';
const BoardWriteForm = () => {
const [subject, setSubject] = useState('');
const [content, setContent] = useState('');
const [subjectDiv, setSubjectDiv] = useState('');
const [contentDiv, setContentDiv] = useState('');
const navigate = useNavigate();
const onSubmit = (e) => {
e.preventDefault();
setSubjectDiv('');
setContentDiv('');
if (!subject)
setSubjectDiv('제목을 입력해주세요');
else if (!content)
setContentDiv('내용을 입력해주세요');
else {
axios
.post(
'http://localhost:8080/spring/board/write?subject',
null,
{ params : {subject: subject, content: content},
withCredentials: true
}
)
.then(res => {
alert('게시글 작성에 성공하였습니다.')
navigate('/board/boardListForm')
}
);
}
};
const onReset = () => {
setSubject('');
setContent('');
setSubjectDiv('');
setContentDiv('');
};
return (
<div className={styles['board-write-container']}>
<h2 className={styles['board-list-title']}>글쓰기</h2>
<form className={styles['board-write-box']} onSubmit={onSubmit}>
<div>
<label className={styles['board-write-title']}>제목</label>
<input type="text" className={styles['board-write-input']} name='subject' value={subject} onChange={e => setSubject(e.target.value)} />
<div id='subjectDiv' className={styles['div']}>{subjectDiv}</div>
</div>
<div>
<label className={styles['board-write-title']}>내용</label>
<textarea className={styles['board-write-input']} name='content' value={content} onChange={e => setContent(e.target.value)} rows={5} />
<div id='contentDiv' className={styles['div']}>{contentDiv}</div>
</div>
<div className={styles['button-container']}>
<button className={styles['board-write-button']} type="submit">글작성</button>
<button className={styles['board-reset-button']} type="button" onClick={ onReset }>초기화</button>
</div>
</form>
</div>
);
};
export default BoardWriteForm;
SpringReactProject
sprin.conf
SpringConfiguration.java
(spring 폴더 - db.properties 만들러가기)
(mapper 폴더 - memberMapper.xml 만들러가기)
member.controller
MemberController.java
member.service
MemberService.java (Interface)
member.service.impl
MemberServiceImpl.java
member.dao
MemberDAO.java (Interface)
board.controller
BoardController.java
board.service
Board Service.java (Interface)
board.service.impl
BoarderviceImpl.java
board.dao
Board DAO.java (Interface)
servlet-context.xml
<context:component-scan base-package="board.controller" />
root-context.xml
<context:component-scan base-package="board.bean" />
<context:component-scan base-package="board.dao" />
<context:component-scan base-package="board.service.impl"/>
BoardController.java
package board.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import board.bean.BoardDTO;
import board.service.BoardService;
@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
@RestController
@RequestMapping(value="board")
public class BoardController {
@Autowired
private BoardService boardService;
@PostMapping(value = "write")
@ResponseBody
public void write(@RequestParam String subject, @RequestParam String content) {
boardService.write(subject, content);
}
}
BoardService.java
package board.service;
import java.util.List;
import board.bean.BoardDTO;
public interface BoardService {
void write(String subject, String content);
}
BoardServiceImpl.java
package board.service.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import board.bean.BoardDTO;
import board.dao.BoardDAO;
import board.service.BoardService;
import member.service.MemberService;
@Service
@Transactional
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardDAO boardDAO;
@Autowired
private HttpSession session;
@Override
public void write(String subject, String content) {
String id = (String) session.getAttribute("memId");
String name = (String) session.getAttribute("memName");
String email = (String) session.getAttribute("memEmail");
Map<String, String> map = new HashMap<>();
map.put("id", id);
map.put("name", name);
map.put("email", email);
map.put("subject", subject);
map.put("content", content);
boardDAO.write(map);
boardDAO.refUpdate();
}
}
BoardDAO.java
package board.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import board.bean.BoardDTO;
@Mapper
public interface BoardDAO {
public int write(Map<String, String> map);
public void refUpdate();
}
boardMapper.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="board.dao.BoardDAO">
<insert id="write" parameterType="java.util.map" useGeneratedKeys="true" keyProperty="seq">
INSERT INTO board (id, name, email, subject, content)
VALUES (#{id}, #{name}, #{email}, #{subject}, #{content})
</insert>
<update id="refUpdate">
update board set ref=LAST_INSERT_ID() where seq=LAST_INSERT_ID()
</update>
</mapper>
<Route path='board/boardWriteForm' element={ <BoardWriteForm/>} />
<Route path='board/boardListForm' element={ <BoardListForm/>} />
위에꺼를
밑에 방식으로 자식라우터로 해서 변경할 수 있다 !!
<Route path='board/'>
<Route path='boardWriteForm' element={ <BoardWriteForm/>} />
<Route path='boardListForm' element={ <BoardListForm/>} />
</Route>
글목록
BoardListForm.module.css
.board-list-container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
width: 100%;
}
.board-list-title {
font-size: 24px;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
}
.board-list {
width: 100%;
max-width: 800px;
border-collapse: collapse;
text-align: left;
margin: 10px 0;
}
.board-list-header {
background-color: #ffdcf4; /* 헤더 배경색 적용 */
font-weight: bold;
}
.board-list-item {
display: grid;
grid-template-columns: 1fr 2fr 3fr 2fr 1fr;
padding: 15px;
border-bottom: 1px solid #ddd;
}
.board-list-item:nth-child(even) {
background-color: #fafafa;
}
.board-list-item h3, .board-list-item p {
margin: 0;
padding: 5px;
}
.post-title {
font-size: 16px;
font-weight: bold;
}
.post-content {
font-size: 14px;
color: #555;
}
.post-date {
font-size: 12px;
color: gray;
}
BoardListForm.jsx
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import styles from '../../css/BoardListForm.module.css';
const BoardListForm = () => {
const [list, setList] = useState([]);
useEffect(() => {
axios.get('http://localhost:8080/spring/board/list')
.then(res => {
console.log('응답 데이터:', res.data);
setList(res.data);
})
.catch(error => console.error('에러:', error));
}, []);
return (
<div className={styles['board-list-container']}>
<h2 className={styles['board-list-title']}>게시글 목록</h2>
<div className={styles['board-list']}>
<div className={`${styles['board-list-item']} ${styles['board-list-header']}`}>
<h3>번호</h3>
<h3>이름</h3>
<h3>제목</h3>
<h3>내용</h3>
<h3>날짜</h3>
</div>
{list.map((data) => (
<div key={data.seq} className={styles['board-list-item']}>
<p>{data.seq}</p>
<p>{data.name}</p>
<p>{data.subject}</p>
<p>{data.content}</p>
<p className={styles['post-date']}>
{new Date(data.logtime).toLocaleDateString()} {/* yyyy-mm-dd 형식으로 날짜 출력 */}
</p>
</div>
))}
</div>
</div>
);
};
export default BoardListForm;
BoardDTO.java
package board.bean;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class BoardDTO {
private int seq;
private String id;
private String name;
private String email;
private String subject;
private String content;
private int ref;
private int lev;
private int step;
private int pseq;
private int reply;
private int hit;
private Date logtime;
}
BoardController.java
@GetMapping(value = "list")
public List<BoardDTO> list() {
List<BoardDTO> list = boardService.getList();
return list;
}
BoardService.java
package board.service;
import java.util.List;
import board.bean.BoardDTO;
public interface BoardService {
public void write(String subject, String content);
public List<BoardDTO> getList();
}
BoardServiceImpl.java
@Override
public List<BoardDTO> getList() {
List<BoardDTO> list = boardDAO.getList();
System.out.println("list = " + list);
return list;
}
BoardDAO.java
package board.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import board.bean.BoardDTO;
@Mapper
public interface BoardDAO {
public int write(Map<String, String> map);
public void refUpdate();
public List<BoardDTO> getList();
}
boardMapper.xml
<select id="getList" resultType="boardDTO">
select * from board;
</select>
BoardController.java
@GetMapping(value = "list")
public List<BoardDTO> list() { //List<BoardDTO> 객체를 자동으로 JSON 배열로 변환하여 보낸다.
List<BoardDTO> list = boardService.getList();
return list;
}
list를 보내도 알아서 JSON 배열로 변환하여 보내준다.
나는 날짜를
<p className={styles['post-date']}>
{new Date(data.logtime).toLocaleDateString()} {/* yyyy-mm-dd 형식으로 날짜 출력 */}
</p>
이 형식으로 vscode에서 바꿨는데 강사님 답으로도 해보자 !!
BoardDTO.java
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.mm.dd")
private Date logtime;
package board.bean;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class BoardDTO {
private int seq;
private String id;
private String name;
private String email;
private String subject;
private String content;
private int ref;
private int lev;
private int step;
private int pseq;
private int reply;
private int hit;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd")
private Date logtime;
}
위에서 저렇게 하고
밑에서 찍어주면 똑같이 나온다.
<p>{data.logtime}</p>
강사님은 번호 / 제목 / 작성자 / 조회수 / 날짜를 출력하였다 !
return (
<div className={styles['board-list-container']}>
<h2 className={styles['board-list-title']}>게시글 목록</h2>
<div className={styles['board-list']}>
<div className={`${styles['board-list-item']} ${styles['board-list-header']}`}>
<h3>번호</h3>
<h3>제목</h3>
<h3>작성자</h3>
<h3>조회수</h3>
<h3>날짜</h3>
</div>
{list.map((data) => (
<div key={data.seq} className={styles['board-list-item']}>
<p>{data.seq}</p>
<p>{data.subject}</p>
<p>{data.name}</p>
<p>{data.hit}</p>
{/* <p className={styles['post-date']}>
{new Date(data.logtime).toLocaleDateString()} yyyy-mm-dd 형식으로 날짜 출력
</p> */}
<p>{data.logtime}</p>
</div>
))}
</div>
</div>
);
};
export default BoardListForm;
'REACT' 카테고리의 다른 글
DAY 81 - React - Redux (2024.10.31) (0) | 2024.10.31 |
---|---|
DAY 80 - Spring + React +MyBatis(MySQL) - 글 상세보기 (2024.10.30) (0) | 2024.10.30 |
DAY 79 - Spring + React +MyBatis(MySQL) (2024.10.29) (0) | 2024.10.30 |
DAY 78 - React HOMEWORK (2024.10.28) (0) | 2024.10.28 |
DAY 78 - React - useReducer / React-Router/ JSX (2024.10.28) (0) | 2024.10.28 |