Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
### 컨트롤러 (Controller)
- `AdminController`: `@Controller`를 사용하여 웹 페이지를 반환합니다. 사용자가 특정 경로로 접속했을 때, 해당하는 HTML 파일을 렌더링하여 보여줍니다.
- `/`: `home.html` (홈 페이지)
- `/reservation`: `reservation.html` (예약 관리 페이지)
- `ReservationController`: `@RestController`를 사용하여 RESTful API를 제공합니다. HTTP 요청을 받아 `ReservationService`를 호출하고, 그 결과를 JSON 형태로 반환합니다.
- `GET /reservations`: 모든 예약 목록을 조회합니다.
- `POST /reservations`: 새로운 예약을 생성합니다.
- `DELETE /reservations/{id}`: 특정 예약을 삭제합니다.

### 서비스 (Service)
- `ReservationService`: 핵심 비즈니스 로직을 담당합니다.
- 예약 데이터를 `List<Reservation>` 형태로 메모리에 저장하고 관리합니다.
- `AtomicLong`을 사용하여 예약 ID를 순차적으로 생성합니다.
- 주요 메서드:
- `getAllReservations()`: 전체 예약 목록을 반환합니다.
- `addReservation()`: 새로운 예약을 리스트에 추가하고, 생성된 예약 객체를 반환합니다.
- `deleteReservation()`: ID를 기준으로 예약을 찾아 리스트에서 삭제합니다. 존재하지 않는 ID일 경우 `IllegalArgumentException`을 발생시킵니다.

## 📝 API 엔드포인트

| Method | URL | 설명 |
| --- | --- | --- |
| `GET` | `/reservations` | 모든 예약을 조회합니다. |
| `POST` | `/reservations` | 새로운 예약을 생성합니다. |
| `DELETE` | `/reservations/{id}` | 특정 ID의 예약을 삭제합니다. |

### `POST /reservations` 요청 예시

**Request Body:**
```json
{
"name": "woowahan",
"date": "2025-11-13",
"time": "14:00"
}
```

**Response (201 Created):**
```json
{
"id": 1,
"name": "woowahan",
"date": "2025-11-13",
"time": "14:00"
}
```

## 📄 페이지

- **홈**: `http://localhost:8080/`
- **예약 관리**: `http://localhost:8080/reservation`
1 change: 0 additions & 1 deletion src/main/java/roomescape/RoomescapeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ public class RoomescapeApplication {
public static void main(String[] args) {
SpringApplication.run(RoomescapeApplication.class, args);
}

}
3 changes: 1 addition & 2 deletions src/main/java/roomescape/controller/AdminController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ public String home() {
}

