Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.servlet.http.HttpServletRequest;
import kr.allcll.backend.admin.AdminRequestValidator;
import kr.allcll.backend.admin.seat.dto.SeatStatusResponse;
import kr.allcll.backend.admin.subject.TargetSubjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down
67 changes: 37 additions & 30 deletions src/main/java/kr/allcll/backend/admin/seat/AdminSeatService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.concurrent.atomic.AtomicLong;
import kr.allcll.backend.admin.seat.dto.ChangeSubjectsResponse;
import kr.allcll.backend.admin.seat.dto.SeatStatusResponse;
import kr.allcll.backend.admin.subject.TargetSubjectStorage;
import kr.allcll.crawler.client.SeatClient;
import kr.allcll.crawler.client.model.SeatResponse;
import kr.allcll.crawler.client.payload.SeatPayload;
Expand Down Expand Up @@ -89,14 +90,48 @@ private void sendPinSubjectRequest(Credential credential) {
if (crawlerSubject == null) {
return;
}
sendExternalRequestWithOutDetect(crawlerSubject, credential);
sendExternalRequest(crawlerSubject, credential);
}

private void sendGeneralSubjectRequest(Credential credential) {
CrawlerSubject crawlerSubject = targetSubjectStorage.getNextGeneralTarget();
sendExternalRequestWithOutDetect(crawlerSubject, credential);
sendExternalRequest(crawlerSubject, credential);
}

private void sendExternalRequest(CrawlerSubject crawlerSubject, Credential credential) {
try {
log.info("[SeatService] [학교 서버] 요청 시도 과목: {}", crawlerSubject);
SeatPayload requestPayload = SeatPayload.from(crawlerSubject);
SeatResponse response = seatClient.execute(credential, requestPayload);
CrawlerSeat renewedCrawlerSeat = createSeat(response, crawlerSubject);
detectDifferenceAndSave(crawlerSubject, renewedCrawlerSeat);
} catch (CrawlerAllcllException e) {
log.error(
"[여석] 외부 API 호출에 실패했습니다. 과목: " + crawlerSubject.getCuriNo() + "-" + crawlerSubject.getClassName());
}
}

private void detectDifferenceAndSave(CrawlerSubject crawlerSubject, CrawlerSeat renewedCrawlerSeat) {
if (changeDetector.isRemainSeatChanged(crawlerSubject, renewedCrawlerSeat)) {
changeDetector.saveChangeToBuffer(crawlerSubject, renewedCrawlerSeat);

synchronized (getSubjectLock(crawlerSubject.getId())) {
seatPersistenceService.saveSeat(renewedCrawlerSeat);
}
}
}

private CrawlerSeat createSeat(SeatResponse response, CrawlerSubject crawlerSubject) {
return response.toSeat(crawlerSubject, LocalDate.now());
}

private Object getSubjectLock(Long subjectId) {
return ("LOCK_" + subjectId).intern();
}

/**
* deprecated : 변경감지로 정책 변경에 따라 해당 메서드를 사용하지 않습니다.
*/
private void sendExternalRequestWithOutDetect(CrawlerSubject crawlerSubject, Credential credential) {
try {
log.info("[SeatService] [학교 서버] 요청 시도 과목: {}", crawlerSubject);
Expand Down Expand Up @@ -127,32 +162,4 @@ private void sendExternalRequestWithOutDetect(CrawlerSubject crawlerSubject, Cre
"[여석] 외부 API 호출에 실패했습니다. 과목: " + crawlerSubject.getCuriNo() + "-" + crawlerSubject.getClassName());
}
}

/**
* 변경감지로 정책 변경 시 해당 메서드로 변경
*/
private void sendExternalRequest(CrawlerSubject crawlerSubject, Credential credential) {
log.info("[SeatService] [학교 서버] 요청 시도 과목: {}", crawlerSubject);
SeatPayload requestPayload = SeatPayload.from(crawlerSubject);
SeatResponse response = seatClient.execute(credential, requestPayload);
CrawlerSeat renewedCrawlerSeat = createSeat(response, crawlerSubject);
detectDifferenceAndSave(crawlerSubject, renewedCrawlerSeat);
}

