1. 프로젝트 진행 상황 및 계획
🥇 Spring 심화 프로젝트 도전 과제 3단계 끝내기 (진행 중, 25.01.03 완료 목표)
🥈 Spring 심화 프로젝트 필수 과제 2단계 끝내기 (진행 중, 25.01.03 완료 목표)
🥉 Spring 심화 프로젝트 도전 과제 4단계 끝내기 (진행 전, 25.01.04 완료 목표)
4️⃣ Spring 심화 프로젝트 도전 과제 5단계 끝내기 (진행 전, 25.01.04 완료 목표)
5️⃣ Spring 심화 프로젝트 도전 과제 6단계 끝내기 (진행 전, 25.01.05 완료 목표)
2. 고민
Q1. ifPresent()를 쓸까, isPresent()를 쓸까?
package org.example.expert.domain.auth.service;
import lombok.RequiredArgsConstructor;
import org.example.expert.config.JwtUtil;
import org.example.expert.config.PasswordEncoder;
import org.example.expert.domain.auth.dto.response.SignUpResponseDto;
import org.example.expert.domain.common.exception.InvalidRequestException;
import org.example.expert.domain.user.entity.User;
import org.example.expert.domain.user.enums.UserRole;
import org.example.expert.domain.user.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AuthService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final JwtUtil jwtUtil;
@Transactional
public SignUpResponseDto signUp(
String email,
String password,
String userRole
) {
userRepository.findByEmail(email)
.ifPresent(
user -> {
throw new InvalidRequestException(
"Email is already registered"
);
}
);
String encodedPassword = passwordEncoder
.encode(password);
UserRole role = UserRole.of(userRole);
User user = new User(
email,
encodedPassword,
role
);
User savedUser = userRepository.save(user);
String bearerToken = jwtUtil.createToken(
savedUser.getId(),
savedUser.getEmail(),
savedUser.getUserRole()
);
return new SignUpResponseDto(bearerToken);
}
}
package org.example.expert.domain.auth.service;
import lombok.RequiredArgsConstructor;
import org.example.expert.config.JwtUtil;
import org.example.expert.config.PasswordEncoder;
import org.example.expert.domain.auth.dto.response.SignUpResponseDto;
import org.example.expert.domain.common.exception.InvalidRequestException;
import org.example.expert.domain.user.entity.User;
import org.example.expert.domain.user.enums.UserRole;
import org.example.expert.domain.user.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AuthService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final JwtUtil jwtUtil;
@Transactional
public SignUpResponseDto signUp(
String email,
String password,
String userRole
) {
boolean isEmailRegistered = userRepository
.findByEmail(email)
.isPresent();
if (isEmailRegistered) {
throw new InvalidRequestException(
"Email is already registered"
);
}
String encodedPassword = passwordEncoder
.encode(password);
UserRole role = UserRole.of(userRole);
User user = new User(
email,
encodedPassword,
role
);
User savedUser = userRepository.save(user);
String bearerToken = jwtUtil.createToken(
savedUser.getId(),
savedUser.getEmail(),
savedUser.getUserRole()
);
return new SignUpResponseDto(bearerToken);
}
}
A1. 처음에는 ifPresent() 메서드(method)를 활용했으나 userRepository.findByEmail(email) 부분은 다른 데서도 쓰일 가능성이 매우 높았고, boolean 변수를 활용하여 '무엇을 검증하는지' 한눈에 보이도록 구현하고 싶었다. 이런 이유로 isPresent() 메서드를 활용했다.
3. 팀 프로젝트 전에 팀에서 정한 코드 작성 규칙(코드 컨벤션, code convention)
① DTO 클래스(class) 이름 짓는 법
- Create / Read / Update / Delete + 엔티티(entity) 이름 + Request / Response + Dto
- 단, 회원가입은 Create 대신 SignUp으로, 로그인은 SignIn으로 짓는다.
- 예시) CreateMemberRequestDto / UpdateTodoResponseDto / ManagerResponseDto
② '수정'은 메서드, 변수, 클래스 상관없이 'update'로 통일
- 'change' 및 'modify'는 사용하지 않기로 했다.
③ List 변수 이름 짓는 법
- 객체 이름 + List
- 예시) List<UserResponseDto> userDtoList / List<Todo> todoList
④ List는 반드시 ArrayList로 먼저 초기화하기
List<Manager> managerList = new ArrayList<>();
managerList = managerRepository.findAllByTodoId(todo.getId());
List<ManagerResponseDto> managerDtoList = new ArrayList<>();
⑤ 클래스 이름 짓는 법
- 객체 이름 + Controller / Service / Repository 이름
- 예시) UserService, ManagerRepository
⑥ DTO(Data Transfer Object) 이름은 requestDto / responseDto 둘 중 하나로 짓기
@PatchMapping("/edit/{id}")
public ResponseEntity<Void> updateUser(
@PathVariable UUID id,
@RequestBody @Valid UserUpdateRequestDto requestDto
)
⑦ return 할 때 new ResponseEntity<>() 사용하기
return new ResponseEntity<>(responseDto, HttpStatus.CREATED);
⑧ 생성자는 어노테이션(annotation) 대신 직접 입력하기
- 나중에 어노테이션을 삭제해야 하는 상황이 왔을 때 곤란해질 수 있으며, 지나치게 의존하면 내부 구현이 어떻게 이루어지는지 모를 수 있으므로 직접 입력하기로 했다.
⑨ if문의 조건식은 boolean 변수로 작성하기
boolean isUserMismatch = !ObjectUtils.nullSafeEquals(
user.getId(),
todo.getUser().getId()
);
if (isUserMismatch) {
throw new InvalidRequestException("User does not match");
}
⑩ 컨트롤러(Controller)의 어노테이션(annotation)은 하나씩 줄 바꾸기
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{userId}")
public ResponseEntity<UserResponseDto> readUserById(
@PathVariable long userId
) {
UserResponseDto responseDto = userService.readUserById(userId);
return new ResponseEntity<>(responseDto, HttpStatus.OK);
}
@PutMapping
public ResponseEntity<Void> updatePassword(
@Auth AuthUser authUser,
@RequestBody UpdatePasswordRequestDto requestDto
) {
userService.updatePassword(
authUser.id(),
requestDto
);
return new ResponseEntity<>(HttpStatus.OK);
}
}
4. 회고
도전 과제 3단계가 정말 뜯어고쳐야 할 부분이 넘쳐 나서 아침에 다 같이 모여 90분 동안 코드 작성 규칙을 미리 정했다. 개인 프로젝트라서 지금 당장 지켜야 할 의무는 없으나 미리 연습하면 좋으니, 규칙에 따라 리팩토링(refactoring)을 진행했다. 내일은 적어도 4단계까지 깔끔하게 끝내서 주말에 테스트 코드 수정하기인 5단계와 스스로 문제를 정의하고 해결해야 하는 6단계에 오롯이 집중할 수 있다. 내일은 오늘보다 더 집중하고, 한 번 더 운동해서 건강을 챙기도록 해야겠다.
'끝을 보는 용기' 카테고리의 다른 글
Day 090 - Spring 심화 프로젝트 5단계 완료, 첫 테스트 코드 작성 (0) | 2025.01.04 |
---|---|
Day 089 - Spring 심화 프로젝트 3단계 및 4단계 완료, 단순한 개발자가 아니라 창작자가 되고 싶다. (0) | 2025.01.03 |
Day 087 - 심화 Spring 3주차 완강, Spring 심화 프로젝트 3단계 진행 중, 지금 눈앞에 있는 코드는 꿈일 거야 (0) | 2025.01.01 |
Day 086 - 심화 Spring 2주차 완강, Spring 심화 프로젝트 1단계 완료, 팀장 특강을 열어도 될까? (0) | 2024.12.31 |
Day 085 - 심화 Spring 1주차 완강, 눈에 띄는 기술 블로그를 운영하려면 어떤 글을 써야 좋을까? (0) | 2024.12.30 |