수업 복습

Java MVC 복습 & 코드 필사

_김영인 2025. 10. 28. 17:06

프론트에 비밀번호 표시되는 것을 방지

 

Member.setMemberPassword(null);

앞단에 이런 코드를 사용하여 가릴 수도 있다
비밀번호는 다 털고 다음 단계로 가야함
 
비밀번호 변경 view

 

1.본인확인 (현재비밀번호입력 >>

 

(2-1.  본인확인을 다시진행 - 심화과정)

 

2-2 메뉴탈출 (*) (실패…)
3. 변경할 비밀번호입력
4-1 성공
4-2 실패
 
view는 코드가 다 이미 존재하기에 따로 만들것이 없다
 
 
 
 
Controller 
 
view  현재비밀번호 받아와서 DB (Model)한테 넘겨줌
 
 
v한테서 변경할 비밀번호 받아와서 m한테 넘겨줌
성공 또는 실패
 
본인확인은 일종의 로그인이라 모델한테 CRUD 중에 selectOne으로 넘김
 
본인이 아닌경우 == data 는 null
 
재활용이 어려우면 변수명을 새로 만들어도 됨
 
 
 

회원탈퇴

탈퇴 진짜로 확인할 건지 확인 
view로 기존 비밀번호 확인
실패하면 out
성공하면 m에서 해당 정보 삭제
 
상품구매
화면에 상품목록이 나옴
사용자가 상품 1개를 선택
해당 상품의 상세정보가 나옴
몇 개 살지 정함
구매를 시도
성공하고 성공화면
실패하면 실패화면
 
전체출력이 된 상황
사용자가 품번을 입력하면 selectAll

 
재고 없는 거 선택 못하게 막기
품절표시하기
 
 
사용자가 입력한 상품번호가 유효한지 배열 안에 있는지 확인
 
상품이 있는지 없는지는 전체출력을 해봐야 알 수있음
 
사용자가 몇 개 살지를 정함
 
카운트를 받음
 
상품 최대 개수보다 못사게 막기
 
재고 유효성 검사를 위해 상품을 알아야하고 재고에 맞게 바꾸기
 
누구를 몇개 살 지 코드 설계
컨디션도 보내야함
 
 
전체목록보기 상품삭제 번호 받기 

컨디션 땜에 디티오 필요로 함


상품재고추가 

무엇을 몇개 추가할지
                                                                                          
클라이언트 뷰에서 전체목록 띄워줌

사용자가 입력한 정보를 통해서 상세 페이지를 띄움
 
원래 재고는 따로 빼서 관리하지만 지금은 이해를 위해 포함시켜 공부 중
 
업데이트에서 구매할 적에 재고가 마이너스 되는 상황은 여러 명이 사용하는 서비스이기 때문에 그럴 수 있다 
 
장바구니에 있다가 동시에 구매가 빠지면 그럴 수 있다
 
그럴 때는 로직을 통해 남겨놓아라

 

아이디 중복검사 로직

 

중복되지 않은 아이디라면 종료

중복아이디라고 안내문 출력해주기
 
~인지 아닌지 반환이 1개만 되기 때문에 selectOne
셀렉트원에 로그인 로직 뿐인데 이 항목에 분기를 나눠 추가
로그인을 수행하는 상황이라면 기존 로직을 수행하고
아이디 중복 검사라면 패스워드가 필요없어서 그 코드만 빼고 복사
(이름도 주지 않고 그 아무것도 주지 않고 아이디만 줌)
 
로그인 수행 컨디션으로 만듬
 
다음은 컨트롤러로
새로 생긴 로그인 컨디션 넣기
 
이제 분기가 생겨서 기존에 쓰던 애한테 컨디션을 주기
 
Data == null (중복되지 않은 아이디라면)
스코프 이슈 해결하기

 

관리자 모드 추가

 
위에는 관리자 계정 (아이디가 어드민인 경우)
밑에는 일반계정
 
계정삭제는 update 인 경우가 많음
Delete 서비스가 없는 경우도 많음
 
컨트롤러 로그인 파트 분기가 또 생김
만약에 관리자가 로그인했다면 
 
몽키스패너 생기는 관리자 모드가 있고 아예 화면이 달라지는 것도 있음
 
9 커맨드부터 다시 만들기
상품 추가하려면 관리자로터 상품이름, 가격, 재고를 받아오기
 
CRUD 보면서 같은 서비스는 뉘앙스가 같기에 참조 가능
 
상품 개수 마이너스 몇개 유효성 검사하기 
 

상품삭제 번호 받기 

컨디션 땜에 디티오 필요로 함

 

package client;

 

import controller.Controller;

 

public class Client {

public static void main(String[] args) {

Controller app = new Controller();

 

app.startApp();

}

}

 

 

package controller;

import java.util.ArrayList;

import model.dao.MemberDAO;
import model.dao.ProductDAO;
import model.dto.MemberDTO;
import model.dto.ProductDTO;
import view.AdminView;
import view.ClientView;
import view.View;

public class Controller {
	private MemberDAO mDAO;
	private ProductDAO pDAO;

	private View common;
	private ClientView client;
	private AdminView admin;

	private MemberDTO userInfo; // 로그인 여부(쿠키,세션,로컬 스토리지 등)
	public Controller() {
		this.mDAO = new MemberDAO();
		this.pDAO = new ProductDAO();

		this.common = new View();
		this.client = new ClientView();
		this.admin = new AdminView();

		this.userInfo = null; // 로그인을 안한 상태
	}
	public void startApp() {
		int PK = 1003; // 상품의 PK
		while(true) {
			if(userInfo == null) {
				common.printMainMenu();
			}
			else {
				if(userInfo.getMemberId().equals("admin")) {
					// 관리자 모드
					admin.printLoginMenu(userInfo);
				}
				else {
					common.printLoginMenu(userInfo);
				}
			}
			int command = common.getMenuNum(); 
			if(command == 0) {
				common.printTurnOff();
				break;
			}
			else if(command == 1) {
				// 회원가입

				String memberId;
				while(true) {
					memberId = client.getMemberId();

					MemberDTO memberDTO = new MemberDTO();
					memberDTO.setCondition("JOIN");
					memberDTO.setMemberId(memberId);
					MemberDTO data = mDAO.selectOne(memberDTO);
					if(data == null) { 
						break;
					}
					client.printInfo();
				}
				String memberPasswd = client.getMemberPasswd00();
				String name = client.getMemberName();

				MemberDTO mDTO = new MemberDTO();
				mDTO.setMemberId(memberId);
				mDTO.setMemberPasswd(memberPasswd);
				mDTO.setMemberName(name);
				boolean flag = mDAO.insert(mDTO);

				if(flag) {
					common.func01();
				}
				else {
					common.func02();
				}
			}
			else if(command == 2) {
				// 로그인

				String memberId = client.getMemberId();
				String memberPasswd = client.getMemberPasswd00();

				MemberDTO mDTO = new MemberDTO();
				mDTO.setCondition("LOGIN");
				mDTO.setMemberId(memberId);
				mDTO.setMemberPasswd(memberPasswd);
				MemberDTO member = mDAO.selectOne(mDTO);

				if(member != null) {
					userInfo = member;
					common.func01();
				}
				else {
					common.func02();
				}
			}
			else if(command == 3) {
				// 상품목록출력

				ProductDTO productDTO = new ProductDTO();
				productDTO.setCondition("ALL");
				ArrayList<ProductDTO> datas = pDAO.selectAll(productDTO);

				client.printProductDatas(datas);
			}
			else if(command == 4) {
				// 상품검색

				String keyword = common.getProductName();

				ProductDTO productDTO = new ProductDTO();
				productDTO.setCondition("SEARCH");
				productDTO.setProductName(keyword);
				ArrayList<ProductDTO> datas = pDAO.selectAll(productDTO);

				client.printProductDatas(datas);
			}
			else if(command == 5) {
				// 로그아웃

				userInfo = null;
				common.func01();
			}
			else if(command == 6) {
				// 회원탈퇴

				String passwd = client.getMemberPasswd01();
				MemberDTO memberDTO = new MemberDTO();
				memberDTO.setMemberId(userInfo.getMemberId());
				memberDTO.setMemberPasswd(passwd);
				MemberDTO data = mDAO.selectOne(memberDTO);

				if(data == null) {
					common.func02();
					continue;
				}

				memberDTO = new MemberDTO();
				memberDTO.setMemberId(userInfo.getMemberId());
				boolean flag = mDAO.delete(memberDTO);

				if(flag) {
					common.func01();
					common.func03();
					userInfo = null; // 로그아웃
				}
				else {
					common.func02();
				}	
			}
			else if(command == 7) {
				// 비밀번호 변경

				String passwd = client.getMemberPasswd01();
				MemberDTO memberDTO = new MemberDTO();
				memberDTO.setMemberId(userInfo.getMemberId());
				memberDTO.setMemberPasswd(passwd);
				MemberDTO data = mDAO.selectOne(memberDTO);

				if(data == null) {
					common.func02();
					continue;
				}

				passwd = client.getMemberPasswd02();
				memberDTO = new MemberDTO();
				memberDTO.setMemberId(userInfo.getMemberId());
				memberDTO.setMemberPasswd(passwd);
				boolean flag = mDAO.update(memberDTO);

				if(flag) {
					common.func01();
					common.func03();
					userInfo = null; // 로그아웃
				}
				else {
					common.func02();
				}	
			}
			else if(command == 8) {
				// 상품구매

				ProductDTO productDTO = new ProductDTO();
				productDTO.setCondition("ALL");
				ArrayList<ProductDTO> datas = pDAO.selectAll(productDTO);
				client.printProductDatas(datas);
				if(datas.isEmpty()) {
					continue;
				}

				int num = client.getProductNum(datas);
				productDTO = new ProductDTO();
				productDTO.setProductId(num);
				ProductDTO data = pDAO.selectOne(productDTO);
				client.printProductData(data);

				int count = client.getCount(data);

				productDTO = new ProductDTO();
				productDTO.setCondition("PAY");
				productDTO.setProductId(num);
				productDTO.setCount(count);
				boolean flag = pDAO.update(productDTO);

				if(flag) {
					common.func01();
				}
				else {
					common.func02();
				}	
			}
			else if(command == 9) {
				// 상품추가
				
				String name = admin.getProductName();
				int price = admin.getProductPrice();
				int count = admin.getCount();
				
				ProductDTO productDTO = new ProductDTO();
				productDTO.setProductId(PK++);
				productDTO.setProductName(name);
				productDTO.setPrice(price);
				productDTO.setCount(count);
				boolean flag = pDAO.insert(productDTO);
				
				if(flag) {
					common.func01();
				}
				else {
					common.func02();
				}
			}
			else if(command == 10) {
				// 상품삭제
				
				ProductDTO productDTO = new ProductDTO();
				productDTO.setCondition("ALL");
				ArrayList<ProductDTO> datas = pDAO.selectAll(productDTO);
				int num = client.getProductNum(datas);
				
				productDTO = new ProductDTO();
				productDTO.setProductId(num);
				boolean flag = pDAO.delete(productDTO);
				
				if(flag) {
					common.func01();
				}
				else {
					common.func02();
				}
			}
			else if(command == 11) {
				// 상품재고추가
				
				ProductDTO productDTO = new ProductDTO();
				productDTO.setCondition("ALL");
				ArrayList<ProductDTO> datas = pDAO.selectAll(productDTO);
				int num = client.getProductNum(datas);
				int count = admin.getCount();
				
				productDTO = new ProductDTO();
				productDTO.setCondition("ADD");
				productDTO.setProductId(num);
				productDTO.setCount(count);
				boolean flag = pDAO.update(productDTO);
				
				if(flag) {
					common.func01();
				}
				else {
					common.func02();
				}
			}
		}
	}
}

 

package model.dao;

import java.util.ArrayList;

import model.dto.MemberDTO;

public class MemberDAO {
	private ArrayList<MemberDTO> datas; // DB 역할
	public MemberDAO() {
		this.datas = new ArrayList<>();

		MemberDTO data01 = new MemberDTO();
		data01.setMemberId("admin");
		data01.setMemberPasswd("1234");
		data01.setMemberName("관리자");
		this.datas.add(data01);
		MemberDTO data02 = new MemberDTO();
		data02.setMemberId("test");
		data02.setMemberPasswd("1234");
		data02.setMemberName("테스트");
		this.datas.add(data02);
	}

	private ArrayList<MemberDTO> selectAll(MemberDTO memberDTO){ // 코드의 결합도가 낮아짐 ★
		ArrayList<MemberDTO> datas = new ArrayList<>();
		for(int i=0;i<this.datas.size();i++) {
			MemberDTO data = new MemberDTO();
			data.setMemberId(this.datas.get(i).getMemberId());
			data.setMemberName(this.datas.get(i).getMemberName());
			datas.add(data);
		}
		return datas;
	}
	public MemberDTO selectOne(MemberDTO memberDTO) {
		if(memberDTO.getCondition().equals("LOGIN")) {
			for(int i=0;i<this.datas.size();i++) {
				if(this.datas.get(i).getMemberId().equals(memberDTO.getMemberId())) {
					if(this.datas.get(i).getMemberPasswd().equals(memberDTO.getMemberPasswd())) {
						MemberDTO data = new MemberDTO();
						data.setMemberId(this.datas.get(i).getMemberId());
						data.setMemberName(this.datas.get(i).getMemberName());
						return data;
					}
					else {
						System.out.println(" [로그] MemberDAO.selectOne() 해당하는 아이디는 찾았으나, 비밀번호가 올바르지 않습니다.");
						return null;
					}
				}
			}
			System.out.println(" [로그] MemberDAO.selectOne() 해당하는 아이디가 없습니다.");
		}
		else if(memberDTO.getCondition().equals("JOIN")) {
			for(int i=0;i<this.datas.size();i++) {
				if(this.datas.get(i).getMemberId().equals(memberDTO.getMemberId())) {
					MemberDTO data = new MemberDTO();
					data.setMemberId(this.datas.get(i).getMemberId());
					return data;
				}
			}
			System.out.println(" [로그] MemberDAO.selectOne() 해당하는 아이디가 없습니다.");
		}
		return null;
	}

	public boolean insert(MemberDTO memberDTO) {
		try {
			MemberDTO data = new MemberDTO();
			data.setMemberId(memberDTO.getMemberId());
			data.setMemberPasswd(memberDTO.getMemberPasswd());
			data.setMemberName(memberDTO.getMemberName());
			this.datas.add(data);
		}
		catch(Exception e) {
			return false;
		}
		return true;
	}
	public boolean update(MemberDTO memberDTO) {
		for(int i=0;i<this.datas.size();i++) {
			if(this.datas.get(i).getMemberId().equals(memberDTO.getMemberId())) {
				this.datas.get(i).setMemberPasswd(memberDTO.getMemberPasswd());
				return true;
			}
		}
		return false;
	}
	public boolean delete(MemberDTO memberDTO) {
		for(int i=0;i<this.datas.size();i++) {
			if(this.datas.get(i).getMemberId().equals(memberDTO.getMemberId())) {
				this.datas.remove(i);
				return true;
			}
		}
		return false;
	}
}

 

package model.dao;

import java.util.ArrayList;

import model.dto.ProductDTO;

public class ProductDAO {
	private ArrayList<ProductDTO> datas;
	public ProductDAO() {
		this.datas = new ArrayList<>();

		ProductDTO data01 = new ProductDTO();
		data01.setProductId(1001);
		data01.setProductName("모자");
		data01.setPrice(3600);
		data01.setCount(5);
		this.datas.add(data01);
		ProductDTO data02 = new ProductDTO();
		data02.setProductId(1002);
		data02.setProductName("모래시계");
		data02.setPrice(3250);
		data02.setCount(0);
		this.datas.add(data02);
	}

	public ArrayList<ProductDTO> selectAll(ProductDTO productDTO){ 
		ArrayList<ProductDTO> datas = new ArrayList<>();

		if(productDTO.getCondition().equals("ALL")) {
			for(int i=0;i<this.datas.size();i++) {
				ProductDTO data = new ProductDTO();
				data.setProductId(this.datas.get(i).getProductId());
				data.setProductName(this.datas.get(i).getProductName());
				data.setPrice(this.datas.get(i).getPrice());
				data.setCount(this.datas.get(i).getCount());
				datas.add(data);
			}
		}
		else if(productDTO.getCondition().equals("SEARCH")) {
			for(int i=0;i<this.datas.size();i++) {
				if(this.datas.get(i).getProductName().contains(productDTO.getProductName())) {
					ProductDTO data = new ProductDTO();
					data.setProductId(this.datas.get(i).getProductId());
					data.setProductName(this.datas.get(i).getProductName());
					data.setPrice(this.datas.get(i).getPrice());
					data.setCount(this.datas.get(i).getCount());
					datas.add(data);
				}
			}
		}

		return datas;
	}
	public ProductDTO selectOne(ProductDTO productDTO) {
		for(int i=0;i<this.datas.size();i++) {
			if(this.datas.get(i).getProductId() == productDTO.getProductId()) {
				ProductDTO data = new ProductDTO();
				data.setProductId(this.datas.get(i).getProductId());
				data.setProductName(this.datas.get(i).getProductName());
				data.setPrice(this.datas.get(i).getPrice());
				data.setCount(this.datas.get(i).getCount());
				return data;
			}
		}
		return null;
	}

	public boolean insert(ProductDTO productDTO) {
		try {
			ProductDTO data = new ProductDTO();
			data.setProductId(productDTO.getProductId());
			data.setProductName(productDTO.getProductName());
			data.setPrice(productDTO.getPrice());
			data.setCount(productDTO.getCount());
			this.datas.add(data);
		}
		catch(Exception e) {
			return false;
		}
		return true;
	}
	public boolean update(ProductDTO productDTO) {
		if(productDTO.getCondition().equals("ADD")) {
			for(int i=0;i<this.datas.size();i++) {
				if(this.datas.get(i).getProductId() == productDTO.getProductId()) {
					this.datas.get(i).setCount(this.datas.get(i).getCount() + productDTO.getCount());
					return true;
				}
			}
		}
		else if(productDTO.getCondition().equals("PAY")) {
			for(int i=0;i<this.datas.size();i++) {
				if(this.datas.get(i).getProductId() == productDTO.getProductId()) {
					if(this.datas.get(i).getCount() >= productDTO.getCount()) {
						this.datas.get(i).setCount(this.datas.get(i).getCount() - productDTO.getCount());
					}
					else {
						System.out.println(" [로그] ProductDAO.update() - PAY : 재고없음");
						return false;
					}
					return true;
				}
			}
		}
		return false;
	}
	public boolean delete(ProductDTO productDTO) {
		for(int i=0;i<this.datas.size();i++) {
			if(this.datas.get(i).getProductId() == productDTO.getProductId()) {
				this.datas.remove(i);
				return true;
			}
		}
		return false;
	}
}

 

package model.dto;

public class MemberDTO {
	private String memberId;
	private String memberPasswd;
	private String memberName;
	
	private String condition;
	public String getCondition() {
		return condition;
	}
	public void setCondition(String condition) {
		this.condition = condition;
	}
	public String getMemberId() {
		return memberId;
	}
	public void setMemberId(String memberId) {
		this.memberId = memberId;
	}
	public String getMemberPasswd() {
		return memberPasswd;
	}
	public void setMemberPasswd(String memberPasswd) {
		this.memberPasswd = memberPasswd;
	}
	public String getMemberName() {
		return memberName;
	}
	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}
	@Override
	public String toString() {
		return "MemberDTO [memberId=" + memberId + ", memberPasswd=" + memberPasswd + ", memberName=" + memberName
				+ "]";
	}
}

 

