트러블 슈팅
1.로그인 세션은 구현하였으나 로그인을 하지 않아도 일정이 조회된다

로그인을 한것이 맞는지 세션의 정보를 확인후 로직을 수행하게 수정하였다.
2.컨트롤러에 로그인 세션기능을 넣었는데, 서비스클래스에 구현하면 안되는건가? 역할분담의 느낌인지?...

HTTP통신의 영역이라서 컨트롤러에 작성하는것이 맞다고한다
그리고, 검증은 입구서부터 컷 하는게 맞다.->불필요하게 굳이 다음단계 까지 넘어가야할 이유가 없다고 생각한다.
3.회원가입이 되어있지 않은 상황에서 로그인 시도를 할려고 했더니, 500에러가 발생

없는 회원으로 로그인 하는데 500에러가 발생
ResponseStatusException(HttpStatus.UNAUTHORIZED, "이메일 또는 비밀번호가 일치하지 않습니다.")
상태코드를 담아서 에러를 전달

오류 문구를 출력하기 위해서 글로벌 GlobalExceptionHandler를 정의하여 사용
@RestControllerAdvice // 모든 컨트롤러에서 발생하는 예외를 여기서 가로챕니다!
public class GlobalExceptionHandler {
// ResponseStatusException이 발생하면 이 메서드가 실행됩니다.
@ExceptionHandler(ResponseStatusException.class)
public ResponseEntity<Map<String, Object>> handleResponseStatusException(ResponseStatusException ex) {
Map<String, Object> body = new LinkedHashMap<>();
// 1. 상태 코드 (예: 401)
body.put("status", ex.getStatusCode().value());
// 2. 에러 종류 (예: Unauthorized)
body.put("error", ex.getStatusCode().toString());
// 3. 드디어 우리가 넣은 메시지! ("로그인이 필요합니다")
body.put("message", ex.getReason());
return new ResponseEntity<>(body, ex.getStatusCode());
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Map<String, Object>> handleIllegalArgumentException(IllegalArgumentException ex) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("status", HttpStatus.BAD_REQUEST.value()); // 400
body.put("error", "Bad Request");
body.put("message", ex.getMessage()); // IllegalArgumentException은 getMessage()를 씁니다!
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}
}
4. 과제 발제에 주어진 암호화 클래스의 로직의미가 이해되지 않는다
암호화시
return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
BCrypt.withDefaults()-암호화를 할때 기본적인 설정으로 암호화 알고리즘을 기본값으로 셋팅
hashToString()-암호화 결과를 문자열 형태로 뽑아내겠다
BCrypt.MIN_COST-암호화 연산의 강도 ->이수치가 높을수록 해킹이 어렵지만 서버가 암호를 계산하는 시간도 길어진다
=> MIN_COST 가장 빠른 기본속도
rawPassword.toCharArray()-비밀번호 문자열을 문자 배열로 바꾼다.
->메모리 보안상 문자열보다 배열이 더 안전하기 때문이라고 한다
로그인시 서버에 암호화된 패스워드 와 입력된 패스워드 비교시
Crypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
BCrypt.verifyer()-검증기를 꺼내는 작업[준비단계]
verify()-실제로 두값을 비교하는 핵심 동작
rawPassword.toCharArray()-사용자가 지금 보내온 비밀번호
encodedPassword-DB에 저장된 암호화된 계정 비밀번호
BCrypt.Result 타입의 result 변수로 결과값을 저장
5.댓글 생성시 로그인이 되어있어야 하고, 댓글을 작성할 일정아이디가 있어야 하는데, 정상로그인을 했음에도 불구하고 로그인을 하라는 에러가 발생

"USER_ID"를 "loginUser"로 수정하여 해결

왜냐하면 loginController에 loginUser 사용으로 모두 일치되게 수정하여서 해결되었다.


6.수정을해도 생성이랑 수정 시간이 똑같음

문제는.......하.......

CommentEntity
public void updateComment(CommentRequestDto requestDto){
this.commentContent = requestDto.getCommentContent();
this.setLastModifiedDate(LocalDateTime.now());
}
BaseEntity
protected void setLastModifiedDate(LocalDateTime now) {
this.lastModifiedDate = now;
}
이렇게 명시적으로 조치하여

동기화 완료!!
7.GlobalExceptionHandler 해석
public ResponseEntity<Map<String, Object>> handleResponseStatusException(ResponseStatusException ex) {
Map<String, Object> body = new LinkedHashMap<>();
public 접근 제어자
ResponseEntity: HTTP 응답을 단순히 데이터만 보내는 게 아니라, HTTP 상태 코드(200 OK, 404 Not Found 등), 헤더, 본문(Body)을 모두 제어할 수 있게 해준다
Map<String, Object>: 응답 본문에 넣을 데이터 형식입니다. "status": 401, "message": "로그인이 필요합니다" 처럼 '키(Key):값(Value)' 형태로 여러 타입의 정보를 자유롭게 담기 위해 사용
(ResponseStatusException ex): 파라미터: 현재 발생한 에러 객체(ex)를 매개변수로 전달받습니다. 이 객체 안에는 어떤 에러인지(상태 코드)와 왜 발생했는지(메시지) 에 대한 정보가 있다
LinkedHashMap: 일반적인 HashMap과 달리, 데이터를 넣은 순서를 기억
'spring_2기[본캠프] > 과제' 카테고리의 다른 글
| [과제] Spring 스탠다드 과제 1 (0) | 2026.01.13 |
|---|---|
| [과제]일정 관리 앱 2 구현 (0) | 2026.01.12 |
| [과제]일정 관리 앱 만들기 (0) | 2026.01.02 |
| [달리기반 과제] 4회차 과제 (0) | 2025.12.23 |
| [라이브 코딩테스트] (0) | 2025.12.23 |