private void detectDifferenceAndSave(CrawlerSubject crawlerSubject, CrawlerSeat renewedCrawlerSeat) {
if (changeDetector.isRemainSeatChanged(crawlerSubject, renewedCrawlerSeat)) {
changeDetector.saveChangeToBuffer(crawlerSubject, renewedCrawlerSeat);
synchronized (getSubjectLock(crawlerSubject.getId())) {
seatPersistenceService.saveSeat(renewedCrawlerSeat);
}
}
}

private CrawlerSeat createSeat(SeatResponse response, CrawlerSubject crawlerSubject) {
return response.toSeat(crawlerSubject, LocalDate.now());
}

private Object getSubjectLock(Long subjectId) {
return ("LOCK_" + subjectId).intern();
}
}
4 changes: 4 additions & 0 deletions src/main/java/kr/allcll/backend/admin/seat/AllSeatBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
import kr.allcll.crawler.common.properties.SjptProperties;
import org.springframework.stereotype.Component;

/**
* deprecated : 변경감지로 정책 변경에 따라 해당 클래스를 사용하지 않습니다.
*/

@Component
public class AllSeatBuffer {

Expand Down
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

public void saveChangeToBuffer(CrawlerSubject crawlerSubject, CrawlerSeat renewedCrawlerSeat) {
        if (isGeneralSubject(crawlerSubject)) { // 교양 과목인 경우 -> 대시보드
            List<ChangeSubjectsResponse> response = liveBoards.checkStatus(
                crawlerSubject,
                SeatUtils.getRemainSeat(renewedCrawlerSeat)
            );
            if (!response.isEmpty()) { // 대시보드에 변화가 생긴 경우
                changedSubjectBuffer.addAll(response);
            }
        } else {  // 교양 과목이 아닌 경우 -> pin과목
            changedSubjectBuffer.add( 
                ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.UPDATE, SeatUtils.getRemainSeat(
                    renewedCrawlerSeat), LocalDateTime.now()));
        }
    }

changedSubjectBuffer.addAll(response); 에 걸리는 경우는 교양과목인 경우 중, 대시보드에 변화가 생긴 경우입니다.

else에 해당하는 changedSubjectBuffer.add()…. 가 실행되는 경우는 교양 과목이 아닌 경우 즉 pin 과목인 경우를 의도하고 작성된 부분인 것 같은데, 교양 과목인데 pin 과목인 경우에는 어느곳에도 해당하지 않아 여석이 업데이트 되지 않을 것 같습니다.

따라서

public void saveChangeToBuffer(CrawlerSubject crawlerSubject, CrawlerSeat renewedCrawlerSeat) {
        if (isGeneralSubject(crawlerSubject)) { // 교양 과목인 경우 -> 대시보드
            List<ChangeSubjectsResponse> response = liveBoards.checkStatus(
                crawlerSubject,
                SeatUtils.getRemainSeat(renewedCrawlerSeat)
            );
            if (!response.isEmpty()) { // 대시보드에 변화가 생긴 경우
                changedSubjectBuffer.addAll(response);
                return;
            }
        }
			  // 대시보드에 없는 교양 과목 + 교양 과목이 아닌 경우 -> pin과목
        changedSubjectBuffer.add( 
            ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.UPDATE, SeatUtils.getRemainSeat(
                renewedCrawlerSeat), LocalDateTime.now()));
        }
    }

