๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Spring๐Ÿ€/๊ฐ„๋‹จํ•œ ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ

[JPA] ๊ฐ„๋‹จํ•œ ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ - user (UserService)

by @ENFJ 2023. 2. 12.

 

์ง€๋‚œ์‹œ๊ฐ„ ๊นŒ์ง€ entity, DTO, Repository ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์•˜๋‹ค.

 

์˜ค๋Š˜์€ ํšŒ์› Serivce ํŒจํ‚ค์ง€๋ฅผ ์ƒ์„ฑํ•˜์—ฌ UserService ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ๋‹ค.

 

๋จผ์ € ์„œ๋น„์Šค! ์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ฐœ๋…? ์ •๋ฆฌ ํ•˜๊ณ  ๊ฐ€๊ฒ ๋‹ค.


 

Service ๋ž€?

 

์ž Service๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ํฐ ํ‹€์„ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. Client๊ฐ€ Request๋ฅผ ๋ณด๋‚ธ๋‹ค.(Ajax, Axios, fetch๋“ฑ..)
  2. Request URL์— ์•Œ๋งž์€ Controller๊ฐ€ ์ˆ˜์‹  ๋ฐ›๋Š”๋‹ค. (@Controller , @RestController)
  3. Controller ๋Š” ๋„˜์–ด์˜จ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Service ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  4. Service๋Š” ์•Œ๋งž์€ ์ •๋ณด๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ Controller์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ธด๋‹ค.
  5. Controller ๋Š” Service ์˜ ๊ฒฐ๊ณผ๋ฌผ์„ Client ์—๊ฒŒ ์ „๋‹ฌํ•ด์ค€๋‹ค.

Service๊ฐ€ ์•Œ๋งž์€ ์ •๋ณด๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ๊ณผ์ •์„ '๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.' ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
Service๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๋Š” DAO๋ฅผ ์ด์šฉํ•ด์„œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ›์•„ ์˜ต๋‹ˆ๋‹ค.


 

 

์ด๊ฒŒ ๋ฌด์Šจ๋ง์ด๋ƒ๋ฉด 

์šฐ๋ฆฌ๊ฐ€ ์ฃผ์†Œ์ฐฝ์— http://www.naver.com ์„ ์ž…๋ ฅํ•˜๋ฉด ๋„ค์ด๋ฒ„ ํ™ˆํŽ˜์ด์ง€๋กœ ์ ‘์†ํ•˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋กœ๊ทธ์ธ์„ ํ•˜๊ธฐ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ์ฃผ์†Œ ๋’ค์— /login ์„ ๋ถ™์—ฌ์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

๊ทธ๋ ‡๋‹ค๋ฉด http://www.naver.com/login ์— ์ ‘์†ํ•˜๋ฉด ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ• ๊ฒƒ์ด๋‹ค.

 

์œ„ ๊ณผ์ •์—์„œ client ์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ์ฃผ์†Œ์ฐฝ์— ํ•ด๋‹น url์„ ๋„ฃ์–ด์„œ ์—”ํ„ฐํ‚ค๋ฅผ ๋”ฑ ๋ˆ„๋ฅด๋Š” ์ˆœ๊ฐ„ 

1 ๋ฒˆ ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ 5๋ฒˆ๊นŒ์ง€  ์‹คํ–‰๋œ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 

 

 

์ฆ‰, ํ•ด๋‹น ์„œ๋น„์Šค์— ๋Œ€ํ•ด์„œ๋Š” service ํŒจํ‚ค์ง€์—์„œ ๋‹ด๋‹นํ•œ๋‹ค.

๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์˜ ํ•ต์‹ฌ ๋กœ์ง์€ ์„œ๋น„์Šค์— ์žˆ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์„œ๋น„์Šค๋Š” ํ•ด๋‹น ๊ธฐ๋Šฅ! ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ๋กœ๊ทธ์ธ์œผ๋กœ ๊ฐ€์ •ํ•˜๋ฉด ๋กœ๊ทธ์ธ ํ•ต์‹ฌ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” DB์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ์ด์šฉํ•ด์•ผ ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํšŒ์›๋ ˆํฌ์ง€ํ† ๋ฆฌ(UserRepository) ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์„œ๋น„์Šค ๋กœ์ง์„ ์ง ๋‹ค.

 


๋Œ€๋žต์ ์ธ ์„œ๋น„์Šค ํ๋ฆ„? ์ดํ•ด๋ฅผ ํ–ˆ๋”ฐ๋ฉด ์ด์ œ ์ฝ”๋“œ๋ฅผ ๋ณด์ž!

 

UserService ์ „์ฒด ์ฝ”๋“œ

package com.example.projectpicker.user.service;

import com.example.projectpicker.security.TokenProvider;
import com.example.projectpicker.user.dto.LoginResponseDTO;
import com.example.projectpicker.user.dto.UserSignUpDTO;
import com.example.projectpicker.user.dto.UserSignUpResponseDTO;
import com.example.projectpicker.user.entity.UserEntity;
import com.example.projectpicker.user.exception.DuplicatedEmailException;
import com.example.projectpicker.user.exception.NoRegisteredArgumentsException;
import com.example.projectpicker.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;