package model.dto;

public class ProductDTO {
	private int productId;
	private String productName;
	private int price;
	private int count;
	
	private String condition;
	public String getCondition() {
		return condition;
	}
	public void setCondition(String condition) {
		this.condition = condition;
	}
	public int getProductId() {
		return productId;
	}
	public void setProductId(int productId) {
		this.productId = productId;
	}
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	@Override
	public String toString() {
		return "ProductDTO [productId=" + productId + ", productName=" + productName + ", price=" + price + ", count="
				+ count + "]";
	}
}

 

package view;

import java.util.ArrayList;
import java.util.Scanner;

import model.dto.MemberDTO;
import model.dto.ProductDTO;

public class View {
	static protected Scanner scanner = new Scanner(System.in);

	public void printMainMenu() {
		System.out.println();
		System.out.println("1. 회원가입");
		System.out.println("2. 로그인");
		System.out.println("3. 전체상품출력");
		System.out.println("4. 상품검색");
		System.out.println("0. 프로그램 종료");
	}
	public void printLoginMenu(MemberDTO member) {
		System.out.println();
		System.out.println(member.getMemberName()+"님, 환영합니다!");
		System.out.println("5. 로그아웃");
		System.out.println("6. 회원탈퇴");
		System.out.println("7. 비밀번호 변경");
		System.out.println("8. 상품구매");
		System.out.println("0. 프로그램 종료");
	}
	public int getMenuNum() {
		System.out.print("메뉴번호입력 >> ");
		int num = scanner.nextInt();
		return num;
	}
	public void printTurnOff() {
		System.out.println("프로그램을 종료합니다.");
	}
	public String getProductName() {
		System.out.print("상품이름입력 >> ");
		String name = View.scanner.next();
		return name;
	}
	public void func01() {
		System.out.println("성공!");
	}
	public void func02() {
		System.out.println("실패...");
	}
	public void func03() {
		System.out.println("로그아웃 후 다시 이용해주세요!");
	}
	public int getCount(ProductDTO data) {
		int count; // scope(유효범위) 이슈
		while(true) {
			System.out.print("상품개수입력 >> ");
			count = scanner.nextInt();
			if(0<count && count<=data.getCount()) {
				break;
			}
			System.out.println("다시 입력해주세요!");
		}
		return count;
	}
	public int getProductNum(ArrayList<ProductDTO> datas) {
		int num;
		while(true) {
			try {
				System.out.print("상품번호입력 >> ");
				num = scanner.nextInt();

				boolean flag = false;
				for(ProductDTO data:datas) {
					if(data.getProductId() == num) {
						if(data.getCount() > 0) {
							flag = true;
						}
						break;
					}
				}
				if(!flag) {
					System.out.println("번호 및 재고 확인후 다시 입력해주세요!");
					continue;
				}

				break;
			}
			catch(Exception e) {
				scanner.nextLine();
				System.out.println("다시 입력해주세요!");
			}
		}
		return num;
	}
}

 

