2021-03-12-TIL
2021-03-12-TIL
[PR]
미션 2: 데이터베이스 활용
안녕하세요, 코드스쿼드 백엔드 반의 August입니다. 항상 상세하고 좋은 리뷰 너무 감사합니다! 이번 과제는 주어진 요구사항인 H2 DB 설정 및 적용, 회원가입 및 회원목록 기능 구현, 개인정보 수정 기능(미션1에서 진행한 것을 약간 수정) 했습니다.
- 서버 주소 : https://august-qna.herokuapp.com/
구현 내용
미션1로부터 변경된 부분만 언급하겠습니다!
- QuestionController : 기존에 List의 size()로 id를 관리하던 부분은 모두 없어졌습니다. (@GeneratedValue)
- UserController : 기존에 user가 null인지 체크하는 부분은 service 계층으로 넘겨주었습니다. update()에서는 패스워드가 일치하는지 확인하고 일치한다면 수정하도록 했습니다.
- Question : id를 자동으로 증가하도록 했고, 나머지 칼럼들은 각 역할에 맞게 일부는 not null 제한을 두었습니다.
- User : 마찬가지로 id는 자동증가하고, 나머지 칼럼의 속성도 애노테이션으로 지정했습니다. matchPassword를 추가하여 패스워스 일치여부를 확인합니다.
- QuestionRepository/UserRepository : JPA를 적용하는 방식으로 변경했습니다.
- QuestionService : 대부분 QuestionRepository에서 제공하는 JPA 메서드를 그대로 전송해주는 역할만 하지만 findQuestionById에서는 Optional을 검증하는 로직을 포함하여 컨트롤러에서는 코드상에 변경사항이 없도록 했습니다.
- UserService : 마찬가지로 findUserById만 Optional 검증 로직이 포함되어 있습니다.
[CODE REVIEW]
미션2: 데이터베이스 적용 by 새리
[August]
- helper 기능이 궁금합니다.
- Question에 strategy = GenerationType 이부분 궁금합니다. -> 안해서 오류 나는 경우가 많다.
- public 생성자를 두는게 나은가요? 아니면 private이 나은가요? 저는 에러가 발생하던데..
- Optional로 받지 않는 방법도 있습니다.
[아이작]
- 레퍼지토리 패키지 분리
- Logger사용으로 전환
[Jane]
- 날짜가 String인데 LocalDateTime으로 변경하는 것이 좋아보인다.
- password를 getter로 가져올 필요가 없어보인다.
- 메서드명도 matchPassword에서 hasMatchingPassword로
- 255넘어가면 에러나는데 column length를 늘리는게 나을 것 같다.
[bat]
- UserController에서 matchPassword를 User에서 모두 처리하는 것으로 변경하는 것이 좋을 것 같다.
[kyu]
- 디폴트 생성자를 정의 안 해줘도 되던데? -> 기본적으로 생성자가 아예없다면 컴파일러가 디폴트 생성자를 삽입한다. 하지만 다른 생성자가 있다면 오버로딩된 디폴트 생성자를 반드시 정의해주어야 한다.
미션2: 데이터베이스 적용 by August
[Kyu]
@Column(nullable = false)
는 테스트 해보았더니 입력 폼에 내용이 없어도 써지던데, null이 오는 경우는 어떤 경우?- [아이작] : 만약 password 입력폼이 아예 없다면 User객체로 넘겨줄 때 password가 null로 넘어갑니다.
- 실제로 입력 폼에 내용이 없는 상태로 submit하면 null이 아니라 빈 문자열로 채워진 객체가 컨트롤러로 넘겨진다. 따라서 빈 문자열에 대한 처리를 해주려면 별도의 방법이 필요하다.
- [bat] :
String::trim().isEmpty()
로 빈 문자열인지 검증(validation)이 가능하다. - [Jane] :
@NotEmpty
애노테이션으로 빈 문자열 체크가 가능하다. 단,build.gradle
에 의존을 추가해주어야한다!implementation 'org.springframework.boot:spring-boot-starter-validation'
- 왜 QuestionRepositoy는 CrudRepository를 상속하고, UserRepository는 JpaRepository를 상속하는지? => 특별한 이유는 없다.
- User나 Question에서 setter만 사용하는데, 생성자를 통해서 가져오는 것과 다른지?
- 한 번만 생성하고 바꿀 필요가 없는 데이터는 생성자만을 통해서 생성하는게 맞는것 같고, 수정할 가능성이 있는 필드에 대해서는 setter를 두는 것이 맞는 것 같다. // TODO: remove to make it unmodifiable
[bat]
private final UserService userService;
로 선언할 때final
키워드 추가. 어차피 하나만 주입받는 싱글톤이므로 + 변경 방지- TODO: Column(length = 2000 ~ 4000) 기본값이 255
[아이작]
1
logging.level.com=DEBUG
개발할 때만 디버그 레벨을 쓰고, 상용으로 배포할 때는 이 설정값만 레벨업하고 배포하면 되니까 이러한 방법을 권장한 듯.
[Jane]
User::update는 setter를 사용하지 않는 것이 낫다. 내부자원에 대한 접근이 가능한데, 굳이 외부에서 사용하기 위한 메서드인 setter(내부 메서드)를 통해서 접근할 필요가 없다.
UserController::create 에서 사용자 계정을 생성과정에서 서비스 계층에서 검증을 하면 좋겠다.
TODO: validation logic in service layer -> exist userID or sth…
UserController::update에서 user.update(newUser)를 했으면 userService.save(user)로 굳이 다시 저장해줄 필요가 없다고 한다.
이미 생성된 계정에 대해서는 알아서 레코드를 찾아서 변경해준다.
by JPA?
@GeneratedValue(strategy = GenerationType.IDENTITY)
- https://stackoverflow.com/questions/20603638/what-is-the-use-of-annotations-id-and-generatedvaluestrategy-generationtype
@NotEmpty, @NotNull, @NotBlank
- https://www.baeldung.com/java-bean-validation-not-null-empty-blank
- https://sanghye.tistory.com/36
그런데 애노테이션을 필드에 붙여주면 별도의 해당 경우에 500에러가 발생하고 추가적인 에러 핸들링을 해주어야 함.
- https://medium.com/sprang/validation-and-exception-handling-with-spring-ba44b3ee0723
This post is licensed under CC BY 4.0 by the author.