쇼핑몰 만들기 총 정리!
Front
index.html
index.js
window.onload = async () => {
// 1.윈도우가 로드되면 이 싱크가 실행됨
// 2. response는 파싱한 채로 온다.
let response = await axios.get('http://localhost:8080/getAllProducts');
console.log(response); // response 객체에 들어온 데이터를 확인하기 위해 console.log()사용
let productList = response.data; // 서버 응답 데이터 추출
let productListDiv = ``; // HTML 요소를 담을 변수로 사용
productList.forEach((item) => {
productListDiv += `<div class="card m-3" style="width: 10rem;">
<img src="img/${item.pimg}" class="card-img-top" alt="...">
<div class="card-body">
<b class="card-title">${item.prodname}</b>
<p class="card-text text-danger">${item.price}원</p>
<a href="#" class="btn btn-outline-info">장바구니 담기</a>
</div>
</div>`;
});
document.getElementById('productListDiv').innerHTML = productListDiv;
};
window.onload = async () => {
window.onload
웹 페이지가 모든 리소스(HTML,CSS, JS..)를 다 불러온 후 실행된는 이벤트
→ 페이지가 완전히 로드된 후 실행될 익명 함수(Arrow Function)를 정의한 것
async를 사용한 이유는?
내부에서 await을 사용할 것이기에
let response = await axios.get('http://localhost:8080/getAllProducts');
axios.get(url)
axios는 JS에서 비동기적으로 HTTP 요청을 보낼 수 있는 라이브러리
getAllProducts API 엔드포인트에서 데이터를 가져오고, 결과를 response변수에 저장
await
axios.get()는 비동기 함수이므로 서버 응답을 받을 때까지 기다리기 위해 await를 사용
forEach() 반복문
productList 배열을 순회하면서 item(각 상품 객체)을 하나씩 처리
item은 { "prodname": "상품A", "price": 10000, "pimg": "productA.jpg" } 같은 형태
document.getElementById('productListDiv').innerHTML = productListDiv;
HTML에 동적으로 데이터 삽입
innerHTML = productListDiv를 사용해 해당 요소의 내용을 동적으로 변경
- 페이지가 완전히 로드되면 실행됨 (window.onload)
- axios.get()을 사용하여 http://localhost:8080/getAllProducts에서 상품 데이터를 가져옴
- 서버에서 받은 데이터를 productList에 저장
- productList의 각 상품을 HTML 카드로 변환하여 productListDiv에 추가
- productListDiv를 document.getElementById('productListDiv').innerHTML에 삽입하여 화면에 표시
Back
DB table만들기
Product.java
상품 정보를 저장하는 DTO역할 → 상품 데이터를 담아서 주고받는 객체
🧐 DTO는 무엇인가?
DTO(Data Transfer Object) → 그릇 역할
데이터를 전달할때 사용하는 객체
package com.shop.cafe.dto;
public class Product { // Product 클래스는 하나의 상품 정보를 저장하는 객체
private String prodname,pimg;
private int prodcode, price;
public Product(String prodname, String pimg, int prodcode, int price) { // 상품 정보를 넣어서 Product 객체를 생성
setPimg(pimg);
setPrice(price);
setProdcode(prodcode);
setProdname(prodname);
}
public Product() {
super();
// TODO Auto-generated constructor stub
}
// override: 부모 클래스에서 상속받은 메서드를 재정의하는것
@Override
public String toString() {
return "Product [prodname=" + prodname + ", pimg=" + pimg + ", prodcode=" + prodcode + ", price=" + price + "]";
}
public String getProdname() {
return prodname;
}
public void setProdname(String prodname) {
this.prodname = prodname;
}
public String getPimg() {
return pimg;
}
public void setPimg(String pimg) {
this.pimg = pimg;
}
public int getProdcode() {
return prodcode;
}
public void setProdcode(int prodcode) {
this.prodcode = prodcode;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
🧐 왜 new set이 아닌가?
public Product(String prodname, String pimg, int prodcode, int price) {
setPimg(pimg);
setPrice(price);
setProdcode(prodcode);
setProdname(prodname);
}
new setPing가 아닌 이유는 이미 Product라는 객체가 생성된 상태이기때문이다.
위의 코드에서는 생성된 객체의 값을 설정하는 것이다.
그래서 set메서드만 호출해 값을 설정한다.
ProductDao.java
상품 데이터베이스 처리 → 데이터베이스에서 상품 목록을 가져오는 역할
🧐 DAO란 무엇인가?
데베와 직접 연결되어 데이터를 가져오거나 저장하는 역할 → (Create, Read, Update, Delete)하는 역할을 담당
기존 코드의 아쉬운 점
JDBC를 직접 사용 → Connection, PreparedStatement, Result을 다 작성해야함
SQL이 코드 안에 포함되어 유지보수 어려움
DB연결 코드가 많아져 코드가 복잡해짐
현재 코드의 좋은 점
DAO를 인터페이스로 변화했다.
SQL을 따로 XML에서 관리해 유지보수 GOOD!
DB연결 코드 직접 작성 X
@Mapper만 붙이면 자동으로 MyBatis가 SQL 실행을 처리해준다.
package com.shop.cafe.dao;
import java.util.*;
import org.apache.ibatis.annotations.Mapper;
import com.shop.cafe.dto.Product;
@Mapper // MyBatis가 자동으로 SQL을 실행하도록 설정됨
public interface ProductDao {
public List<Product> getAllProducts() throws Exception; // SQL 실행 메서드 선언
}
ProductService.java
package com.shop.cafe.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shop.cafe.dao.ProductDao;
import com.shop.cafe.dto.Product;
@Service // 이 클래스가 서비스 역할을 한다고 Spring에 알림
public class ProductService {
@Autowired
ProductDao productDao;
public List<Product> getAllProducts() throws Exception{
return productDao.getAllProducts(); // DAO를 호출해 상품 리스트 가져옴
}
}
ProductController.java
package com.shop.cafe.controller;
import java.util.*;
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.RestController;
import com.shop.cafe.dto.Product;
import com.shop.cafe.service.ProductService;
@RestController // SON 데이터를 반환하는 API를 쉽게 만든다.
@CrossOrigin("http://172.30.1.46:5500") // 특정 도메인의 요청 허용
public class ProductController {
@Autowired // Spring이 자동으로 ProductService 객체를 주입(연결)해 줌, new 필요x
ProductService productService;
Map<String,Object> storage=new HashMap<>(); // 캐시에서 데이터 가져옴
@GetMapping("getAllProducts") // HTTP GET 요청을 처리하는 메서드
public List<Product> getAllProducts() {
try {
Object o=storage.get("firstPageProducts");
if(o==null) { // 캐시에 데이터가 없으면
List<Product> list=productService.getAllProducts(); // DB에서 데이터를 가져온다.PS에서 DB를 조회하고 상품 목록을 리스트 형태로 반환
storage.put("firstPageProducts", list); // 가져온 데이터를 캐시에 저장
return list; //DB에서 가져온 데이터 반환
}
return (List<Product>)o; // 캐시에 데이터가 있으면 그대로반환
} catch (Exception e) { // 예외처리
e.printStackTrace(); // 오류있으면 출력하시오
return null;
}
}
}
Object o = storage.get("firstPageProducts");
storage(HashMap)에 "firstPageProducts" 키가 있는지 확인
만약 이전에 저장한 데이터가 있다면, 해당 데이터를 가져온다.
storage는 Map<String, Object> 타입이므로 Object 타입으로 값을
가져온다.
회원가입 처리 및 로그인 처리하
Member table 생성
Member.java
package com.shop.cafe.dto;
import java.util.Date;
public class Member {
private String email, pwd, nickname;
private Date registDate;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Date getRegistDate() {
return registDate;
}
public void setRegistDate(Date registDate) {
this.registDate = registDate;
}
public Member() {
super();
// TODO Auto-generated constructor stub
}
public Member(String email, String pwd, String nickname, Date registDate) {
super();
this.email = email;
this.pwd = pwd;
this.nickname = nickname;
this.registDate = registDate;
}
@Override
public String toString() {
return "Member [email=" + email + ", pwd=" + pwd + ", nickname=" + nickname + ", registDate=" + registDate
+ "]";
}
}
MemberDao.java
package com.shop.cafe.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import com.shop.cafe.dto.Member;
@Mapper
// 커넥션을 직접하지 않기 위해
public interface MemberDao {
public Member login(Member m) throws Exception;
public void insertMember(Member m) throws Exception;
}
MemberService.java
package com.shop.cafe.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shop.cafe.dao.MemberDao;
import com.shop.cafe.dto.Member;
@Service
public class MemberService {
@Autowired
MemberDao memberDao;
public Member login(Member m) throws Exception {
return memberDao.login(m);
}
public void insertMember(Member m) throws Exception{
memberDao.insertMember(m);
}
}
MemberController.java
package com.shop.cafe.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.shop.cafe.dto.Member;
import com.shop.cafe.service.MemberService;
@RestController
@CrossOrigin("http://172.30.1.46:5500")
public class MemberController {
@Autowired
MemberService memberService;
@PostMapping("login")
public Map<String,String> login(@RequestBody Member m) {
Map<String,String> responseMap=new HashMap<>();
try {
m = memberService.login(m);
String nickname = m.getNickname();
if(m!= null && nickname != null && !nickname.trim().equals("")) {
responseMap.put("nickname", nickname);
} else {
responseMap.put("msg", "다시 로그인 해주세요");
}
} catch (Exception e) {
e.printStackTrace();
responseMap.put("msg", "다시 로그인 해주세요");
}
return responseMap;
}
@PostMapping("insertMember")
public String insertMember(@RequestBody Member m) {
System.out.println(m);
try {
memberService.insertMember(m);
return "ok";
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "nickname이나 email이 중복됩니다.";
}
}
}
잘못설정하면 계ㅖ정 털리는 내용 적기
주말에 다시 정리해야쥐..
자바 이녀석.. 어려운듯..재밌군..
그냥 오류 고쳐지면 행복 그자체
똑같이 따라쳐도 오타가 발생하는 아주 큰 문제..
눈 크게 뜨고 하나하나 따라쳐야쥐
'💡 URECA > 🗒️ 스터디 노트' 카테고리의 다른 글
[URECA] Day 31 | backend (0) | 2025.03.11 |
---|---|
[URECA] Day 30 | Backend(5) (0) | 2025.03.10 |
[URECA] Day28 | Backend(3) (0) | 2025.03.06 |
[URECA] Day 27 | Backend(2) (1) | 2025.03.05 |
[URECA] Day 26 | SQL(2) (1) | 2025.03.04 |