티스토리 뷰
SpringBoot로 게시판 만들기 실습 / 4 - 2. 로그인, 로그아웃 기능 구현하기
GrapeMilk 2020. 12. 11. 18:08실습4 - 1에서는 JSP로 메인, 로그인 화면을 구현했습니다.
이번장에서는 로그인과 로그아웃 기능을 만들어 보겠습니다.
실습4 - 1에서 생각해볼 내용
- POST방식에서 데이터의 전송 흐름
- $(document).ready(function() ~) 이란?
- jstl이란?
Goal
- 로그인 기능 구현
- 로그아웃 기능 구현
[로그인 흐름]
사용자는 아이디와, 비밀번호를 입력하여 로그인을 요청합니다.
백엔드에서의 역할은 사용자로부터 입력받은 정보를 확인하여 데이터베이스의 정보화 조회한 뒤 로그인 처리를 한 후 결과를 반환하는 것 입니다.
1. UserController
- 컨트롤러에서는 사용자로부터 입력받은 정보를 받아 유효성을 판단한 뒤 service에 작업을 요청합니다.
*Controller란?
: 컨트롤러는 클라이언트가 보낸 데이터를 적절히 가공하여 모델에 보내고 모델이 업무 수행을 완료하면, 그 결과를 가지고 화면을 생성하도록 뷰에 전달합니다. SpringBoot에서는 @Controller 어노테이션을 사용하여 Controller class라는 것을 명시합니다.
- User와 관련된 기능을 처리하는 Controller는 UserController로 네이밍하겠습니다.
1) UserController 전체 코드
package com.coronabook.springboot.controller;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.RequestParam;
import com.coronabook.springboot.model.User;
import com.coronabook.springboot.service.UserService;
@Controller
@RequestMapping("/user")
public class UserContorller {
@Autowired
private UserService userService;
@GetMapping(value = "/login")
public String login() {
return "user/login";
}
@PostMapping("/login")
public String login(@RequestParam Map<String, String> map, Model model, HttpSession session) {
try {
if (map.get("userid") == null || map.get("userpwd") == null) {
model.addAttribute("msg", "아이디 또는 비밀번호를 입력해주세요");
return "error/error";
}
User user = userService.login(map);
if (user != null) {
session.setAttribute("user", user);
} else {
model.addAttribute("msg", "아이디 또는 비밀번호가 올바르지 않습니다.");
return "error/error";
}
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("msg", "로그인 중 문제가 발생했습니다.");
return "error/error";
}
return "index";
} // end of PostMapping("login")
}
[UserController 코드 설명]
@Controller
@RequestMapping("/user")
public class UserContorller {
- @Controller, @RequestMapping("/user")
: @Controller은 @Component에서 Controller를 특정지을 수 있도록 한 어노테이션 입니다. 어노테이션이 붙은 class는 implement될 때 classpath scanning에 의해 자동으로 스캔됩니다. @Controller는 주로 @RequestMapping 어노테이션과 자주 사용됩니다. @RequestMapping 어노테이션은 요청을 처리하는 (request handling) 메서드의 위에 작성합니다. 클래스의 위에 작성하면, 해당 클래스의 접근에 URL 매핑을 해줍니다.
: 따라서 UserController에 접근할 때는 context-path/user URL로 접근하고, login 메서드에 접근할 때는 context-path/user/login 형식으로 접근합니다.
@Autowired
private UserService userService;
- @Autowired (참고 : Autowired를 사용하기 위해 이해해야 하는 Spring component 구조)
: @Autowired 어노테이션은 해당 어노테이션을 선언한 코드에 Autowire을 해줍니다. Autowire된 객체는 사용자가 직접 new로 생성하는 것이 아닌 Spring이 객체를 생성해서 주입해줍니다. 이러한 객체의 주입을 의존성주입 (DI)라고 합니다.
- Service
: Spring MVC 패턴에서 Model은 일반적으로 Service와 DAO로 구성되어 있습니다. 사용자의 데이터를 가공하여 Model로 보내는 Controller는 우선적으로 Service를 호출하여 Service에 데이터 처리를 요청합니다.
@GetMapping(value = "/login")
public String login() {
return "user/login";
}
- Get방식으로 user/login URL에 들어온 사용자의 요청을 받으면 login화면을 보여주는 코드입니다. String으로 반환된 "user/loing"에서는 viewResolver를 통해 .jsp파일의 위치로 변환되어 해당 페이지를 띄워줄 수 있게 됩니다.
@PostMapping("/login")
public String login(@RequestParam Map<String, String> map, Model model, HttpSession session) {
try {
if (map.get("userid") == null || map.get("userpwd") == null) {
model.addAttribute("msg", "아이디 또는 비밀번호를 입력해주세요");
return "error/error";
}
User user = userService.login(map);
if (user != null) {
session.setAttribute("user", user);
} else {
model.addAttribute("msg", "아이디 또는 비밀번호가 올바르지 않습니다.");
return "error/error";
}
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("msg", "로그인 중 문제가 발생했습니다.");
return "error/error";
}
return "index";
} // end of PostMapping("login")
- Post 방식으로 user/login URL에 요청을 하면 페이지 이동이 아닌 사용자 로그인을 처리합니다.
- 요청받은 데이터인 userid와 userpwd를 확인하여 error페이지로 에러메세지를 보낼지, 로그인을 처리하는 service 메서드를 호출할지 if문을 통해 확인합니다.
- session.setAttribute : model단에서 받어온 userid, userpwd에 해당하는 user가 있을 경우 session에 해당 정보 유저를 저장하여 index페이지로 이동합니다. index 페이지에서는 sessionScope에 저장된 user데이터에 따라 로그인정보가 인식됩니다.
2. UserService
*Service란?
: Service는 트랜잭션의 한 단위입니다. 트랜잭션이란 하나의 논리적 기능을 수행하기 위한 작업의 단위로서 로그인기능을 예로 들었을 때, login을 하기 위해 userid와 userpwd를 DB에서 확인하기 위해 수행하는 하나의 작업을 의미합니다. Service의 작업은 하나이지만 이 작업을 수행하기 위해서는 DAO가 여러번 불릴 수 있습니다. 따라서 Service에서 논리적으로 처리하는 하나의 작업에는 많은 수의 DAO호출이 있을 수 있기 때문에 Service와 DAO를 나누는 것이 적절합니다.
- User와 관련된 Service이기 때문에 UserService로 네이밍하겠습니다.
1) UserService 전체 코드
1-1) UserService.java
package com.coronabook.springboot.service;
import java.util.Map;
import com.coronabook.springboot.model.User;
public interface UserService {
public User login(Map<String, String > map) throws Exception;
}
[UserService.java 코드설명]
- Service는 재사용성과 확장성을 위해 인터페이스와 구현부분으로 분리하겠습니다.
- login 처리를 수행할 수 있는 메서드를 정의합니다. ServiceImpl이 해당 메서드를 구현합니다.
1-2) UserServiceImpl.java
package com.coronabook.springboot.service;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.coronabook.springboot.mapper.UserMapper;
import com.coronabook.springboot.model.User;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
public User login(Map<String, String> map) throws Exception {
return userMapper.login(map);
}
}
[UserServiceImpl.java 코드설명]
@Service("userService")
- Spring이 해당 클래스가 Service임을 알 수 있도록 @Service 어노테이션을 명시합니다. 어노테이션을 명시하면서 이름을 부여할 수 있습니다.
@Autowired
private UserMapper userMapper;
public User login(Map<String, String> map) throws Exception {
return userMapper.login(map);
}
- Service는 작업단위를 수행하기 위해 데이터베이스와 연결하여 로직을 처리하는 Mapper클래스를 필요로합니다. UserMapper를 사용하기 위해 @Autowired를 통해 객체를 주입할 수 있도록 합니다.
- login 메서드는 userMapper의 login메서드를 호출합니다. Mapper의 login메서드는 데이터베이스와 직접 소통하여 login 처리를 할 것입니다.
3. UserMapper
- Mapper 인터페이스는 Mapper XML파일에 있는 SQL을 호출하기 위한 인터페이스 입니다.
- @Mapper 어노테이션은 해당 interface가 Mapper 인터페이스임을 알려줍니다.
* Mapper 인터페이스는 Implementation을 필요로 하지 않습니다. 좀 더 자세히 알아보려면 참고하세요 ( DAO vs Mapper Interface )
package com.coronabook.springboot.mapper;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import com.coronabook.springboot.model.User;
@Mapper
@Repository
public interface UserMapper {
public User login(Map<String, String> map);
}
- @Repository
: @Repository은 해당 클래스가 repository임을 알려줍니다. class scanning을 통해 @Repository를 Spring beans로 등록됩니다. 스프링에서 Repository는 해당 클래스가 storage, retrieval, search, update 그리고 delete의 기능을 제공하는 클래스를 의미합니다.
4. mapper/user.xml
- Mapper XML파일은 resources안에 mapper라는 파일을 두어 따로 관리하겠습니다.
* Mapper XML
: Mapper XML파일은 select, insert, update 그리고 delete와 같인 SQL문들을 설정하는 코드들을 포함하는 Mybatis의 파일입니다. XML에 선언된 코드들은 Mapped Statements 또는 Mapped SQL Statements라고 불립니다.
( mapper XML file prevents the burden of writing SQL statements repeatedly in the application. In comparison to JDBC, almost 95% of the code is reduced using Mapper XML file in MyBatis. )
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.coronabook.springboot.mapper.UserMapper">
<select id="login" parameterType="map" resultType="User">
select username, userid, email
from user
where userid = #{userid} and userpwd = #{userpwd}
</select>
</mapper>
<mapper namespace="com.coronabook.springboot.mapper.UserMapper">
<mapper namespace=~> </mapper> : Mapper XML안의 모든 Mapped SQL statements는 <mapper>라는 이름의 element안에 작성되어 있습니다. <mapper> element는 namespace라는 속성값을 같습니다. namespace와 Mapped Statements의 id를 확인하여 UserMapper에 작성한 메서드와 해당 SQL문을 매핑해줍니다. 따라서 메서드에서 전달된 데이터를 사용할 수 있고 SQL의 결과를 다시 메서드로 반환할 수 있게 됩니다.
<select id="login" parameterType="map" resultType="User">
select username, userid, email
from user
where userid = #{userid} and userpwd = #{userpwd}
</select>
- 모든 statements는 unique한 id를 갖습니다. 이 id는 UserMapper.java에 정의된 login 메서드와 매핑됩니다.
5. 실행화면
* 현재 회원가입 기능이 구현 되어있지 않습니다. 다음 sql문을 복사하고 실행하여 user 테이블에 생성하고 해당 사용자 정보로 로그인을 테스트 해보세요
- test사용자 insert sql
insert into user (userid, username, userpwd, email, phonenumber, address, joindate)
values ("11", "11", "11", "11@11.com", "11", "11", now());
- 자 이제 로그인 기능이 완료되었습니다. 서버를 실행하고 매핑된 URL(http://localhost:8000/coronabook/)로 방문했을 때 다음과 같은 화면이 나오고 로그인이 정상적으로 이루어지면 완성입니다!
이번 장에서는 로그인 기능을 구현하고 Spring MVC 패턴에서 각 컴포넌트의 기능에 대해 알아보았습니다.
글이 길어진 관계로 다음장에서 로그아웃을 구현하겠습니다.
'Spring > SpringBoot & AWS' 카테고리의 다른 글
SpringBoot로 게시판 만들기 실습 / 4 - 1. 로그인, 로그아웃 기능 구현하기 (0) | 2020.12.09 |
---|---|
SpringBoot로 게시판 만들기 실습 / 3. DB설계, 화면설계 (0) | 2020.12.08 |
SpringBoot로 게시판 만들기 실습 / 2. 첫 번째 JSP 실행하기 (0) | 2020.12.08 |
SpringBoot로 게시판 만들기 실습 / 1. 개발환경 준비 및 프로젝트 생성 (0) | 2020.12.07 |
- 20200415
- 20200804
- 20200427
- 20200413
- 20200428
- 백준
- 20200622
- 20200504
- 20200417
- 20200502
- 20200423
- 20200420
- 20200317
- 20200510
- 20200403
- 20200319
- 20201204
- 20200425
- 20200624
- 20200424
- chapter7
- 20200406
- likelion
- 20200429
- chapter8
- 20200421
- 20200503
- 생활코딩리눅스
- 20200330
- 20200512
- Total
- Today
- Yesterday