Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Spring JDBC] 이지은 미션 제출합니다. #248

Open
wants to merge 37 commits into
base: jelee2555
Choose a base branch
from

Conversation

jelee2555
Copy link

@jelee2555 jelee2555 commented May 20, 2024

안녕하세요, 리뷰어님!! spring 공부는 처음이다 보니 어느 파일에서 코드를 작성해야 하는 건지 어려움이 많았는데 그래도 최선을 다해 진행해 보았습니다!

<어려웠던 & 궁금했던 점>

  • 다른 분들 코드들을 참고하였을 때, class를 나누어 코드를 작성하였는데 어떤 기준으로 class를 분리하는지
  • class를 나누어 코드를 작성하였을 때, 예외 처리는 어디서 진행해야 하는지

부족한 코드지만 잘 부탁드립니다!

Spring JDBC 미션 commit

@PlusUltraCode
Copy link

안녕하세요 지은님 ^^

요번 리뷰어 이동호입니다.

지은님 께서 궁금하셨던 부분 2가지를 중점적으로 코드 리뷰를 진행했습니다.

혹시 틀렸던 부분이나, 궁금하신 부분들은 댓글로 남겨주시면 피드백 혹은 답변해드리겠습니다.:)

Comment on lines 15 to 42
@Controller
public class ReservationController {
//
// private List<Reservation> reservations = new ArrayList<>();
// private AtomicLong index = new AtomicLong(1);

@Autowired
private JdbcTemplate jdbcTemplate;

@RequestMapping("/reservation")
public String reservation() {
return "reservation";
}

// 예약 목록 조회
@GetMapping("/reservations")
public ResponseEntity<List<Reservation>> read() {
String sql = "SELECT * FROM reservation";
List<Reservation> reservations = jdbcTemplate.query(sql,
(rs, rowNum) -> new Reservation(
rs.getLong("id"),
rs.getString("name"),
rs.getString("date"),
rs.getString("time")
));
return ResponseEntity.ok().body(reservations);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jdbc 를 사용하여 쿼리문을 잘 작정하였고 데이터 베이스와 잘 연동하신게 보입니다.

다만 ReservationController 입장에서 너무 많은 일을 하고 있다는 생각이 듭니다.
그래서 지은님께서 요청해주신 class 나누는 기준에 대해서 말을 해보겠습니다.

MVC 패턴을 아시나요??
https://mundol-colynn.tistory.com/147 혹시 몰라 링크를 첨부할게요

Model View Controller에는 정해진 역할이 있습니다.

이 3가지 모델을 나누는 가장 큰 이유는

각 구성 요소의 역할과 책임을 명확하게 구분 때문입니다.

예를들어 설명하겠습니다.

Controller라는 놈은 주위에 있는 칼을 들어 휘두르는 역할을 합니다.

Model 이라는 놈은 Controller 가 사용할 칼을 직접 제작하는 역할을 합니다.

지은씨가 작성하신 ReservationController 를 보시면 칼을 휘두르는것 뿐만 아니라 칼을 직접 제작하고 있습니다.

쉽게 말해 칼을 휘두른다 == GetMapping 및 PostMapping을 통해 웹과 통신한다.

칼을 직접 제작한다 == jdbc 문법을 이용하여 쿼리문을 작성하여 데이터 베이스와 연동한다.

그래서 jdbc 쿼리 문법을 Controller에서 사용하는게 아닌 따로 클래스를 만들고
Controller 에서는 해당 클래스를 소환해야 된다 생각합니다.

다만 ****처음에 어떤 클래스를 어떤 패키지에 넣으셔야 될지 고민이 많으실거 같습니다.

그래서 저는 코드를 작성하기 전에 먼저 패키지부터 선언하는 습관을 만들었습니다.
model, controller, view 패키지를 만든 뒤 필요할 때마다 해당 패키지 안에 클래스 파일들을 넣었습니다.

위와 같은 큰 틀에서 패키지 이름들이 조금씩 더 추가하는 식으로 코드를 만들면 되겠습니다.

요번 태연님의 코드를 예시로 설명드리겠습니다.

태연님은 domain , exception, presentation, dto으로 총 패키지를 4개 만드셨습니다.

domain 은 model에 해당한다고 보시면 되겠습니다.

exception은 예외를 관리하는 패키지

presentation은 controller의 의미를 담고있습니다. 또한 어느정도 view 패키지의 의미도 나타내고 있습니다.

dto패키지란 멤버 변수들만 선언되어 있고 각 멤버 변수들을 validate를 검증하기 위해 만들어 놓은 패키지라고 생각하면 되겠습니다.

여기서 presentation 패키지에서 ReservationController.java 파일을 보시면 컨트롤러에서 직접 쿼리문을 작성하는 것이 아닌
domain패키지 안에 있는 ReservationRepository라는 파일을 소환하여 사용하고 있습니다.(검만 휘두른다)

이런식으로 패키지를 나누고 각 클래스를 만들 때마다 이 클래스가 이 패키지에 들어가는게 맞는지 고민하면서 만드는 습관이 생기면 좋겠습니다. :)

Copy link
Author

@jelee2555 jelee2555 May 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자세한 답변 감사합니다!!

동호님 리뷰를 보고 공부를 하던 중 궁금한 점이 생겨 질문 납깁니다. 태연님 코드에서 presentation이 controller와 view 패키지의 의미를 둘 다 지니고 있다고 하셨는데 어떤 부분에서 view의 의미를 가지고 있는 건지 궁금합니다!

ReservationController에서 사용자로부터 request를 받고 그에 따른 response를 보내기 때문에 view의 의미를 담고 있는 건가요??

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네, 맞습니다! ReservationController에서 사용자로부터 request를 받고 그에 따른 response를 보내는 부분이 바로 view의 의미를 담고 있습니다. 조금 더 구체적으로 설명드리자면:

##ReservationController에서 View의 의미
ReservationController는 사용자로부터 HTTP 요청을 받고, 그 요청에 따라 데이터를 처리한 후, 적절한 응답을 생성합니다. 이 응답은 보통 HTML, JSON 등의 형태로 사용자에게 반환됩니다. 따라서 ReservationController는 다음과 같은 두 가지 역할을 수행합니다:

  1. Controller 역할: 사용자 요청을 받아 처리하고, 필요한 데이터를 모델에서 가져와서 처리합니다.

  2. View 역할: 처리된 데이터를 사용자에게 반환하는 응답을 생성합니다. 여기서 응답을 생성하는 부분이 뷰의 역할을 일부 포함하고 있다고 볼 수 있습니다.

Comment on lines 10 to 21
public class GlobalExceptionHandler {

@ExceptionHandler
public ResponseEntity handleNoSuchElementException(NoSuchElementException e) {
return ResponseEntity.badRequest().build();
}

@ExceptionHandler
public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) {
return ResponseEntity.badRequest().build();
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class를 나누어 코드를 작성하였을 때, 예외 처리는 어디서 진행해야 하는지

예외에는 2가지가 있습니다. 런타임 에러와 컴파일 에러

컴파일 에러
쉽게 말해 인간이 만들어 놓은 코드를 기계어로 바꾸는 과정에서 생기는 오류라고 생각하면 됩니다.

예를들어 세미클론을 빼먹는 거, public 이라고 선언해야되는데 pubic 라고 선언하는 등등

컴파일 에러는 대부분 intellij에서 빨간줄 혹은 밑줄을 통해 알려줍니다.

런타임 에러
프로그램이 실행중에 생기는 에러입니다.

요번 스프링 과제에서 클라이언트가 이름, 날짜, 시간 등등을 입력을 하고 그 데이터가 데이터 베이스에 저장되는 과정

이 있습니다. 그 데이터는 다시 클라이언트가 보고 있는 홈페이지에서 자신이 입력했던 값들을 보게 됩니다.

이러한 과정들을 런타임이라 하고, 만약 이름, 날짜 등등을 작성안하고 데이터를 넘길시 에러가 발생합니다.

즉 런타임 에러가 발생합니다.

스프링에서는 @ControllerAdvice 라는 어노테이션을 사용하여 런타임 중에 일어나는 에러들을
한꺼번에 관리해주는 역할을 합니다.

지은님 처럼 위와 같이 발생할 에러들을 잘 정리해주셨습니다.

그래서 스프링에서 개발할 경우 어느 클래스든지 예외들을 throw만 하게 되면
그 에러를 @ControllerAdvice 를 사용하여 처리해주시면 되겠습니다. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants