Skip to content

Conversation

@kimsky247-coder
Copy link

@kimsky247-coder kimsky247-coder commented Nov 6, 2025

안녕하세요 해윤님! 이번 미션도 잘 부탁드립니다

프로젝트 구조

- controller
    * HomeController.java: 메인 페이지의 GET 요청을 받아 home.html 뷰를 반환하는 컨트롤러
    * ReservationController.java: 예약 페이지 뷰 요청과, 예약 목록 데이터 요청을 처리하는 컨트롤러

- domain
    * Reservation.java: 예약의 핵심 데이터를 정의하는 도메인 객체.

고민한 점

2단계 미션을 진행하면서 Reservation 도메인 객체의 날짜와 시간 필드를 LocalDateLocalTime으로 구현했습니다. 이번 미션에서는 LocalDate.now()와 같은 LocalDateLocalTime의 기능을 쓰지 않습니다
그래서 이 필드들을 단순히 String 타입으로 두고, "2023-01-01" 같은 텍스트를 그대로 저장하는 것이 더 간단하지 않을까 고민했습니다. 단순히 값을 저장하는 상황이더라도 LocalDate/LocalTime을 사용하는 것이 좋은 방식이 맞는지 궁금합니다.

Copy link

@haeyoon1 haeyoon1 left a comment

Choose a reason for hiding this comment

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

안녕하세요 하늘님! 이번 미션도 잘 부탁드립니다~

1, 2단계 미션의 범위가 비교적 작아 수정이 필요한 부분이 많이 없었어요!
그래서 이번 리뷰는 동작 원리와 개념을 이해하는 데 초점을 맞춰, 질문 중심으로 작성했습니다.
코드를 고치기보다는, 개념을 함께 알아가는 시간이라고 생각해주시면 좋겠어요😃

qna

2단계 미션을 진행하면서 Reservation 도메인 객체의 날짜와 시간 필드를 LocalDate와 LocalTime으로 구현했습니다. 이번 미션에서는 LocalDate.now()와 같은 LocalDate와 LocalTime의 기능을 쓰지 않습니다
그래서 이 필드들을 단순히 String 타입으로 두고, "2023-01-01" 같은 텍스트를 그대로 저장하는 것이 더 간단하지 않을까 고민했습니다. 단순히 값을 저장하는 상황이더라도 LocalDate/LocalTime을 사용하는 것이 좋은 방식이 맞는지 궁금합니다.

물론 1,2단계 미션에서는 String 타입으로 구현하는 것이 훨씬 간단해요.
하지만 확장성과, 타입이 가진 의미를 고민해본다면 지금처럼 구현하는 것이 의도에 더 맞다고 생각합니다!

LocalDate와 LocalTime을 사용하면

  • 날짜,시간 형식이 자동으로 검증되고
  • 추후 비교, 정렬, 계산 등의 기능을 안전하게 쓸 수 있어요

무엇보다 도메인 관점에서, 날짜와 시간이라는 개념을 의미 있는 타입으로 다루고자하는 의도가 잘 드러나려면, 지금과 같은 타입으로 작성하는 것이 합리적인 선택이라고 생각합니다!

Comment on lines +25 to +28
@GetMapping("/reservation")
public String reservation() {
return "reservation";
}
Copy link

Choose a reason for hiding this comment

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

해당 메서드의 작동 원리를 한번 설명해주시겠어요?!

Copy link
Author

Choose a reason for hiding this comment

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

@GetMapping은 HTTP GET 요청을 특정 자바 메서드와 연결시키는 어노테이션입니다.

  1. 클라이언트가 /reservation URL로 GET요청을 보냅니다.
  2. Spring은@GetMapping("/reservation")어노테이션을 보고, 이 요청을 reservation() 메서드와 연결시킵니다.
  3. reservation() 메서드가 실행되고, 문자열 "reservation"을 반환합니다.
  4. 반환된 문자열 "reservation"을 View의 이름으로 해석합니다.
  5. Spring은 Thymeleaf 템플릿 엔진을 사용해 templates/reservation.html 파일을 찾아 렌더링하고, 완성된 HTML 페이지를 클라이언트에게 응답합니다.

