[BCGD] 비전공자 백엔드 개발 도전기 (67)

2025. 6. 10. 18:46·SpringBoot
728x90

join.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>사용자 등록</title>
</head>
<body>
	<h2>사용자 등록</h2>
	<form:form modelAttribute="user" method="post" action="join">
		<spring:hasBindErrors name="user">
			<font color="red">
				<c:forEach items="${errors.globalErrors}" var="error">
					<spring:message code="${error.code}" /><br/>
				</c:forEach>
			</font>
		</spring:hasBindErrors>
		<table>
			<tr>
				<td>아이디</td>
				<td>
					<form:input path="userid" />
					<font color="red"><form:errors path="userid" /></font>
				</td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td>
					<form:input path="password" />
					<font color="red"><form:errors path="password" /></font>
				</td>
			</tr>
			<tr>
				<td>이름</td>
				<td>
					<form:input path="username" />
					<font color="red"><form:errors path="username" /></font>
				</td>
			</tr>
			<tr>
				<td>전화번호</td>
				<td><form:input path="phoneno" /></td>
			</tr>
			<tr>
				<td>우편번호</td>
				<td><form:input path="postcode" /></td>
			</tr>
			<tr>
				<td>주소</td>
				<td><form:input path="address" /></td>
			</tr>
			<tr>
				<td>이메일</td>
				<td>
					<form:input path="email" />
					<font color="red"><form:errors path="email" /></font>
				</td>
			</tr>
			<tr>
				<td>생년월일</td>
				<td>
					<form:input path="birthday" />
					<font color="red"><form:errors path="birthday" /></font>
				</td>
			</tr>
			<tr>
				<td><input type="submit" value="회원가입"></td>
				<td><input type="reset" value="초기화"></td>
			</tr>
		</table>
	</form:form>
</body>
</html>

 

 

logic/User.java

@Data
public class User {
	@Size(min=3, max=10, message="아이디는 3자이상 10자 이하로 입력하세요")
	private String userid;
	private String channel;
	@Size(min=3, max=10, message="비밀번호는 3자이상 10자 이하로 입력하세요")
	private String password;
	@NotEmpty(message="사용자 이름은 필수 입니다")
	private String username;
	private String phoneno;
	private String postcode;
	private String address;
	@NotEmpty(message="email을 입력하세요")
	@Email(message="email 형식으로 입력하세요")
	private String email;
	// @NotNull(message="생일을 입력하세요") 필수입력
	@Past(message="생일은 과거 날짜만 가능합니다")
	@DateTimeFormat(pattern="yyyy-MM-dd")
	private Date birthday;
}

 

 

service/UserService

@Service
public class UserService {
	@Autowired
	UserDao userdao;
	
	public void userInsert(User user) {
		userdao.insert(user);
	}
	
}

 

controller/UserController

@Controller
@RequestMapping("user")
public class UserController {
	@Autowired
	private UserService service;
	
	@GetMapping("*") // Get 방식 모든 요청호출
	public ModelAndView form() {
		ModelAndView mav = new ModelAndView();
		mav.addObject(new User());
		return mav; // url과 연동된 뷰를 호출
	}
	
	@PostMapping("join")
	//BindingResult은 입력값 검증대상 변수의 다음에 와야함
	public ModelAndView userAdd(@Valid User user, BindingResult bresult) {
		ModelAndView mav = new ModelAndView();
		if(bresult.hasErrors()) {
			// 추가 오류 메세지 등록
			bresult.reject("error.input.user");
			bresult.reject("error.input.check");
			return mav;
		}
		
		// 정상적으로 입력된 경우
		try {
			service.userInsert(user);
		}catch (DataIntegrityViolationException e) { // (아이디 중복)
			e.printStackTrace();
			bresult.reject("error.duplicate.user");
			return mav;
		} catch (Exception e) {
			e.printStackTrace();
			return mav;
		}
		mav.setViewName("redirect:login");
		return mav;
	}
}

 

config/MvcConfig

utf-8설정해야된다

@Bean // 메세지를 코드값으로 처리하기 위한 설정
	public MessageSource messageSource() {
		ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
		ms.setBasename("messages"); // messages.properties로 설정
		ms.setDefaultEncoding("UTF-8");
		return ms;
	}

 

 

resources/messages.properties

typeMismatch.birthday=생년월일은 YYYY-MM-DD 형식으로 입력해 주세요
error.input.user=회원 가입 정보 입력 오류 입니다.
error.input.check=입력 정보를 확인하세요.
error.duplicate.user=중복된 아이디 입니다.
error.login.input=입력 데이터 오류 입니다.
error.login.id=아이디를 확인하세요
error.login.password=비밀번호 오류입니다.
error.required.userid=아이디는 3자이상 10자 이하로 입력하세요
error.required.password=비밀번호는 3자이상 10자 이하로 입력하세요

 

 

 

