1. Facts(사실, 객관)
- 회사 어드민 30일 이상 미접속 차단
- 로그인 케이스 리팩토링
- 아샬 static-2 강의 수강
- 품격 swagger 연동
2. Feelings(느낌, 주관)
- 회사 프로젝트에서 개선될 사항이나 필요한 기능을 만들고 있습니다. 보안감사 정책 중, 30일 이상 미접속한 어드민은 접속을 차단해야 한다고 합니다. 따라서 30일 이상 미접속자는 어떻게 처리할까 고민했습니다. DB에는 어드민 테이블에 삭제여부만 있지, 미접속 제한에 대한 칼럼은 없습니다. 대리님은 그렇다고 휴면테이블에 넣을거까지는 없다고 하셨습니다. 따라서 최근 접속일을 확인하여 30일 이상의 경우 로그인 예외처리하는 로직을 추가했습니다. 기존에 아이디 혹은 비밀번호 틀릴 시, 접속 ip권한이 없을 시, 계정이 삭제됐을 시 등등 예외 경우에 하나 추가한 것입니다.
- 기존 프로젝트에서 이런 예외 경우를 일종의 상태코드로 관리하고 있었습니다. 또한 예외 경우를 알기 위해 정수를 이용해서 케이스를 구분하고 있었습니다. 이 방식이 좋은 방식이 아니라고 생각이 되어 static, enum 등의 분리를 고려했습니다. 그렇게 찾던 중, 아샬님의 static 강의를 보게 되었고, 궁극적으로 객체지향코드를 짜기 위해서 enum도 아니고 class로 각 경우를 분리해야 함을 깨달았습니다. 따라서 각 예외의 경우 처리를 위한 각각의 class를 생성했습니다
- 품격에서 swagger를 추가했습니다. 프런트 분들에게 API를 제공하기 위해서입니다. Spring Docs의 경우 하나씩 직접 API를 작성해주어야 했던 것으로 기억합니다. 하지만 swagger는 자동적으로 모든 api 정보를 기본적으로 표시해주기 때문에 너무 편리했습니다.
3. Findings (배운 점)
- 객체지향적인 설계를 위해서 "어떻게 원하는 정보들을 가져올까 고민하지 말고 책임을 떠넘겨라" 라는 말이 가장 중요하다고 생각합니다. 즉, 상태코드나 메세지를 대입해서 사용하는 것이 아니라 해당 책임을 가진 클래스 각각들이 해당 정보를 가지고 본인들이 알아서 처리하는 것입니다. 그래서 코드를 다음과 같이 점진적으로 개선했습니다. ( 저는 언제나 처음부터 완벽한 코드를 추구하지 않고 점진적으로 개선하는 것을 선호합니다 )
기존의 코드를 약 10개 이상의 케이스를 if/else로 구분하고 있습니다.
if(retCode == -10) {
model.addAttribute("resultMsg", message.getMessage("login.fail"));
model.addAttribute("resultStatus", "permission");
}
각각의 코드를 static을 활용하여 상수로 대체합니다.
if(retCode == LOGIN_FAIL) {
model.addAttribute("resultMsg", message.getMessage("login.fail"));
model.addAttribute("resultStatus", "permission");
}
하지만 이 상태들을 한데모아 enum으로 분리해보았습니다.
if(retCode == LOGIN_STATUS.LOGIN_FAIL)
...
최종적으로 로그인 실패에 책임을 가지는 class가 직접 값을 가지고 검증하도록 개선했습니다.
new LoginFail(message, model).login(retCode);
LoginFail에 대한 클래스가 상태코드 -10을 가지고 있으며 login함수를 통해서 검증까지 합니다.
public class LoginFail extends LoginStatus {
private MessageUtil message;
public LoginFail(MessageUtil message, Model model) {
super(message, model);
// TODO Auto-generated constructor stub
this.message = message;
}
@Override
protected String status() {
// TODO Auto-generated method stub
return "-10";
}
@Override
protected String message() {
// TODO Auto-generated method stub
return message.getMessage("login.fail");
}
}
해당 클래스를 보면 상태값과 메세지는 본인이 가지고 있습니다. 즉, 결과코드인 retCode를 LoginFail 클래스에 던져주면 여기서 알아서 지지고 복고 검서하고 적용하는 겁니다. 검증은 추상 클래스인 LoingStatus에 해두었습니다.
public abstract class LoginStatus {
private final Model model;
public LoginStatus(MessageUtil message, Model model) {
this.model = model;
}
public void login(String retCode) {
if(this.isSame(retCode)) {
model.addAttribute("resultMsg", this.message());
model.addAttribute("resultStatus", "permission");
}
}
public boolean isSame(String retCode) {
return this.status().equals(retCode);
}
protected abstract String status();
protected abstract String message();
}
추상 클래스인 LoginStatus는 검증로직을 가지고 있습니다. 또한 이를 상속하는 클래스들이 자신만의 상태코드와 메세지를 가지도록 추상 메서드를 정의했습니다. 이를 통해 이제 클래스에 결과코드인 retCode만 던저주면 알아서 검증을 하고 true false 여부에 따라 작동합니다.
4. Affirmation (자기 선언)
- 나는, 새롭게 배운 지식은 직접 코드로 짜서 내것으로 만들고 익히는 사람이다~!
'회고' 카테고리의 다른 글
TIL_210701 (0) | 2021.07.06 |
---|---|
TIL_210630 (0) | 2021.07.01 |
TIL_210629 (0) | 2021.06.29 |
TIL_210617 (0) | 2021.06.17 |
TIL_210616 (0) | 2021.06.17 |