@Controller
public class ReservationController {
private final List<Reservation> reservations = new ArrayList<>();
private AtomicLong index = new AtomicLong(1);
Copy link

Choose a reason for hiding this comment

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

직접 id값을 하드코딩 해 넣지 않고, 자동으로 증가시켜주는 것 이 정말 좋네요!

Copy link
Author

Choose a reason for hiding this comment

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

만약 long을 쓰면, 여러 사용자가 동시에 예약 요청을 보낼 때 ID 번호가 겹치거나 누락되는 오류가 생길 수도 있을 것 같습니다. 감사합니다!

Comment on lines +8 to +11
@GetMapping("/")
public String home() {
return "home";
}
Copy link

Choose a reason for hiding this comment

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

요 메서드의 작동 원리도 한번 설명해주세요!

Copy link
Author

Choose a reason for hiding this comment

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

reservation()메서드와 같은 방식으로 작동합니다

  1. 클라이언트가 "/" URL로 GET 요청을 보냅니다.
  2. Spring은 @GetMapping("/") 어노테이션을 보고, 이 요청을 home() 메서드와 연결시킵니다.
  3. home() 메서드가 실행되고, 문자열 "home"을 반환합니다.
  4. Spring은 이 반환된 문자열 "home"을 View의 이름으로 해석합니다.
  5. Spring은 Thymeleaf 템플릿 엔진을 사용해 templates/home.html 파일을 찾아 렌더링하고, 완성된 HTML 페이지를 클라이언트에게 응답합니다.

Comment on lines +30 to +33
@GetMapping("/reservations")
public ResponseEntity<List<Reservation>> getReservations() {
return ResponseEntity.ok().body(reservations);
}
Copy link

@haeyoon1 haeyoon1 Nov 8, 2025

Choose a reason for hiding this comment

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

  1. @Controller의 주 역할이 뭘까요?
  2. /reservations@GetMapping("/reservation") 와 다르게 JSON만 반환하고있어요! 작성하신 코드에서 응답은 어떤 방식으로 처리될까요?

Copy link
Author

Choose a reason for hiding this comment

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

@Controller의 주 역할

@Controller 어노테이션은 해당 클래스가 웹 애플리케이션의 컨트롤러임을 나타냅니다.
Spring은 클래스 내부를 스캔하여 @GetMapping, @PostMapping 같은 매핑 정보를 찾아내고, 실제 웹 요청이 들어왔을 때 해당 메서드와 연결시켜 줍니다.

getReservations()의 응답 처리 방식

이 메서드는 ResponseEntity<List<Reservation>>를 반환합니다.
ResponseEntity객체를 반환하면 Spring은 뷰 리졸버 대신 메시지 컨버터를 사용합니다.
이 컨버터가 List<Reservation> 자바 객체를 JSON 문자열로 변환합니다.
응답의 Content-Type을 application/json으로 설정하고, 변환된 JSON 데이터를 응답 본문에 담아 전송합니다.

Copy link

@haeyoon1 haeyoon1 Nov 9, 2025

Choose a reason for hiding this comment

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

위에 각 메서드의 작동 흐름을 설명해주셨을 때 작성해주셨듯이, @Controller의 기본적인 역할은 웹 요청을 처리하는 것이에요!
이번 미션에서는 return "reservation"; 를 했을 시 reservation.html파일을 랜더링 해주는 등, view를 랜더링 하는 역할을 주로 수행한 것 같아요.

하지만 해당 메서드의(getReservations) 경우에는 view 템플릿을 반환하는 것 이 아닌 json을 직접 반환하는 메서드예요. 이때 사용할 수 있는 어노테이션이 @RequestBody 입니다!

  1. @ResponseBody 어노테이션에 대해 학습하고, 그 내용을 공유해주세요! (언제 사용되는지, 어떤 역할을 사용하는지 등)
  2. 말씀해주신대로 현재 코드는 ResponseEntity<List<Reservation>>를 반환하여 JSON 형태의 응답을 내려주고 있습니다.
    이때 ResponseEntity는 어떤 역할을 하는지, 그리고 단순히 @ResponseBody로 반환하는 경우와 어떤 차이가 있는지 학습해보세요!
  3. @ResponseBody를 학습하셨다면 @Controller + @ResponseBody를 대체할 수 있는 어노테이션이 있습니다! 어떤 어노테이션인지, 내부적으로 어떻게 동작하는지도 함께 정리해보면 좋을 것 같습니다.

Copy link
Author

Choose a reason for hiding this comment

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

