[Spring] 숙련 Lv.1 과제

호호빵·2022년 12월 24일
0

2022 Spring HW

목록 보기
1/3

Service에서 최소한의 일만 하도록

User

현재

  • controller에서 파라미터로 HttpServletRequest를 넘겨
    service에서 해당 데이터들로 토큰을 생성하고 헤더에 넣는 작업을 함
    -> service의 일이 무겁고 불필요한 scope가 늘어남

변경 후

  • service 로직 처리값을 토큰으로 저장하여 헤더에 넣는 작업을 controller에서 처리하게 함.
    -> scoep 최소화, 파라미터로 HttpServletRequest를 보낼 필요 없음.
# 현재  
# UserController
@PostMapping("/login")
    public StatusResponse login(@RequestBody LoginRequest request, HttpServletResponse response) {
        userService.login(request, response);
        return new StatusResponse(response);
    }
  
# UserService
@Transactional(readOnly = true)
    public void login(LoginRequest request, HttpServletResponse response) {
        String username = request.getUsername();
        String password = request.getPassword();

        User user = userRepository.findByUsername(username).orElseThrow(
                () -> new IllegalArgumentException("사용자가 존재하지 않습니다.")
        );

        if (!user.isValidPassword(password)) {
            throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
        }

        // JWT 활용 시 추가, Header에 넣어주는 작업
        response.addHeader(JwtUtil.AUTHORIZATION_HEADER, jwtUtil.createToken(user.getUsername(), user.getRole()));
    }


  # 변경 후
  # UserController
   @PostMapping("/login")
    public StatusResponse login(@RequestBody LoginRequest request, HttpServletResponse response) {
        String token = userService.login(request);
  		// Service에서 만든 토큰으로 헤더에 넣는 작업은 controller에서 처리
        response.addHeader(JwtUtil.AUTHORIZATION_HEADER, token);      

        return new StatusResponse(response);
    }  

  
  # UserService
   @Transactional(readOnly = true)
    public String login(LoginRequest request) {
        String username = request.getUsername();
        String password = request.getPassword();

        User user = userRepository.findByUsername(username).orElseThrow(
                () -> new IllegalArgumentException("사용자가 존재하지 않습니다.")
        );

        if (!user.isValidPassword(password)) {
            throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
        }

        // JWT 활용 시 추가
        return jwtUtil.createToken(user.getUsername(), user.getRole());
    }
  

Post

현재

  • 토큰이 유효한지 검증하는 과정을 HttpServletRequest를 파라미터로 같이 보내어서 service에서 검증

변경 후

  • 파라미터값을 보낼 필요없이 토큰이 유효한지 검증하는 과정을 controller에서 처리하고 서비스 로직만 service에 구현하도록 함
# 현재
#PostController
@PostMapping("/posts")
    public PostResponse createPost(@RequestBody PostRequest requestDto, HttpServletRequest request) {
        return postService.createPost(requestDto, request);
    }
    
# PostService
@Transactional
    public PostResponse createPost(PostRequest requestDto, HttpServletRequest request) {
        String token = jwtUtil.resolveToken(request);
        Claims claims;   // JWT 내 정보를 담을 수 있는 객체라고 생각하기

        // 토큰이 있는 경우에만 관심상품 추가 가능
        if (token != null) {
            if (jwtUtil.validateToken(token)) {
                // 토큰에서 사용자 정보 가져오기
                claims = jwtUtil.getUserInfoFromToken(token);
            } else {
                throw new IllegalArgumentException("Token Error");
            }

            // 토큰에서 가져온 사용자 정보를 사용하여 DB 조회
            User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
                    () -> new IllegalArgumentException("사용자가 존재하지 않습니다.")
            );

            // 요청받은 DTO 로 DB에 저장할 객체 만들기
            Post post = postRepository.saveAndFlush(new Post(requestDto, user));

            return new PostResponse(post, user);
        } else {
            return null;
        }
    }
    
    
    
    ▽
    ▽
  
  
# 변경 후 
#PostController
@PostMapping("/posts")
    public PostResponse createPost(@RequestBody PostRequest requestDto, HttpServletRequest request) {
        String token = jwtUtil.resolveToken(request);
        Claims claims;

        if (token != null) {
            if (!jwtUtil.validateToken(token)) {
                throw new IllegalArgumentException("토큰값이 잘못되었습니다.");
            }
            claims = jwtUtil.getUserInfoFromToken(token);
            String usernameOfToken = claims.getSubject();

            return postService.createPost(requestDto, usernameOfToken);
        } else {
            throw new IllegalArgumentException("토큰이 존재하지 않습니다.");
        }
    }
  
# PostService
 @Transactional
    public PostResponse createPost(PostRequest requestDto, String usernameOfToken) {

        User user = userRepository.findByUsername(usernameOfToken).orElseThrow(
                () -> new IllegalArgumentException("사용자가 존재하지 않습니다.")
        );
        Post post = new Post(requestDto, user);
        postRepository.save(post);
        return new PostResponse(post, user);
    }
  • 마지막에 service에서 DB접근도 최소화하기 위해 username을 얻어 toEntity 메소드를 쓰고 싶은데 가져오는 것이 그럴려면 DB 접근없이 user를 가져오든 처음부터 username을 참조하든 해야해서 좀 더 고심해봐야겠다.
    (JWT의 장점 db의 접근을 줄임)



더 알아보기

  • parserBuilder
  • generatedID
  • HttpServletResponse
profile
하루에 한 개념씩

0개의 댓글