📌 장바구니 기능 (로그인 인증이 필요한 기능)
1. DB 테이블 생성
1
2
3
4
5
6
| CREATE TABLE cart (
email VARCHAR(50),
prodcode INT,
quantity INT,
PRIMARY KEY (email, prodcode)
);
|
- 같은 사용자가 동일한 상품을 여러 번 담을 경우, 수량이 증가
2. Cart.java (DTO)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package com.shop.cafe.dto;
public class Cart {
private String email;
private int prodcode, quantity;
public String getEmail() {
return email;
}
public Cart(String email, int prodcode, int quantity) {
this.email = email;
this.prodcode = prodcode;
this.quantity = quantity;
}
public Cart() {
super();
}
// Getter & Setter & toString() 생략
}
|
3. CartnDao.java (MyBatis)
👉 장바구니 추가 기능을 DB에 연결.
1
2
3
4
| @Mapper
public interface CartDao {
void addToCart(Cart cart) throws Exception;
}
|
4. CartService.java (Service Layer)
👉 장바구니 추가 기능을 비즈니스 로직에 연결.
1
2
3
4
5
6
7
8
9
| @Service
public class CartService {
@Autowired
CartDao cartDao;
public void addToCart(Cart cart) throws Exception {
cartDao.addToCart(cart);
}
}
|
5. CartController.js (API 엔드포인트 + 인증 검사 포함)
👉 로그인된 사용자만 장바구니 추가 가능
- JWT 토큰을 이용한 로그인 인증 (authorization 헤더 활용)
- 30분 이내 활동한 경우에만 장바구니 담기 허용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| @RestController
@CrossOrigin("http://127.0.0.1:5500/")
public class CartController {
@Autowired
MemberService memberService;
@Autowired
CartService cartService;
@PostMapping("addToCart")
public String addToCart(@RequestHeader String authorization, @RequestBody Cart cart) {
try {
Login loginInfo = memberService.checkToken(authorization);
if (loginInfo != null && loginInfo.getLoginTime() != null) {
long now = System.currentTimeMillis(); // 현재 시간 (밀리초)
long lastRequestTime = loginInfo.getLoginTime().getTime(); // DB에서 가져온 로그인 시간
long interval = now - lastRequestTime;
if (interval <= 1800000) { // 30분 이내 로그인 유지
cart.setEmail(loginInfo.getEmail());
cart.setQuantity(1);
cartService.addToCart(cart);
return "ok";
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
|
6. cart.xml (MyBatis 설정)
ON DUPLICATE KEY UPDATE
:
같은 상품을 장바구니에 추가하면 수량 증가하도록 처리.
1
2
3
4
5
6
7
| <mapper namespace="com.shop.cafe.dao.CartDao">
<insert id="addToCart" parameterType="com.shop.cafe.dto.Cart">
INSERT INTO cart (email, prodcode, quantity)
VALUES (#{email}, #{prodcode}, #{quantity})
ON DUPLICATE KEY UPDATE quantity = quantity + VALUES(quantity);
</insert>
</mapper>
|
7. 로그인 인증 -> MemberService.java
- 로그인 시 토큰을 발급하고 DB에 저장.
- 로그인 시간도 저장하여 세션 유지 시간(30분) 적용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| @Service
public class MemberService {
@Autowired
MemberDao memberDao;
@Autowired
LoginDao loginDao;
public Login checkToken(String authorization) throws Exception {
return loginDao.checkToken(authorization);
}
public Login tokenLogin(Member m) throws Exception {
m = memberDao.login(m);
if (m != null) {
String nickname = m.getNickname();
if (nickname != null && !nickname.trim().equals("")) {
String email = m.getEmail();
String salt = UUID.randomUUID().toString();
byte[] originalHash = OpenCrypt.getSHA256(email, salt);
String myToken = OpenCrypt.byteArrayToHex(originalHash);
Login loginInfo = new Login(email, myToken, nickname, new Date());
loginDao.insertToken(loginInfo);
return loginInfo;
}
}
return null;
}
}
|
8. LoginDao.java (로그인 인증)
1
2
3
4
5
6
| @Mapper
public interface LoginDao {
void insertToken(Login login) throws Exception;
void deleteToken(String token) throws Exception;
Login checkToken(String authorization) throws Exception;
}
|
9. login.xml (로그인 인증)
- 로그인 시 토큰을 DB에 저장
- 로그인 시간이 자동으로
NOW()
로 기록됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <mapper namespace="com.shop.cafe.dao.LoginDao">
<select id="checkToken" parameterType="String" resultType="Login">
SELECT * FROM login WHERE token=#{token}
</select>
<insert id="insertToken" parameterType="Login">
INSERT INTO login(email, token, loginTime) VALUES(#{email}, #{token}, NOW())
</insert>
<delete id="deleteToken" parameterType="String">
DELETE FROM login WHERE token=#{token}
</delete>
</mapper>
|
10. secu.properties에서 세계표준 시를 제거
1
2
3
4
| DB_DRIVER=com.mysql.cj.jdbc.Driver
DB_URL=jdbc:mysql://localhost:3306/ureca
DB_USER=ureca
DB_PW=ureca
|
11. MemberService.java에서 tokenLogin시에 로그인 시간을 직접 입력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| public Login tokenLogin(Member m) throws Exception {
m=memberDao.login(m);
if(m!=null) {
String nickname=m.getNickname();
if(nickname!=null && !nickname.trim().equals("")) {
String email=m.getEmail();
String salt=UUID.randomUUID().toString();
System.out.println("salt:"+salt);
byte[] originalHash=OpenCrypt.getSHA256(email, salt);
String myToken=OpenCrypt.byteArrayToHex(originalHash);
System.out.println("myToken : "+myToken);
// 로그인 시간을 직접 입력
Login loginInfo=new Login(email, myToken, nickname, new Date());
loginDao.insertToken(loginInfo);
return loginInfo;
}
}
return null;
}
|
cart.js - 프론트엔드 요청
localStorage.getItem("token")
: 저장된 로그인 토큰을 가져와 Authorization
헤더에 포함.- 장바구니 추가 요청을 보냄.
1
2
3
4
5
6
7
8
| async function addToCart(prodcode) {
const cartResponse = await axios.post(
"http://localhost:8080/addToCart",
{ prodcode },
{ headers: { Authorization: localStorage.getItem("token") } } // 토큰 포함
);
console.log(cartResponse.data);
}
|
장바구니 담기 클릭 시, 테이블 모습
📌 RESTful API 란?
RESTfu에 대한 개념이 많아 따로 포스팅해보았다. RESTful API란?
✅ RESTful API 디자인 가이드
API URI는 직관적이고 일관성 있게 설계해야 함
✅ URI Naming Sample
HTTP Method | URI 예시 | 설명 |
---|
GET | /products | 전체 상품 조회 |
GET | /products/{id} | 특정 상품 조회 |
POST | /cart | 장바구니에 상품 추가 |
PUT | /cart/{id} | 장바구니 상품 수정 |
DELETE | /cart/{id} | 장바구니 상품 삭제 |
✅ RESTful API Controller 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| @RestController
@CrossOrigin("http://127.0.0.1:5500/")
@RequestMapping("/api/members") // 기본 URI를 설정
public class RestMemberController {
@Autowired
MemberService memberService;
@DeleteMapping("/{id}") // 회원 삭제
public String deleteMember(@PathVariable Long id) {
System.out.println("Deleting member with ID: " + id);
try {
memberService.deleteMemberById(id);
return "ok";
} catch (Exception e) {
e.printStackTrace();
return "회원 삭제 실패";
}
}
}
|
📌 Swagger 사용하기
1. pom.xml
의존성 추가**
1
2
3
4
5
| <dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
|
2. Swagger UI 접속
Swagger UI를 통해 API 문서 자동 생성 및 테스트 가능
1
| http://localhost:8080/swagger-ui/index.html
|
END