@Service
@Slf4j
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;

    private final PasswordEncoder passwordEncoder;

    private final TokenProvider tokenProvider;

    // ํšŒ์›๊ฐ€์ž… ์ฒ˜๋ฆฌ PART
    public UserSignUpResponseDTO create(final UserSignUpDTO userSignUpDTO){ //final ํ‚ค์›Œ๋“œ: ํด๋ž˜์Šค๋‚˜ ๋ณ€์ˆ˜์— final์„ ๋ถ™์ด๋ฉด ์ฒ˜์Œ ์ •์˜๋œ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค๋Š” ์˜๋ฏธ

        // ๊ฐ€์ž…์ •๋ณด๊ฐ€ null ์ผ๋•Œ
        if(userSignUpDTO == null){
            throw new NoRegisteredArgumentsException("๊ฐ€์ž…์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.");
        }

        final String email = userSignUpDTO.getEmail(); // ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ(์ด๋ฉ”์ผ)

        // ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ์ธ ๊ฒฝ์šฐ
        if(userRepository.existsByUserEmail(email)){
            log.warn("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค. - {}",email);
            throw new DuplicatedEmailException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค.");
        }

        //ํŒจ์Šค์›Œ๋“œ ์ธ์ฝ”๋”ฉ (์•”ํ˜ธํ™”์ฒ˜๋ฆฌ)
        String rawPassword = userSignUpDTO.getPassword(); // ํ‰๋ฌธ ๋น„๋ฐ€๋ฒˆํ˜ธ
        String encodedPassword = passwordEncoder.encode(rawPassword); //passwordEncoder ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™” ์ฒ˜๋ฆฌ
        userSignUpDTO.setPassword(encodedPassword); // ์•”ํ˜ธํ™”๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ์„ค์ •!

        UserEntity savedUser = userRepository.save(userSignUpDTO.toEntity()); // ์œ„ ๊ณผ์ •์„ ์ €์žฅ!

        log.info("ํšŒ์› ๊ฐ€์ž… ์„ฑ๊ณต!! - user_id: {} ", savedUser.getUserId());
        return new UserSignUpResponseDTO(savedUser); // ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต๊ฒฐ๊ณผ์—๋Š” savedUSer(์•”ํ˜ธ์ฒ˜๋ฆฌ๋œ) ์ •๋ณด ๋ฐ˜ํ™˜
    }


    //์ด๋ฉ”์ผ ์ค‘๋ณตํ™•์ธ
    public boolean isDuplicate(String email){
        if (email == null){
            throw new RuntimeException("์ด๋ฉ”์ผ ๊ฐ’์ด ์—†์Šต๋‹ˆ๋‹ค.");
        }
        return userRepository.existsByUserEmail(email);
    }


    // ๋กœ๊ทธ์ธ ๊ฒ€์ฆ(์ด๋ฉ”์ผ,๋น„๋ฐ€๋ฒˆํ˜ธ) PART
    public LoginResponseDTO getByCredentials(final String email, final String rawPassword){

        // ์ž…๋ ฅํ•œ ์ด๋ฉ”์ผ์„ ํ†ตํ•ด ํšŒ์›์ •๋ณด ์กฐํšŒ
        UserEntity originalUser = userRepository.findByUserEmail(email); // ์ด๋ฉ”์ผ๋กœ ์กฐํšŒ๋œ ํšŒ์›์„ originUser ์— ๋‹ด์Œ.


        // email ์กฐํšŒ๋œ ํšŒ์›์ด null ์ผ๋•Œ(์—†์„ ๋•Œ)
        if(originalUser == null) {
            throw new RuntimeException("๊ฐ€์ž…๋œ ํšŒ์›์ด ์•„๋‹™๋‹ˆ๋‹ค.");
        }

        // ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ
        if(!passwordEncoder.matches(rawPassword,originalUser.getUserPassword())){
            throw new RuntimeException("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ‹€๋ ธ์Šต๋‹ˆ๋‹ค.");
        }

        //๋กœ๊ทธ์ธ ์„ฑ๊ณต์‹œ ๋กœ๊ทธ ์ถœ๋ ฅ
        log.info("{}๋‹˜ ๋กœ๊ทธ์ธ ์„ฑ๊ณต",originalUser.getUserName());

        // ํ† ํฐ ๋ฐœ๊ธ‰
        String token = tokenProvider.createToken(originalUser);
        return new LoginResponseDTO(originalUser, token);
    }

}