package view;

 

import model.dto.MemberDTO;

 

public class AdminView extends View {

public int getCount() {

System.out.print("상품개수입력 >> ");

int count = scanner.nextInt();

return count;

}

public int getProductPrice() {

System.out.print("상품가격입력 >> ");

int price = View.scanner.nextInt();

return price;

}

public void printLoginMenu(MemberDTO member) {

System.out.println();

System.out.println(" +++ 관리자 모드 +++");

System.out.println(member.getMemberName()+"님, 환영합니다!");

System.out.println("9. 상품추가");

System.out.println("10. 상품삭제");

System.out.println("11. 상품재고추가");

System.out.println("5. 로그아웃");

System.out.println("0. 프로그램 종료");

}

}

 

package view;

import java.util.ArrayList;

import model.dto.ProductDTO;

public class ClientView extends View {
	public void printProductData(ProductDTO data) {
		System.out.println("상품명 : "+data.getProductName());
		System.out.println("가격 : "+data.getPrice());
		System.out.println("재고 : "+data.getCount());
	}
	public void printInfo(){
		System.out.println("해당 아이디는 이미 사용중입니다!");
		System.out.println("다른 아이디를 입력해주세요...");
	}
	public String getMemberId() {
		System.out.print("회원 ID 입력 >> ");
		String id = View.scanner.next();
		return id;
	}
	public String getMemberPasswd00() {
		System.out.print("회원 PW 입력 >> ");
		String pw = View.scanner.next();
		return pw;
	}
	public String getMemberPasswd01() {
		System.out.print("기존 회원 PW 입력 >> ");
		String pw = View.scanner.next();
		return pw;
	}
	public String getMemberPasswd02() {
		System.out.print("변경할 회원 PW 입력 >> ");
		String pw = View.scanner.next();
		return pw;
	}
	public String getMemberName() {
		System.out.print("회원 이름 입력 >> ");
		String name = View.scanner.next();
		return name;
	}
	public void printProductDatas(ArrayList<ProductDTO> datas) {
		if(datas.isEmpty()) {
			System.out.println("출력할 상품이 없습니다...");
			return;
		}

		for(ProductDTO data:datas) {
			System.out.println(data);
		}
	}
}

'수업 복습' 카테고리의 다른 글

JS 내장객체  (0) 2025.11.18
HTML 복습 및 코드리뷰 피드백  (0) 2025.11.11
Java 복습 & 코드 필사  (0) 2025.10.27
Java interface 복습  (0) 2025.10.26
Java Thread & MVC  (0) 2025.10.24