Conversation
daheeParkk
left a comment
There was a problem hiding this comment.
수고하셨습니다! 잘 작성해주셨네요 👍
추가로 패키지를 구분하는 방식이 어떤 것들이 있는지도 찾아보시면 좋을 것 같습니다.
| public void setId(int id) { | ||
| this.id = id; | ||
| } |
There was a problem hiding this comment.
자바시간에 배운 바로는 setter에 예외처리가 없으면 멤버변수를 public으로 두는 것과 다름 없다라고 배웠습니다. 깜박 잊고 int에 대한 예외처리를 안했네요... setter 장단점 더 찾아보도록 하겠습니다!
| if (title == null || content == null) { | ||
| throw new RuntimeException(); | ||
| } |
| public ResponseEntity<Article> createArticle(@RequestBody Article article) { | ||
| int newId = idCounter++; | ||
| article.setId(newId); | ||
| struct.put(newId, article); | ||
| return ResponseEntity.created(URI.create("/article/" + newId)).body(article); | ||
| } |
There was a problem hiding this comment.
domain과 dto가 무엇인지,
요청 또는 응답 시에 어떤 것을 사용했을 때 어떤 장점이 있을지 찾아보시면 좋을 것 같습니다!
There was a problem hiding this comment.
이번 과제가 MVC 패턴이던데 dto가 비슷한 역할인 것 같아 한번 찾아보려합니다!
|
7주차 과제 제출합니다! 잘 작성해보려 노력했는데 잘 한건지 모르겠네요... 그리고 맥북에서 json 한글이 깨지던데 왜 그런지 잘 모르겠습니다. 관련해서 검색도 해보고 직접 해봐도 해결이 안됐습니다... |
dradnats1012
left a comment
There was a problem hiding this comment.
리뷰가 밀려서 죄송합니다...
DTO에 관해서 학습해보시고 적용해보면 좋을 것 같아요
RequestDTO 나 ResponseDTO 처럼 요청과 응답에 따른 DTO를 분리해서 사용하기도 하니 한번 알아보시고 모르는거 있으면 편하게 연락 주세요!
build.gradle
Outdated
| /* | ||
| dependencies { | ||
| implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' | ||
| implementation 'org.springframework.boot:spring-boot-starter-web' | ||
| implementation 'org.springframework.boot:spring-boot-starter-jdbc' | ||
| implementation 'mysql:mysql-connector-java:8.0.33' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
| testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
| } | ||
|
|
||
| */ |
There was a problem hiding this comment.
사용하지 않는 코드는 지워도 될 것 같아요~!
| @Autowired | ||
| public ArticleController(ArticleService service) { | ||
| this.service = service; | ||
| } |
There was a problem hiding this comment.
생성자 주입 방법을 사용하셨네요!
이 방법의 장점은 무엇이고 다른 방법은 또 뭐가 있는지 알아보면 좋을 것 같아요!
There was a problem hiding this comment.
이번 과제가 관련되어있어서 과제를 통해 자세히 조사해보려 합니다!
| } | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<List<Article>> getAll() { |
There was a problem hiding this comment.
Article 을 그대로 반환하기 보다는 ResponseDTO 를 만들어서 반환하면 좋을 것 같아요!
| try { | ||
| Article article = service.getArticleById(id); | ||
| return ResponseEntity.ok(article); | ||
| } | ||
| catch (NoSuchElementException e) { | ||
| return ResponseEntity.notFound().build(); | ||
| } |
There was a problem hiding this comment.
컨트롤러 단에서 예외처리 하는 부분에 대해서 어떻게 생각하시나요?
There was a problem hiding this comment.
전에 질문드린 부분에 대해 생각해봤는데 controller가 아닌 예외가 일어난 곳에서 예외를 일으키는 것이 맞다고 생각이 듭니다!
| } | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<Article> create(@RequestBody Article article) { |
There was a problem hiding this comment.
이 부분도 RequestDTO 를 적용해 줄 수 있을 것 같아요!
새로운 article을 만드는 데에 필요한 값들만 받아와서 매핑해주면 쓸모없는 값들이 전달되지 않을 것 같네요
| a.setId(rs.getInt("id")); | ||
| a.setBoardId(rs.getInt("board_id")); | ||
| a.setAuthor(String.valueOf(rs.getInt("author_id"))); | ||
| a.setTitle(rs.getString("title")); | ||
| a.setContent(rs.getString("content")); | ||
| a.setWriteDateTime(rs.getString("created_date")); | ||
| a.setModifyDateTime(rs.getString("modified_date")); |
There was a problem hiding this comment.
생성자를 통해서 해결하면 어떨까요?
그러면 setter의 사용도 없앨 수 있을 것 같아요
| }); | ||
| } | ||
|
|
||
| public Optional<Article> findById(int id) { |
There was a problem hiding this comment.
Optional은 어떤 역할을 하나요?
There was a problem hiding this comment.
Null값이어도 nullPointException이 발생하지 않도록 도와줍니다! 현재는 id로 찾는 article이 없으면 발생할 수 있기 때문에 Optional해놨습니다!
| @Repository | ||
| public class ArticleRepository { |
There was a problem hiding this comment.
| @Repository | |
| public class ArticleRepository { | |
| @Repository | |
| @Transactional(readOnly = true) | |
| public class ArticleRepository { |
보고서에 남긴 리뷰처럼 이렇게 클래스 단에 달아놓고 사용할 수 있습니다!
There was a problem hiding this comment.
팁 감사합니다 ㅎㅎ 아직 저의 서치에 부족한 부분이 많은 것 같습니다...
| "UPDATE article SET title = ?, content = ? WHERE id = ?", | ||
| a.getTitle(), a.getContent(), id |
| public void delete(int id) { | ||
| jdbc.update("DELETE FROM article WHERE id = ?", id); | ||
| } |
There was a problem hiding this comment.
지우려는 아이디를 가진 데이터가 없으면 어떻게 되나요?
There was a problem hiding this comment.
아무것도 삭제 되지 않고 종료될 것 같습니다. 이 부분은 더 생각해보고 처리해보겠습니다!
|
Long으로 타입을 다 수정하였습니다! 다른 분들 보니 거의 Long으로 하시길래 나름 생각해보니 원시타입보다는 객체 타입 그리고 Long으로 해서 오버플로우 걱정을 더는게 나을것 같아 수정하였습니다. 그외에도 Lombok적용 및 request, response Dto를 적용하였습니다. setter 대신 Bulider패턴을 적용해보려했는데 그러면 수정이 많이 들어갈 것 같아 아직 적용은 못했습니다 ㅠㅠ 아직 다루기는 어렵네요... 계속 시도해보겠습니다! |
| public ResponseEntity<Void> delete(@PathVariable Long id) { | ||
| return service.deleteArticle(id) | ||
| ? ResponseEntity.noContent().build() : ResponseEntity.notFound().build(); |
There was a problem hiding this comment.
데이터가 존재하지 않는 경우 서비스에서 예외를 던지고
예외 핸들러에서 처리해주는 방법은 어떨까요
There was a problem hiding this comment.
그것도 좋은 방법인 것 같습니다. 한번 생각해보겠습니다!
| @OneToMany( | ||
| mappedBy = "board", | ||
| cascade = CascadeType.ALL, | ||
| orphanRemoval = true, | ||
| fetch = FetchType.LAZY | ||
| ) |
| //자식 추가 | ||
| public void addArticle(Article a) { | ||
| articles.add(a); | ||
| a.setBoard(this); |
There was a problem hiding this comment.
그렇게 의미있는 주석처럼 보이진 않아서 삭제해주셔도 좋을 것 같아요 (나머지도)
| if(req.getAuthorId() == null || | ||
| req.getTitle() == null || | ||
| req.getContent() == null ) throw new BadRequestException("누락된 값 존재"); |
There was a problem hiding this comment.
요청/응답에 대한 책임을 가진 계층은 컨트롤러이기 때문에
요청 값에 대한 유효성 검사는 컨트롤러 단으로 빼주셔도 좋다고 생각합니다
There was a problem hiding this comment.
수정에 시간이 오래 걸릴 것 같아서... 나중에 한꺼번에 수정하겠습니다!!
|
로그인 기능 구현을 해보았는데 잘 됐는지 모르겠습니다... 일단 login, logout 과정은 잘 되나, 세부적인 코드 부분에 대해서는 아직도 많은 공부가 필요할 것 같습니다. |
kih1015
left a comment
There was a problem hiding this comment.
리뷰가 늦어져서 죄송합니다🥲
회고 프로젝트 중 궁금한 점 있으시면 언제든 dm 주세요!
build.gradle
Outdated
| annotationProcessor 'org.projectlombok:lombok:1.18.28' | ||
| implementation 'org.springframework.boot:spring-boot-starter-security' |
There was a problem hiding this comment.
오 시큐리티 사용하셨네요
시큐리티 사용에 어려움이 있다면 회고 프로젝트에서 굳이 사용하지 않으셔도 됩니다!
There was a problem hiding this comment.
넵! 다른 분들은 어떻게 하셨는지 한번 봐야겠네요 ㅎㅎ
| @Bean | ||
| public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
| http | ||
| .csrf(AbstractHttpConfigurer::disable) | ||
| .authenticationProvider(authenticationProvider()) | ||
| .authorizeHttpRequests(auth -> auth | ||
| .requestMatchers("/auth/login", "/members").permitAll() | ||
| .anyRequest().authenticated() | ||
| ) |
There was a problem hiding this comment.
로그인 로그아웃 로직은 의존성을 사용하지 않고 한번쯤 직접 구현해보는 것이 도움이 될 것 같아요!
| @Setter | ||
| @Getter | ||
| public class LoginRequestDto { | ||
| private String email; | ||
| private String password; | ||
| } |
There was a problem hiding this comment.
앗... 아무 생각 없이 그냥 넣어버렸네요. 저는 안써도 나중에 쓰일지 모르니 그냥 넣자 주의였는데, 다른 분들 리뷰도 보니 안쓰는 건 넣지 말자더라구요. 아무래도 불러오는 비용이 있어서 그런 것 같습니다. 수정하겠습니다!
| @Service | ||
| @RequiredArgsConstructor | ||
| public class MemberDetailsService implements UserDetailsService { |
There was a problem hiding this comment.
인터페이스 구현하셨네요.
UserDetailsService 인터페이스를 사용한 이유는 무엇이고 장점은 무엇인가요?
There was a problem hiding this comment.
Spring security가 제공하는 기능을 사용할수 있고, 제 마음대로 커스텀을 진행할 수 있다는 점이 장점이라 사용하였습니다!
|
그동안 리뷰해주셔서 정말 감사합니다! 덕분에 많이 배웠습니다. 특히 어떤 식으로 코드를 작성했는지 생각하는 부분을 많이 배웠다고 생각합니다. 또, 보고서에 올려주신 코멘트들도 이론 공부할 때 이런 부분은 왜 why라는 질문을 하지 않았을까 생각해보는 계기가 되었습니다! 회고 프로젝트 끝까지 마무리 잘하여 레귤러 면접까지 나아가보겠습니다. 감사합니다! |
6주차 - model이나 view에 대해서는 일단 생각하지 않고 구현에만 초점을 두어 작성했습니다.
7주차 - jdbc 적용
8주차 - 예외처리 적용
9주차 - jpa 사용
10주차 - 연관관계, 고아객체, springData
11주차 - 로그인 기능 구현(세션 인증 방식)