[도착 알리미 SUFY] 5. 알림 정보를 DB에 등록하기
저번 포스팅에 이어서 이제 지하철을 선택하고,
선택한 지하철과 도착 정보를 DB에 저장하는 로직을 구현할 것이다.
저번 포스팅의 Step 3에 이어서, Step 4에서는 나의 목적지 역을 선택하는 단계이다.
사실 Step 4 역시 Step 2처럼 역을 선택하는 단계이기 때문에, Step 2의 코드를 거의 복사해서 동일하게 써주면 된다.
<div id="step4Contents" class="stepContents">
<div class="stepSpan">
<span>Step 4. 목적지 역을 선택해 주세요.</span>
<span style="font-size: 20px">선택하신 열차가 목적지 전역을 출발하면, 카카오톡으로 알림이 전송됩니다.</span>
</div>
<div class="inputContainer">
<input class="inputStn" placeholder="역 이름 검색..." oninput="searchTo(this.value)">
</div>
<div id="stationContainer2" style="width: 80%">
</div>
</div>
///////////////////////////////////////////////////////////////
// Step 4
function searchTo(stnName) {
const stationContainer = document.getElementById('stationContainer2');
stationContainer.innerHTML = "";
let data = {
stnName: stnName,
subwayID: subwayID
}
$.ajax({
type: "POST",
url: "/findStation",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8"
}).done(function (resp) {
resp.forEach(function (station) {
const stationDiv = document.createElement('div');
stationDiv.className = 'stationButton';
stationDiv.innerText = station.stationName;
stationDiv.onclick = function () {
onClickStation2(station);
};
stationContainer.appendChild(stationDiv);
});
}).fail(function (error) {
alert("에러 발생 (콘솔 확인)");
console.log(error);
});
}
function onClickStation2(station) {
document.getElementById('step4Contents').style.display = 'none';
document.getElementById('step5Contents').style.display = 'flex';
toStationID = station.stationId;
toStationName = station.stationName;
checkAlarm();
}
ㅋㅋ 사실상 Step 2와 거의 동일한 로직이다. 함수랑 변수 이름만 조금 바꿔줬을 뿐...
여기서 목적지 역을 선택하면 Step 5로 넘어간다.
Step 5에서는, 내가 선택한 지하철과 역 정보를 가지고 알림을 만들기 전 최종 확인을 하는 단계이다.
목적지 역이나 현재 역, 탑승할 열차와 열차 번호 등은 각 Step에서 변수로 담아 뒀기 때문에 그걸 그냥 불러와주면 된다.
<div id="step5Contents" class="stepContents">
<div class="stepSpan">
<span>Step 5. 설정을 확인해 주세요.</span>
</div>
<div id="checkAlarmContainer">
</div>
<div style="color: white; font-size: 24px; margin-bottom: 10px">
위의 내용에 따라 알림을 설정할까요?
</div>
<div style="width: 100%; display: flex; flex-direction: row; align-items: center; justify-content: center">
<div class="checkOkButton" style="margin-right: 10px" onclick="saveAlarmToDB()">
확인
</div>
<div class="checkCancelButton" onclick="window.location.href = '/index'">
처음으로
</div>
</div>
</div>
///////////////////////////////////////////////////////////////
// Step 5
function checkAlarm() {
const checkAlarmDiv = document.createElement('div');
checkAlarmDiv.className = "checkAlarm";
checkAlarmDiv.innerHTML = "열차 노선: 1호선<br>"
+ "열차 번호: " + subwayNo + "<br>"
+ "현재 역: " + fromStationName + " 역<br>"
+ "목적지 역: " + toStationName + " 역<br>"
+ "전역 출발 시 알람이 전송됩니다."
document.getElementById('checkAlarmContainer').appendChild(checkAlarmDiv);
}
됐다. 이제 내가 탑승할 지하철과 역을 선택하는 단계는 모두 끝났다.
Step 5에서 '확인' 버튼을 누르면 내가 선택한 정보들이 DB에 저장되도록 하면 오늘의 목표는 끝이다.
우선, 아래와 같이 알람 클래스를 만들어 주었다.
< Alarm.java >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
public class Alarm {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
// 알림을 설정한 유저
@ManyToOne
@JoinColumn(name="userId")
@OnDelete(action = OnDeleteAction.CASCADE)
private Account user;
// 탑승한 지하철 정보
private int subwayLine;
private int subwayNo;
// 목적지 역 ID
private String stationID;
// 상행인지 하행인지
private String goingRoute;
}
그리고 이제 DTO를 만들어야 하는데, DTO를 선언하기 전에 jsp에서 어떤 변수들을 정의했었는지 살펴보면 아래와 같다.
- subwayID : 지하철의 노선 ID, 1호선의 경우 1001
- subwayName : 지하철의 노선 이름, 1호선의 경우 "1호선"
- fromStationID : 알림 생성 당시에 위치한 역, 즉 출발 역의 ID
- fromStationName : 알림 생성 당시에 위치한 역의 이름
- subwayNo : 탑승한 지하철의 열차 번호
- toStationId : 목적지 역의 ID
- toStationName : 목적지 역의 이름
- gointRoute : 상행/하행 구분
이 중 알람 클래스에 필요한 변수들은 bold 표시 해놨다.
이 변수들과 현재 접속한 principal 객체를 가지고 dto를 만들면 될 것!
< saveAlarmToDBDTO.java>
@Getter
@RequiredArgsConstructor
public class saveAlarmToDBDTO {
private String username;
private int subwayID;
private int subwayNo;
private String stationID;
private String goingRoute;
}
그리고 이제 이 데이터들을 가지고 ajax로 POST 요청을 보내서 DB에 저장하자!
function saveAlarmToDB() {
// 토큰을 가지고 principal 유저 정보를 가져온다.
$.ajax({
type: "GET",
url: "https://kapi.kakao.com/v2/user/me",
headers: {'Authorization': localStorage.getItem('Authorization'),
'Content-type': "Content-type: application/x-www-form-urlencoded;charset=utf-8"}
}).done(function (resp) {
// 유저 정보를 성공적으로 가져오면, DB에 저장하도록 POST 요청을 보낸다.
let data = {
username: "K" + resp.id,
subwayLine: subwayID,
subwayNo: subwayNo,
stationID: toStationID,
goingRoute: toStationName
}
$.ajax({
type: "POST",
url: "/saveAlarmToDB",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8"
}).done(function (resp) {
alert("알림이 저장되었습니다.");
window.location.href = "/index";
}).fail(function (error) {
alert("에러 발생 (콘솔 확인)");
console.log(error);
})
}).fail(function(error) {
alert("에러 발생 (콘솔 확인)");
console.log(error);
});
}
그리고 해당 uri에 해당하는 컨트롤러는 아래와 같다.
< HomeApiController.java >
@PostMapping("/saveAlarmToDB")
public int saveAlarmToDB(@RequestBody saveAlarmToDBDTO saveAlarmToDBDto) {
homeService.saveAlarmToDB(saveAlarmToDBDto);
return 0;
}
< HomeService.java >
@Transactional
public void saveAlarmToDB(saveAlarmToDBDTO saveAlarmToDBDto) {
String stationID = saveAlarmToDBDto.getStationID();
Station station = stationRepository.findByStationId(stationID);
station.setSettedAlarm(station.getSettedAlarm() + 1); // 해당 역에 설정된 알림의 개수를 1개 증가시킨다
String username = saveAlarmToDBDto.getUsername();
Account user = accountRepository.findByUsername(username);
int subwayID = saveAlarmToDBDto.getSubwayID();
int subwayNo = saveAlarmToDBDto.getSubwayNo();
String gointRoute = saveAlarmToDBDto.getGoingRoute();
Alarm alarm = new Alarm();
alarm.setUser(user);
alarm.setSubwayLine(subwayID);
alarm.setSubwayNo(subwayNo);
alarm.setStationID(stationID);
alarm.setGoingRoute(gointRoute);
alarmRepository.save(alarm);
}
코드를 보면 대충 알 수 있듯이, 클라이언트에게서 dto를 받은 후 정보를 뽑아내서 Alarm 객체를 생성해서 DB에 저장하는 것 뿐이다.
이렇게 하면 내가 탑승할 지하철 정보를 DB에 저장하는 단계까지 완료된다.
이제 다음 단계는, settedAlarm이 1 이상인 목적지 역들을 대상으로 주기적으로 http 요청을 보내서 실시간 지하철들의 위치를 확인 후, 목적지 역에 접근하는 열차가 있다면 db에 저장된 정보들과 비교하여 유저가 설정한 정보와 일치하면 알림을 보내는 로직을 작성하기만 하면 끝일 것 같다.
문제는... 그 많은 DB 객체들을 어떻게 다 검사하느냐인데... 고민 좀 해봐야 할 듯...