Tiny Star

📌TIL [Today I Learn]

[TIL] 23년 7월 31일 월요일

청크 2023. 8. 1. 23:02

23년 7월 31일 월요일

오늘의 목표 : JPA, JWT 복습/플러스 주차 복습과제

 

오늘 공부한 내용🤓

지난주 내내 정리했던 JPA, JWT 관련 내용 게더타운 동기들한테 알려주고 배우면서 복습하는 시간을 가졌다.

한번 훑어보고 친한 동기들이랑 플러스 주차 복습과제를 시작했다.

 

우선 동기들이랑 1차로 구현하기로 한 목표!

 

[UserService]

package com.sparta.plus.service;


import com.sparta.plus.dto.ApiResponseDto;
import com.sparta.plus.dto.AuthRequestDto;
import com.sparta.plus.dto.SignupRequestDto;
import com.sparta.plus.entity.User;
import com.sparta.plus.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    //회원가입
    // 닉네임, 비밀번호, 비밀번호 확인을 request 에서전달받기
    // 닉네임과 같은 값이 포함된 경우 회원가입에 실패로 만들기
    // 비밀번호 확인은 비밀번호와 정확하게 일치하기
    // 데이터베이스에 존재하는 닉네임을 입력한 채 회원가입 버튼을 누른 경우 "중복된 닉네임입니다." 라는 에러메세지를 response 에 포함하기
    @Transactional
    public ResponseEntity<ApiResponseDto> Signup(SignupRequestDto signupRequestDto) {
        String nickName = signupRequestDto.getNickName();
        String password = passwordEncoder.encode(signupRequestDto.getPassword());
       String rePassword = passwordEncoder.encode(signupRequestDto.getRePassword());

        // 유저 닉네임 중복확인
        if (userRepository.findByNickName(nickName).isPresent()) {
//            throw new IllegalArgumentException("이미 존재하는 닉네임입니다. 다른 닉네임을 입력해주세요.");
            return ResponseEntity.status(400).body(new ApiResponseDto("이미 존재하는 닉네임입니다. 다른 닉네임을 입력해주세요.",HttpStatus.BAD_REQUEST.value()));
        }
        // 비밀번호 2번확인
        if (!signupRequestDto.getPassword().equals(signupRequestDto.getRePassword())) {
//            throw new IllegalArgumentException("입력하신 비밀번호가 다릅니다. 비밀번호 일치여부를 확인해주세요.");
            return ResponseEntity.status(400).body(new ApiResponseDto("입력하신 비밀번호가 다릅니다. 비밀번호 일치여부를 확인해주세요.",HttpStatus.BAD_REQUEST.value()));
        }
        // 닉네임과 비밀번호를 비교하여 같은 값이 포함되어 있으면 회원가입 실패
        if (signupRequestDto.getNickName().contains(signupRequestDto.getPassword())){
//            throw new IllegalArgumentException("비밀번호에는 닉네임을 사용할 수 없습니다.");
            return ResponseEntity.status(400).body(new ApiResponseDto("비밀번호에는 닉네임을 사용할 수 없습니다.",HttpStatus.BAD_REQUEST.value()));
        }
        User user = new User(nickName, password, rePassword);
        userRepository.save(user);
        return ResponseEntity.status(201).body(new ApiResponseDto("회원가입이 완료 되었습니다.", HttpStatus.CREATED.value()));
}
    //로그인
    // 닉네임, 비밀번호를 request 에서전달받기
    // 로그인 버튼을 누른 경우 닉네임과 비밀번호가 데이터베이스에 등록됐는지 확인한 뒤, 하나라도 맞지 않는 정보가 있다면 "닉네임 또는 패스워드를 확인해주세요."라는 에러 메세지를 response 에 포함하기
    // 로그인 성공 시 로그인에 성공한 유저의 정보를 JWT를 활용하여 클라이언트에게 Cookie로 전달하기
    @Transactional
    public ResponseEntity<ApiResponseDto> signin(AuthRequestDto authRequestDto) {
        String nickName = authRequestDto.getNickName();
        String password = authRequestDto.getPassword();

        User user = userRepository.findByNickName(nickName).orElse(null);

        if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
            return ResponseEntity.status(400).body(new ApiResponseDto("닉네임 또는 패스워드를 확인해주세요.", HttpStatus.BAD_REQUEST.value()));
        } else {
            return ResponseEntity.status(201).body(new ApiResponseDto("로그인 성공", HttpStatus.CREATED.value()));
        }

    }
}

[UserController]

Controller는 깔끔하게 작성할 수 있었다.

package com.sparta.plus.controller;

import com.sparta.plus.dto.ApiResponseDto;
import com.sparta.plus.dto.AuthRequestDto;
import com.sparta.plus.dto.SignupRequestDto;
import com.sparta.plus.jwt.JwtUtil;
import com.sparta.plus.service.UserService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequiredArgsConstructor
@RequestMapping("/api")
public class UserController {

        private final UserService userService;
        private final JwtUtil jwtUtil;

        // 회원가입
        @PostMapping("auth/signup")
        public ResponseEntity<ApiResponseDto> signup (@RequestBody SignupRequestDto signupRequestDto) {
            return userService.Signup(signupRequestDto);
        }
        // 로그인
        @PostMapping("/auth/signin")
        public ResponseEntity<ApiResponseDto> signin(@RequestBody AuthRequestDto authRequestDto, HttpServletResponse response) {
                // JWT 생성 및 쿠키에 저장 후 Response 객체에 추가
                response.addHeader(JwtUtil.AUTHORIZATION_HEADER, jwtUtil.createToken(authRequestDto.getNickName(), authRequestDto.getRole()));
                return userService.signin(authRequestDto);
        }
}
어려웠던 내용😵‍💫

처음에 구현했을 때는 Controller에서 ResponseEntity를 반환하는 코드로 작성을 했었다.

 

그러나 Service Class에서 어떤 권한의 문제가 발생하면 응답 값을 반환해야 한다는 걸 뒤늦게 깨닫고 바꾼 코드.

ResponseEntity를 Controller에서 반환하는 코드로 작성해도 코드 상의 문제는 발생하지 않지만,

Controller에서 던진 응답코드는 실행창에서 개발자만 확인이 되고 내가 의도했던 유저한테 코드가 전달되지 않는 문제가 발생하는 것이다.

궁금&부족한 내용❓

 

느낀 점💡

곰곰히 고민해보면서 코드를 짜면 못할 것도 없다!

자바만큼 친절한 언어는 또 없을지도....🤚🏻

'📌TIL [Today I Learn]' 카테고리의 다른 글

[TIL] 23년 8월 16일 수요일  (0) 2023.08.16
[TIL] 23년 8월 1일 화요일  (0) 2023.08.01
[TIL] 23년 7월 28일 금요일  (0) 2023.07.28
[TIL] 23년 7월 27일 목요일  (0) 2023.07.27
[TIL] 23년 7월 26일 수요일  (0) 2023.07.26