다음과 같이 로직을 변경해야하지 않나 하는 생각이 드는데 어떻게 생각하시나요?

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package kr.allcll.backend.admin.seat;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import kr.allcll.backend.admin.seat.dto.ChangeSubjectsResponse;
Expand All @@ -20,7 +22,9 @@ public class ChangeDetector {
private final SjptProperties sjptProperties;

public boolean isRemainSeatChanged(CrawlerSubject crawlerSubject, CrawlerSeat renewedCrawlerSeat) {
Optional<CrawlerSeat> previousSeat = crawlerSeatRepository.findByCrawlerSubject(crawlerSubject);
LocalDate today = LocalDate.now();

Optional<CrawlerSeat> previousSeat = crawlerSeatRepository.findByCrawlerSubjectAndCreatedDate(crawlerSubject, today);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

db에서 매번 해당 과목의 여석 정보를 가져오는 것 보다, 모든 과목의 여석 정보를 담고있는 캐시에서 가져와서 비교하는 식으로 방법을 바꾸는건 어떨까요?

매번 db를 들락날락하면 병목이 생길 수 있을 것 같은데, 관리포인트가 너무 늘어나지 않는 선에서 방법을 고민해보면 좋을 것 같아요.

if (previousSeat.isEmpty()) {
return true;
}
Expand All @@ -41,7 +45,7 @@ public void saveChangeToBuffer(CrawlerSubject crawlerSubject, CrawlerSeat renewe
} else {
changedSubjectBuffer.add(
ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.UPDATE, SeatUtils.getRemainSeat(
renewedCrawlerSeat)));
renewedCrawlerSeat), LocalDateTime.now()));
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/main/java/kr/allcll/backend/admin/seat/LiveBoards.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kr.allcll.backend.admin.seat;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -27,25 +28,25 @@ public LiveBoards() {
public List<ChangeSubjectsResponse> checkStatus(CrawlerSubject crawlerSubject, Integer remainSeat) {
if (canOnlyIn(crawlerSubject, remainSeat)) {
liveBoardSubjects.put(crawlerSubject, remainSeat);
return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.IN, remainSeat));
return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.IN, remainSeat, LocalDateTime.now()));
}
CrawlerSubject maxCrawlerSubject = findMaxRemainSeatSubject();
Integer maxSubjectRemainSeat = liveBoardSubjects.get(maxCrawlerSubject);
if (canInAndOut(crawlerSubject, maxCrawlerSubject, remainSeat)) {
liveBoardSubjects.put(crawlerSubject, remainSeat);
liveBoardSubjects.remove(maxCrawlerSubject);
return List.of(
ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.IN, remainSeat),
ChangeSubjectsResponse.of(maxCrawlerSubject.getId(), ChangeStatus.OUT, maxSubjectRemainSeat)
ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.IN, remainSeat, LocalDateTime.now()),
ChangeSubjectsResponse.of(maxCrawlerSubject.getId(), ChangeStatus.OUT, maxSubjectRemainSeat, LocalDateTime.now())
);
}
if (canOut(crawlerSubject, remainSeat)) {
liveBoardSubjects.remove(crawlerSubject);
return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.OUT, remainSeat));
return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.OUT, remainSeat, LocalDateTime.now()));
}
Comment on lines 43 to 46
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

out 된 경우에는 전광판의 과목의 개수가 19개가 되니 21번째 전광판 과목이 20번째로 올라와야할 것 같은데 그 로직이 빠져있는 것 같아요!
out이 될 경우 in이 함께 동반되어야 할 것 같습니다. 어차피 몇 초 뒤면 새로운 과목들이 크롤링 되고, 과목이 20개가 채워질 수 도 있지만 새로운 과목이 나타나기 전까지는 19개만 전광판에 보일 것 같은데, liveboard 사이즈를 20보다 조금 크게 22-25 정도로 해두고 20개만 보이게 하는 것은 어떤가요?

Copy link
Copy Markdown
Member

@haeyoon1 haeyoon1 Dec 15, 2025

Choose a reason for hiding this comment

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

또한 checkStatus 메서드에 대해

 public List<ChangeSubjectsResponse> checkStatus(CrawlerSubject crawlerSubject, Integer remainSeat) {
        if (isRemainSeatBecomeEmpty(remainSeat)) { // 크롤링 한 과목의 여석이 0인 경우
            if (canOut(crawlerSubject, remainSeat)) {
                liveBoardSubjects.remove(crawlerSubject);
                return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.OUT, remainSeat,
                    LocalDateTime.now()));
            }
        } else { // 크롤링 한 과목의 여석이 0이 아닌 경우
            if (canOnlyIn(crawlerSubject, remainSeat)) {
                liveBoardSubjects.put(crawlerSubject, remainSeat);
                return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.IN, remainSeat,
                    LocalDateTime.now()));
            }

            CrawlerSubject maxCrawlerSubject = findMaxRemainSeatSubject();
            Integer maxSubjectRemainSeat = liveBoardSubjects.get(maxCrawlerSubject);
            if (canInAndOut(crawlerSubject, maxCrawlerSubject, remainSeat)) {
                liveBoardSubjects.put(crawlerSubject, remainSeat);
                liveBoardSubjects.remove(maxCrawlerSubject);
                return List.of(
                    ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.IN, remainSeat, LocalDateTime.now()),
                    ChangeSubjectsResponse.of(maxCrawlerSubject.getId(), ChangeStatus.OUT, maxSubjectRemainSeat,
                        LocalDateTime.now())
                );
            }

            if (canUpdate(crawlerSubject, remainSeat)) {
                liveBoardSubjects.put(crawlerSubject, remainSeat);
                return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.UPDATE, remainSeat,
                    LocalDateTime.now()));
            }
        }
        return Collections.emptyList();
    }