/**
 *  Service๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ํฐ ํ‹€
 *
 * 1. Client๊ฐ€ Request๋ฅผ ๋ณด๋‚ธ๋‹ค.(Ajax, Axios, fetch๋“ฑ..)
 * 2. Request URL์— ์•Œ๋งž์€ Controller๊ฐ€ ์ˆ˜์‹  ๋ฐ›๋Š”๋‹ค. (@Controller , @RestController)
 * 3. Controller ๋Š” ๋„˜์–ด์˜จ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Service ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
 * 4. Service๋Š” ์•Œ๋งž์€ ์ •๋ณด๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ Controller์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ธด๋‹ค.
 * 5. Controller ๋Š” Service ์˜ ๊ฒฐ๊ณผ๋ฌผ์„ Client ์—๊ฒŒ ์ „๋‹ฌํ•ด์ค€๋‹ค.
 *
 * ์ •๋ฆฌ
 * Service๊ฐ€ ์•Œ๋งž์€ ์ •๋ณด๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ๊ณผ์ •์„ '๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.' ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
 * Service๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๋Š” DAO๋ฅผ ์ด์šฉํ•ด์„œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ›์•„ ์˜ต๋‹ˆ๋‹ค.
 */

 

๋จผ์ € ์ƒ๋‹จ์— ์œ„์น˜ํ•ด ์žˆ๋Š”  ์•„๋ž˜ ์ฝ”๋“œ๋“ค์€ ์•„๊นŒ ์งง์€ ๋งŒํ™”?์—์„œ ๋‚˜์™”์—ˆ๋Š”๋ฐ

์„œ๋น„์Šค๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๊ธฐ์œ„ํ•ด์„œ db์— ๋ฐ์ดํ„ฐ๋“ค์ด ํ•„์š”ํ•˜๋‹ค. ๋งค์šฐ ๋‹น์—ฐํ•œ ์ด์•ผ๊ธด๋ฐ ๋‚ด๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ•˜๊ธฐ์œ„ํ•ด์„œ 

db์— ๋‹ด๊ฒจ์žˆ๋Š” ๋‚˜๋ฅผ ์ธ์ฆํ•  ์ˆ˜ ์žˆ๋Š”? ๊ทธ๋Ÿฐ ๋ฐ์ดํ„ฐ๋“ค๊ณผ ์ผ์น˜ ํ•œ์ง€ ํ™•์ธํ•ด์•ผ ๋œ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— db (entity)๋ฅผ ๋ฐ”๋กœ ์ฐธ์กฐํ•˜๋Š”๊ฑด ๋ฌด๋ฆฌ๊ณ , ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์ด์šฉํ•ด์„œ db ๊ฐ’์„ ์ฐธ์กฐํ•œ๋‹ค.

 

๊ทธ๋ž˜์„œ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•ด ์„œ๋น„์Šค ๊ตฌํ˜„์— ์žˆ์–ด ํ•„์š”ํ•œ ํŒŒ์ผ (ํด๋ž˜์Šค)๋“ค์„ ๋ถ€๋ฅธ๋‹ค!

private final UserRepository userRepository;

private final PasswordEncoder passwordEncoder;

private final TokenProvider tokenProvider;

 

 

// ํšŒ์›๊ฐ€์ž… ์ฒ˜๋ฆฌ PART
public UserSignUpResponseDTO create(final UserSignUpDTO userSignUpDTO){ //final ํ‚ค์›Œ๋“œ: ํด๋ž˜์Šค๋‚˜ ๋ณ€์ˆ˜์— final์„ ๋ถ™์ด๋ฉด ์ฒ˜์Œ ์ •์˜๋œ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค๋Š” ์˜๋ฏธ

    // ๊ฐ€์ž…์ •๋ณด๊ฐ€ null ์ผ๋•Œ
    if(userSignUpDTO == null){
        throw new NoRegisteredArgumentsException("๊ฐ€์ž…์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.");
    }

    final String email = userSignUpDTO.getEmail(); // ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ(์ด๋ฉ”์ผ)

    // ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ์ธ ๊ฒฝ์šฐ
    if(userRepository.existsByUserEmail(email)){
        log.warn("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค. - {}",email);
        throw new DuplicatedEmailException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค.");
    }

    //ํŒจ์Šค์›Œ๋“œ ์ธ์ฝ”๋”ฉ (์•”ํ˜ธํ™”์ฒ˜๋ฆฌ)
    String rawPassword = userSignUpDTO.getPassword(); // ํ‰๋ฌธ ๋น„๋ฐ€๋ฒˆํ˜ธ
    String encodedPassword = passwordEncoder.encode(rawPassword); //passwordEncoder ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™” ์ฒ˜๋ฆฌ
    userSignUpDTO.setPassword(encodedPassword); // ์•”ํ˜ธํ™”๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ์„ค์ •!

    UserEntity savedUser = userRepository.save(userSignUpDTO.toEntity()); // ์œ„ ๊ณผ์ •์„ ์ €์žฅ!

    log.info("ํšŒ์› ๊ฐ€์ž… ์„ฑ๊ณต!! - user_id: {} ", savedUser.getUserId());
    return new UserSignUpResponseDTO(savedUser); // ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต๊ฒฐ๊ณผ์—๋Š” savedUSer(์•”ํ˜ธ์ฒ˜๋ฆฌ๋œ) ์ •๋ณด ๋ฐ˜ํ™˜
}

ref :https://chung-develop.tistory.com/23 ,

(https://velog.io/@jybin96/Controller-Service-Repository-%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C)