  1. @ResponseBody 어노테이션

@ResponseBody@controller 클래스 내의 메서드가 반환하는 값을 HTTP 응답 본문에 직접 담도록 지시하는 어노테이션입니다. Spring 컨트롤러에서 HTML 페이지가 아닌, JSON 같은 순수 데이터를 반환하고 싶을 때 사용됩니다.
@ResponseBody 어노테이션이 있으면 Spring은 ViewResolver를 작동시키지 않고, HttpMessageConverter를 작동시켜 메서드가 반환하는 객체를 JSON 형식의 문자열로 변환하여 HTTP 응답 본문에 써넣어 클라이언트에게 전송합니다.

  1. ResponseEntity의 역할과 @ResponseBody와 차이
  1. ResponseEntity의 역할
    REsponseEntity는 HTTP 응답을 세밀하게 제어하기 위한 클래스입니다.
    상태 코드, 헤더, 본문을 모두 하나의 객체로 캡슐화하여 반환할 수 있습니다.

  2. ResponseEntity vs @ResponseBody

  • ResponseEntity
    객체 자체에 상태 코드, 헤더 정보, 본문을 모두 담아서 반환하여 상태 코드를 명시적으로 설정하거나, 헤더를 추가하는 것이 매우 유연합니다.
    하지만, @ResponseBody 방식보다 작성할 코드가 조금 더 많습니다.

  • @ResponseBody
    어노테이션 하나만 추가하면 되므로 간단합니다.
    HTTP 헤더를 설정하기가 어렵습니다. HTTP 상태 코드를 설정하려면 별도의 어노테이션을 추가해야 합니다.

  1. @Controller + @ResponseBody

두 어노테이션을 합친 것이 @RestController 입니다. 데이터만 반환하는 컨트롤러를 만들 때 사용됩니다.
클래스에 @RestController를 붙이면, Spring은 @Controller가 붙은 것으로 인지하여 빈으로 등록합니다. 동시에 @ResponseBody가 붙은 것으로 인지하여, 해당 클래스의 모든 메서드에 @ResponseBody의 기능을 일괄 적용합니다. 따라서 메서드마다 @ResponseBody를 붙이지 않아도 자동으로 JSON을 반환하게 됩니다.

Comment on lines +13 to +14
@JsonFormat(pattern = "HH:mm")
private LocalTime time;
Copy link

Choose a reason for hiding this comment

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

응답 JSON의 시간 포맷을 지정해주셨네요!👍

Copy link
Author

Choose a reason for hiding this comment

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

LocalTime을 그대로 반환하면 11:00:00처럼 초 단위까지 나와서, HH:mm 형식으로 포맷팅하기 위해 @JsonFormat을 추가했습니다! 감사합니다


dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
Copy link

Choose a reason for hiding this comment

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

spring-boot-starterspring-boot-starter-web의 차이에대해 설명해주세요!
추가로 implementationtestImplementation에 대해서도 설명 부탁드립니다~

Copy link
Author

Choose a reason for hiding this comment

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

  1. spring-boot-starter vs spring-boot-starter-web

Spring Boot에서는 spring-boot-starter라는 편리한 의존성 조합을 제공합니다.
프로젝트에 설정해야하는 다수의 의존성들을 starter가 이미 포함하고 있기 때문에 starter에 대한 의존성 추가만으로도 프로젝트를 시작하거나 새로운 기능을 추가할 수 있습니다.
하지만 웹 서버가 포함되어 있지 않아 주로 웹 기능이 없는 단순한 콘솔 애플리케이션이나 백그라운드 작업을 만들 때 사용합니다.

spring-boot-starter-webspring-boot-starter의 모든 기능을 포함하고, 추가로 웹 애플리케이션 개발에 필요한 기능을 포함합니다. 내장 Tomcat 웹 서버, Spring MVC 프레임워크, JSON 변환기가 포함되어있어 @Controller를 사용하고 웹 서버를 띄우려면 spring-boot-starter-web이 반드시 필요합니다.

  1. implementation vs testImplementation

implementationtestImplementation은 Gradle이 의존성을 관리하는 범위를 지정합니다
implementation는 src/main/java에 있는 메인 애플리케이션 코드를 컴파일하고 실행할 때 필요한 라이브러리입니다. 이 의존성은 최종적으로 빌드되는 실행 파일에 포함됩니다.

testImplementation는 src/test/java에 있는 테스트 코드를 컴파일하고 실행할 때만 필요한 라이브러리입니다. 테스트를 실행할 때는 사용되지만, 최종 실행 파일에는 포함되지 않습니다.

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