과 같이 초반에 isRemainSeatBecomeEmpty(크롤링 한 과목의 여석이 0인지) 를 기준으로 분기처리를 해 로직을 수정하는 것은 어떤가요? 여석이 0인 경우에도 불필요하게 많은 로직들을 거치게 되는 것 같아서요!

if (canUpdate(crawlerSubject, remainSeat)) {
liveBoardSubjects.put(crawlerSubject, remainSeat);
return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.UPDATE, remainSeat));
return List.of(ChangeSubjectsResponse.of(crawlerSubject.getId(), ChangeStatus.UPDATE, remainSeat, LocalDateTime.now()));
}
return Collections.emptyList();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package kr.allcll.backend.admin.seat;

import java.time.LocalDate;
import java.util.Optional;
import kr.allcll.crawler.seat.CrawlerSeat;
import kr.allcll.crawler.seat.CrawlerSeatRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -15,6 +17,17 @@ public class SeatPersistenceService {

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveSeat(CrawlerSeat crawlerSeat) {
crawlerSeatRepository.save(crawlerSeat);
LocalDate today = LocalDate.now();

Optional<CrawlerSeat> existingSeatOpt = crawlerSeatRepository.findByCrawlerSubjectAndCreatedDate(
crawlerSeat.getCrawlerSubject(),
today
);
if (existingSeatOpt.isPresent()) {
CrawlerSeat existingCrawlerSeat = existingSeatOpt.get();
existingCrawlerSeat.merge(crawlerSeat);
Comment on lines +26 to +28
Copy link
Copy Markdown
Member

@haeyoon1 haeyoon1 Dec 15, 2025

Choose a reason for hiding this comment

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

기존에는 과목을 크롤링할 때 마다 계속 save만 했던 로직을, 과목 여석 정보를 Update하는 방식으로 변경했는데요,
이는 매번 db에서 특정 과목의 여석 정보를 찾아, 현재 크롤링한 여석과 비교하여 변경 여부를 판단하기때문인 것 같습니다!

하지만 이는 매초 15번 일어나는 로직이기에

  1. db에서 특정 과목의 여석 정보를 찾아

이 경우(1)

  1. 과목 여석 정보를 Update하는 방식

요 경우(2) ==

Optional<CrawlerSeat> existingSeatOpt = crawlerSeatRepository.findByCrawlerSubjectAndCreatedDate(
            crawlerSeat.getCrawlerSubject(),
            today
        );

에도 db에 부하를 너무 많이 주는 로직인 것 같습니다. 따라서 변경이 필요해보여요!

위에 링크 남겨놓은 부분이 db를 거치지 않는 방식으로 수정된다면, 해당 부분은 원래대로 save만 하는 방법으로 수정할 수 있을 것 같은데 어떻게 생각하시나요?

} else {
crawlerSeatRepository.save(crawlerSeat);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kr.allcll.backend.admin.seat;
package kr.allcll.backend.admin.subject;

import java.util.List;
import java.util.Map;
Expand All @@ -8,7 +8,6 @@
import kr.allcll.crawler.common.exception.CrawlerAllcllException;
import kr.allcll.crawler.subject.CrawlerSubject;
import kr.allcll.crawler.subject.CrawlerSubjectRepository;
import kr.allcll.backend.admin.subject.SubjectFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kr.allcll.backend.admin.seat;
package kr.allcll.backend.admin.subject;

import java.util.LinkedList;
import java.util.List;
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/kr/allcll/backend/client/ExternalClient.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package kr.allcll.backend.client;

import java.util.List;
import kr.allcll.backend.admin.seat.AllSeatBuffer;
import kr.allcll.backend.admin.seat.TargetSubjectService;
import kr.allcll.backend.admin.seat.ChangedSubjectBuffer;
import kr.allcll.backend.admin.subject.TargetSubjectService;
import kr.allcll.backend.admin.seat.dto.ChangeSubjectsResponse;
import kr.allcll.backend.admin.seat.dto.PinSubjectUpdateRequest;
import kr.allcll.backend.domain.seat.SeatStorage;
Expand All @@ -25,8 +25,8 @@ public class ExternalClient {

// 외부 의존성
private final TargetSubjectService targetSubjectService;
// private final ChangedSubjectBuffer changedSubjectBuffer;
private final AllSeatBuffer allSeatBuffer;
private final ChangedSubjectBuffer changedSubjectBuffer;
// private final AllSeatBuffer allSeatBuffer;

private final SeatStorage seatStorage;
private final SubjectRepository subjectRepository;
Expand All @@ -36,16 +36,16 @@ public void sendPinSubjects(PinSubjectUpdateRequest request) {
}

public void getAllTargetSubjects() {
List<ChangeSubjectsResponse> allChangedSubject = allSeatBuffer.getAllAndFlush();
List<ChangeSubjectsResponse> allChangedSubject = changedSubjectBuffer.getAllAndFlush();
for (ChangeSubjectsResponse eachChange : allChangedSubject) {
Long subjectId = eachChange.subjectId();
Subject subject = subjectRepository.findById(subjectId, Semester.now())
.orElseThrow(() -> new AllcllException(AllcllErrorCode.SUBJECT_NOT_FOUND, subjectId));
seatStorage.add(
new SeatDto(subject,
eachChange.remainSeat(),
eachChange.createdAt()
// eachChange.changeStatus()
eachChange.createdAt(),
eachChange.changeStatus()
)
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package kr.allcll.backend.domain.seat;

import java.util.List;
import kr.allcll.backend.admin.seat.TargetSubjectService;
import kr.allcll.backend.admin.subject.TargetSubjectService;
import kr.allcll.backend.admin.seat.dto.PinSubjectUpdateRequest;
import kr.allcll.backend.domain.seat.dto.DeprecatedSubjectSummaryResponse;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package kr.allcll.backend.domain.seat;

import java.util.List;
import kr.allcll.backend.admin.seat.TargetSubjectStorage;
import kr.allcll.backend.admin.subject.TargetSubjectStorage;
import kr.allcll.backend.domain.seat.dto.DeprecatedSubjectSummaryResponse;
import kr.allcll.crawler.subject.CrawlerSubject;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public boolean hasActiveSchedule() {

private Runnable getGeneralSeatTask() {
return () -> {
List<SeatDto> generalSeats = seatStorage.getGeneralSeats(QUERY_LIMIT);
List<SeatDto> generalSeats = seatStorage.getGeneralSeats();
sseService.propagate(EVENT_NAME, SeatsResponse.from(generalSeats));
};
}
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/kr/allcll/backend/domain/seat/SeatStorage.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package kr.allcll.backend.domain.seat;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
Expand All @@ -23,13 +25,15 @@ public SeatStorage() {
this.seats = new ConcurrentHashMap<>();
}

public List<SeatDto> getGeneralSeats(int limit) {
public List<SeatDto> getGeneralSeats() {
LocalDateTime now = LocalDateTime.now();

Collection<SeatDto> seatsValue = seats.values();
return seatsValue.stream()
.filter(seat -> seat.getSubject().isNonMajor())
.filter(seat -> seat.getSeatCount() > 0)
.filter(seat ->
Duration.between(seat.getQueryTime(), now).getSeconds() <= LIMIT_QUERY_TIME)
.sorted(Comparator.comparingInt(SeatDto::getSeatCount))
.limit(limit)
.toList();
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/kr/allcll/backend/domain/seat/dto/SeatDto.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kr.allcll.backend.domain.seat.dto;

import java.time.LocalDateTime;
import kr.allcll.backend.admin.seat.ChangeStatus;
import kr.allcll.backend.domain.subject.Subject;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -12,5 +13,5 @@ public class SeatDto {
private Subject subject;
private int seatCount;
private LocalDateTime queryTime;
// private ChangeStatus changeStatus;
private ChangeStatus changeStatus;
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package kr.allcll.backend.domain.seat.dto;

import java.time.LocalDateTime;
import kr.allcll.backend.admin.seat.ChangeStatus;

public record SeatResponse(
Long subjectId,
Integer seatCount,
LocalDateTime queryTime
LocalDateTime queryTime,
ChangeStatus changeStatus
) {

public static SeatResponse from(SeatDto seatDto) {
return new SeatResponse(
seatDto.getSubject().getId(),
seatDto.getSeatCount(),
seatDto.getQueryTime()
seatDto.getQueryTime(),
seatDto.getChangeStatus()
);
}
}
Loading
Loading