dao/UserDao

@Repository
public class UserDao {
	@Autowired
	private SqlSessionTemplate template;
	private Map<String, Object> param = new HashMap<>();
	private Class<UserMapper> cls = UserMapper.class;
	
	public void insert(User user) {
		template.getMapper(cls).insert(user);
		
	}
}

 

 

dao/mapper/UserMapper

public interface UserMapper {

	@Insert("insert into useraccount "
			+ "(userid,username,password,birthday,phoneno,postcode,address,email)"
			+ "values (#{userid},#{username},#{password},#{birthday},#{phoneno},#{postcode},#{address},#{email})")
	void insert(User user);
	
}

 


로그인

user/login

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인화면</title>
<script type="text/javascript">
function win_open(page){
	var op = "width=500, height=350, left=50, top=150";
	open(page,"",op);
}
</script>
</head>
<body>
	<h2>사용자 로그인</h2>
	<form:form modelAttribute="user" method="post" action="login" name="loginform">
		<spring:hasBindErrors name="user">
			<font color="red">
				<c:forEach items="${errors.globalErrors}" var="error">
					<spring:message code="${error.code}" />
				</c:forEach>
			</font>
		</spring:hasBindErrors>
		
		<table>
			<tr>
				<td>아이디</td>
				<td>
					<form:input path="userid"/>
					<font color="red">
						<form:errors path="userid" />
					</font>
				</td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td>
					<form:password path="password"/>
					<font color="red">
						<form:errors path="password" />
					</font>
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="submit" value="로그인">
					<input type="submit" value="회원가입" onclick="location.href='join'">
					<input type="submit" value="아이디찾기" onclick="win_open('idsearch')">
					<input type="submit" value="비밀번호찾기" onclick="win_open('pwsearch')">
				</td>
			</tr>
		</table>
	</form:form>
</body>
</html>

 

controller/UserController

/*
	1. userid 맞는 User를 db에서 조회하기
	2. 비밀번호 검증
	일치 : session.setAttribute("loginUser", dbUser) => 로그인 정보
	불일치 : 비밀번호를 확인하세요. 출력 (error.login.password)
	3. mypage로 페이지 이동 => 404 오류 발생 (임시)
	*/
	@PostMapping("login")
	public ModelAndView login(User user, BindingResult bresult, HttpSession session) {
		if(user.getUserid().trim().length() < 3 ||user.getUserid().trim().length() > 10) {
			// @Valid 어노테이션에서 등록방식으로 처리
			// messages.properties 파일에 : error.required.userid로 메세지 등록
			bresult.rejectValue("userid", "error.required");
		}
		if(user.getPassword().trim().length() < 3 ||user.getPassword().trim().length() > 10) {
			bresult.rejectValue("password", "error.required");
		}
		
		ModelAndView mav = new ModelAndView();
		if(bresult.hasErrors()) { // 등록된 오류 존재?
			// global error 등록
			bresult.reject("error.input.check");
			return mav;
		}
		
		User dbUser = service.selectUser(user.getUserid());
		if(dbUser == null) { // 아이디 없음
			bresult.reject("error.login.id");
			return mav;
		}
		if(user.getPassword().equals(dbUser.getPassword())) { // 비밀번호 일치
			session.setAttribute("loginUser", dbUser);
			mav.setViewName("redirect:mypage?userid=" + user.getUserid());
		}else { // 비밀번호 오류시
			bresult.reject("error.login.password");
			return mav;
		}
		return mav;
	}

 

service/UserService

	public User selectUser(String userid) {
		return userdao.selectOne(userid);
	}

 

UserDao

dao.mapper gpt 돌려서 해석받기

	public User selectOne(String userid) {
		param.clear();
		param.put("userid", userid);
		return template.selectOne("dao.mapper.UserMapper.select",param);
	}

 

UserMapper

	@Select({"<script>",
	    "select * from useraccount ",
	    "<if test='userid != null'> where userid=#{userid}</if>",
	"</script>"})
	List<User> select(Map<String, Object> param);

 

마이페이지

user/mypage

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Mypage</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
		$("#minfo").show()
		$("#oinfo").hide()
		$(".saleLine").each(function(){
			$(this).hide()
		})
		$("#tab1").addClass("select")
	})
	
	function disp_div(id, tab){
		$(".info").each(function(){
			$(this).hide()
		})
		$(".tab").each(function(){
			$(this).removeClass("select")
		})
		$("#" + id).show()
		$("#" + tab).addClass("select")
	}
	
	function list_disp(id){
		$("#" + id).toggle()
	}
</script>
<style type="text/css">
	.select{paddong:3px; background-color:#0000ff;}
	.select > a{color:#fff; text-decoration: none; font-weight: bold;}
	.title{text-decoration: none;}
</style>
</head>
<body>
	<table>
		<tr>
			<td id="tab1" class="tab">
				<a href="javascript:disp_div('minfo', 'tab1')" class="title">회원정보</a>
			</td>
			<c:if test="${param.userid != 'admin' }">
				<td id="tab2" class="tab">
					<a href="javascript:disp_div('oinfo', 'tab2')" class="title">주문정보</a>
				</td>
			</c:if>
		</tr>
	</table>
	
	<div id="oinfo" class="info" style="display:none; width:100%;">
		<table>
			<tr>
				<th>주문번호</th>
				<th>주문일자</th>
				<th>주문금액</th>
			</tr>
			<c:forEach items="${salelist}" var="sale" varStatus="stat">
				<tr>
					<td align="center">
						<a href="javascript:list_disp('saleLine${stat.index}')">${sale.saleid }</a>
					</td>
					<td align="center">
						<fmt:formatDate value="${sale.saledate }" pattern="yyyy-MM-dd" />
					</td>
					<td align="center">
						<fmt:formatDate value="${sale.total }" pattern="###,###" />원
					</td>
				</tr>
				<tr id="saleLine${stat.index }" class="saleLine">
					<td colspan="3" align="center">
						<table>
							<tr>
								<td>상품명</td>
								<td>상품가격</td>
								<td>주문수량</td>
								<td>상품총액</td>
							</tr>
							<c:forEach items="${sale.itemList}" var="saleItem">
								<tr>
									<td class="title">${saleItem.item.name }</td>
									<td><fmt:formatNumber value="${saleItem.item.price } pattern="###,###" />원</td>
								</tr>
							</c:forEach>
						</table>
					</td>
				</tr>
			</c:forEach>
		</table>
	</div>
	
	<div id="minfo" class="info">
		<table>
			<tr><td>아이디</td><td>${user.userid }</td></tr>
			<tr><td>이름</td><td>${user.username}</td></tr>
			<tr><td>우편번호</td><td>${user.postcode}</td></tr>
			<tr><td>전화번호</td><td>${user.phoneno }</td></tr>
			<tr><td>이메일</td><td>${user.email }</td></tr>
			<tr>
				<td>생년월일</td>
				<td><fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd" /></td>
			</tr>
		</table>
		<br/>
		<a href="logout">[로그아웃]</a>&nbsp;
		<a href="update?userid=${user.userid}">[회원정보수정]</a>&nbsp;
		<a href="password">[비밀번호수정]</a>&nbsp;
		<c:if test="${loginUser.userid != 'admin' }">
			<a href="delete?userid=${user.userid}">[회원탈퇴]</a>
		</c:if>
		<c:if test="${loginUser.userid == 'admin' }">
			<a href="../admin/list">[회원목록]</a>&nbsp;
		</c:if>
	</div>
</body>
</html>

 

 

controller/UserController

/*
	AOP 설정필요 : UserLoginAspect 클래스의 userIdCheck 메서드로 구현
	1.	로그인여부 검증
		로그아웃상태인 경우 로그아웃 후 거래 메세지 출력. login 페이지로 이동
	2. 	본인 거래 여부 검증
		admin이 아니면서 다른 사용자 정보 출력 불가
	*/
	// (마이페이지)
	@RequestMapping("mypage")
	public ModelAndView idCheckmypage(String userid, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		User user = service.selectUser(userid);
		mav.addObject("user", user);
		return mav;
	}
	
	// (로그아웃)
	@RequestMapping("logout")
	public String logout(HttpSession session) {
		session.invalidate();
		return "redirect:login";
	}

 

스프링 예외처리

MvcConfig 

aop 추가

@EnableAspectJAutoProxy // AOP 사용을 위한 설정
@ComponentScan(basePackages= {"controller", "logic", "service", "dao", "aop"})

 

pom.xml

@Aspect 어노테이션을 사용하기위해서 라이브러리 설치

	<!-- AOP 관련 설정 -->
	<dependency>
	    <groupId>javax.annotation</groupId>
	    <artifactId>javax.annotation-api</artifactId>
	    <version>1.3.2</version>
	</dependency>
	<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjweaver</artifactId>
	    <version>1.9.6</version>
	</dependency>

 

 

exception/ShopException

RuntimeException : 나는 예외처리 안해도되

@Getter
public class ShopException extends RuntimeException {
	private String url;
	public ShopException(String msg, String url) {
		super(msg);
		this.url = url;
	}
}

 

 

aop/UserLoginAspect

로그인 검증이 필요한 컨트롤러 이름 앞에 idCheck  붙여주기

 

@Around("execution(* controller.User*.idCheck*(..)) && args(..,userid,session)") 양식에 맞는 메서드

알아서 로그인 검증하여 오류메세지 출력

/*
1. pointcut : UserControlle.idCheck* 메서드로 시작하고, 마지막 매개변수가 String(userid), HttpSession 인 메서드를 설정
2. advice : Around로 이용
*/
@Component
@Aspect
public class UserLoginAspect {
	@Around("execution(* controller.User*.idCheck*(..)) && args(..,userid,session)")
	public Object userIdCheck(ProceedingJoinPoint joinPoint, String userid, HttpSession session) throws Throwable{
		User loginUser = (User) session.getAttribute("loginUser");
		if(loginUser == null || !(loginUser instanceof User)) { // 로그아웃 상태, 유저객체가 아닌경우 발동
			throw new ShopException("[idCheck] 로그인이 필요합니다.", "login");
		}
		if(!loginUser.getUserid().equals("admin") && !loginUser.getUserid().equals(userid)) {
			throw new ShopException("[idCheck] 본인 정보만 거래 가능합니다.", "../item/list");
		}
		return joinPoint.proceed();
	} 
}

 

 

MvcConfig

오류발생시 500에러 발생 + 에러 메세지 출력

- 

- 

@Bean // 예외처리 객체
	public SimpleMappingExceptionResolver exceptionHandler() {
		SimpleMappingExceptionResolver ser = new SimpleMappingExceptionResolver();
		Properties pr = new Properties();
		// 에러 발생시 exception 페이지로 전달
		pr.put("exception.ShopException", "exception");
		ser.setExceptionMappings(pr);
		return ser;
	}

 

 

 

view/exception

에러페이지 발생x 알림창으로 에러 메세지 발동

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isErrorPage="true" %>
<%-- isErrorPage="ture" : ShopException 객체가 전달됨 --%>
<script>
alert("${exception.message}")
location.href="${exception.url}"
</script>

 

728x90

'SpringBoot' 카테고리의 다른 글

[BCGD] 비전공자 백엔드 개발 도전기 (71)  (1) 2025.06.10
[BCGD] 비전공자 백엔드 개발 도전기 (70)  (0) 2025.06.10
[BCGD] 비전공자 백엔드 개발 도전기 (66)  (0) 2025.06.10
[BCGD] 비전공자 백엔드 개발 도전기 (65)  (0) 2025.06.10
[BCGD] 비전공자 백엔드 개발 도전기 (64)  (0) 2025.06.10
'SpringBoot' 카테고리의 다른 글
  • [BCGD] 비전공자 백엔드 개발 도전기 (71)
  • [BCGD] 비전공자 백엔드 개발 도전기 (70)
  • [BCGD] 비전공자 백엔드 개발 도전기 (66)
  • [BCGD] 비전공자 백엔드 개발 도전기 (65)
PUSH → MERGE → DEPLOY
PUSH → MERGE → DEPLOY
데이터 흐름과 운영 자동화를 설계하는 백엔드 개발자
  • PUSH → MERGE → DEPLOY
    Coding Dongin
    PUSH → MERGE → DEPLOY
  • 전체
    오늘
    어제
    • MEUN
      • 코테(Solved.ac + Programmers)
      • BootCamp(JAVA)
      • JAVA
      • SpringBoot
      • JavaScript
      • JSP
      • DB(SQL)
      • React
      • HTML_CSS
      • jQuery
      • SCSS
      • GSAP
      • 설치 + 꿀팁
      • 정보처리기사 오답노트
      • 정보처리기사 기출문제
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GIT
  • 공지사항

  • 인기 글

  • 태그

    정처기오답노트
    프로그래머스
    자바
    dp
    기출문제
    브루트포스
    실기
    정처기
    정보처리기사
    Level2
    정처기실기
    알고리즘
    level1
    수학
    배열
    백엔드개발자
    구현
    정렬
    정보처리기사 실기 기출문제
    코딩테스트
    백준
    완전탐색
    문자열
    시뮬레이션
    java
    피보나치
    springboot
    level0
    자료구조
    solved.ac
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.4
PUSH → MERGE → DEPLOY
[BCGD] 비전공자 백엔드 개발 도전기 (67)
상단으로

티스토리툴바