@GetMapping("/reservation")
public String reservation()
{
public String reservation() {
return "reservation";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package roomescape.controller; // (또는 roomescape.exception)
package roomescape.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
Expand All @@ -19,8 +19,8 @@ public ResponseEntity<Map<String, String>> handleValidationExceptions(
ex.getBindingResult()
.getFieldErrors()
.forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
errors.put(error.getField(), error.getDefaultMessage())
);
return ResponseEntity.badRequest().body(errors);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public ReservationController(ReservationService service) {

@GetMapping
public List<ReservationResponse> getAllReservations() {
return service.getAllReservations().stream()
return service.getAllReservations().stream()
.map(ReservationResponse::from) // (::from은 ReservationResponse::from과 동일)
.toList();
}
Expand All @@ -41,11 +41,7 @@ public ResponseEntity<ReservationResponse> createReservation(
@Valid @RequestBody ReservationCreateRequest requestDto
) {

Reservation reservationToCreate = new Reservation(
requestDto.name(),
requestDto.date(),
requestDto.time()
);
Reservation reservationToCreate = requestDto.toEntity();

Reservation savedReservation = service.addReservation(reservationToCreate);

Expand Down
22 changes: 17 additions & 5 deletions src/main/java/roomescape/dto/ReservationCreateRequest.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
package roomescape.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import roomescape.model.Reservation;

import java.time.LocalDate;
import java.time.LocalTime;


public record ReservationCreateRequest(

@NotBlank(message = "이름은 필수 항목입니다.")
String name,

@NotBlank(message = "날짜는 필수 항목입니다.")
String date,
@NotNull(message = "날짜는 필수 항목입니다.")
@JsonFormat(pattern = "yyyy-MM-dd")
LocalDate date,

@NotBlank(message = "시간은 필수 항목입니다.")
String time
@NotNull(message = "시간은 필수 항목입니다.")
@JsonFormat(pattern = "HH:mm")
LocalTime time
) {

public Reservation toEntity() {
return new Reservation(name, date, time);
}
}


11 changes: 0 additions & 11 deletions src/main/java/roomescape/dto/ReservationDelete.java

This file was deleted.

31 changes: 17 additions & 14 deletions src/main/java/roomescape/dto/ReservationResponse.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package roomescape.dto;

import roomescape.model.Reservation;

import java.time.LocalDate;
import java.time.LocalTime;

public record ReservationResponse(
long id,
String name,
String date,
String time
)
{
public static ReservationResponse from(Reservation reservation) {
return new ReservationResponse(
reservation.getId(),
reservation.getName(),
reservation.getDate(),
reservation.getTime()
);
}
long id,
String name,
LocalDate date,
LocalTime time
) {
public static ReservationResponse from(Reservation reservation) {
return new ReservationResponse(
reservation.getId(),
reservation.getName(),
reservation.getDate(),
reservation.getTime()
);
}
}

42 changes: 16 additions & 26 deletions src/main/java/roomescape/model/Reservation.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,27 @@
package roomescape.model;

public class Reservation
{
Long id;
String name;
String date;
String time;
import java.time.LocalDate;
import java.time.LocalTime;

public class Reservation {
private Long id;
private String name;
private LocalDate date;
private LocalTime time;

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getDate() {
return date;
}

public String getTime() {
return time;
}

public Reservation(String name, String date, String time) {
public Reservation(Long id, String name, LocalDate date, LocalTime time) {
this.id = id;
this.name = name;
this.date = date;
this.time = time;
}

public Reservation(Long id, String name, String date, String time) {
this(name, date, time);
this.id = id;
public Reservation(String name, LocalDate date, LocalTime time) {
this(null, name, date, time);
}

public Long getId() { return id; }
public String getName() { return name; }
public LocalDate getDate() { return date; }
public LocalTime getTime() { return time; }
}
62 changes: 62 additions & 0 deletions src/main/java/roomescape/repository/ReservationRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package roomescape.repository;

import org.springframework.stereotype.Repository;
import roomescape.model.Reservation;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

@Repository
public class ReservationRepository {

Choose a reason for hiding this comment

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

🔥 Request Change

사용이 안되고 있습니다

Copy link
Author

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.


private final List<Reservation> reservations = new ArrayList<>();
private final AtomicLong counter = new AtomicLong();

public ReservationRepository() {
this.save(new Reservation(
null,
"브라운",
LocalDate.of(2025, 1, 1),
LocalTime.of(12, 0)
));

this.save(new Reservation(
null,
"코니",
LocalDate.of(2025, 1, 2),
LocalTime.of(11, 0)
));
}

public List<Reservation> findAll() {
return new ArrayList<>(reservations);
}

public Reservation save(Reservation reservation) {
Reservation savedReservation = new Reservation(
counter.incrementAndGet(),
reservation.getName(),
reservation.getDate(),
reservation.getTime()
);
reservations.add(savedReservation);
return savedReservation;
}

public boolean existsById(Long id) {
return reservations.stream()
.anyMatch(reservation -> reservation.getId().equals(id));
}

public void deleteById(Long id) {
reservations.removeIf(reservation -> reservation.getId().equals(id));
}

public void clear() {
reservations.clear();
counter.set(0L);
}
}
33 changes: 12 additions & 21 deletions src/main/java/roomescape/service/ReservationService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package roomescape.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import roomescape.model.Reservation;
import roomescape.repository.ReservationRepository;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -10,45 +12,34 @@
@Service
public class ReservationService {

private final List<Reservation> reservations = new ArrayList<>();
private final ReservationRepository reservationRepository;

private final AtomicLong counter = new AtomicLong();

public ReservationService() {
reservations.add(new Reservation(counter.incrementAndGet(), "브라운", "2025-01-01", "10:00"));
reservations.add(new Reservation(counter.incrementAndGet(), "코니", "2025-01-02", "11:00"));
@Autowired
public ReservationService(ReservationRepository reservationRepository) {
this.reservationRepository = reservationRepository;
}

public List<Reservation> getAllReservations() {
return reservations;
return reservationRepository.findAll();
}

public Reservation addReservation(Reservation newReservation) {
Reservation savedReservation = new Reservation(
counter.incrementAndGet(), // 새 ID 발급
newReservation.getName(),
newReservation.getDate(),
newReservation.getTime()
);
reservations.add(savedReservation);
return savedReservation;
}

return reservationRepository.save(newReservation);
}


public void deleteReservation(Long id) {
boolean exists = reservations.stream()
.anyMatch(reservation -> reservation.getId().equals(id));
boolean exists = reservationRepository.existsById(id);

if (!exists) {
throw new IllegalArgumentException("존재하지 않는 예약 ID입니다: " + id);
}

reservations.removeIf(reservation -> reservation.getId().equals(id));
reservationRepository.deleteById(id);
}

public void clear() {
reservations.clear();
counter.set(0L); //테스트를 위한 코드 입니다.
reservationRepository.clear();
}
}