코트카타
37) 행렬의 덧셈
나의 풀이
class Solution {
public int[][] solution(int[][] arr1, int[][] arr2) {
int[][] answer = new int[arr1.length][arr1[0].length];
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[0].length; j++) {
answer[i][j] = arr1[i][j] + arr2[i][j];
}
}
return answer;
}
}
1차원 배열의 크기를 구하는 것은 익숙하나
행렬의 행과 열을 각각 구하는 방법에는 익숙하지 않았었다.
그래서 arr1[0].length에 대해 쉽게 생각하지 못했다.
다른 분들의 풀이
class Solution {
public int[][] solution(int[][] arr1, int[][] arr2) {
int[][] answer = {};
answer = arr1;
for(int i=0; i<arr1.length; i++){
for(int j=0; j<arr1[0].length; j++){
answer[i][j] += arr2[i][j];
}
}
return answer;
}
}
출처:https://school.programmers.co.kr/learn/courses/30/lessons/12950/solution_groups?language=java
사실 answer의 크기를 어떻게 할당해야 하나 고민이었는데
arr1을 할당하신 점이 기발하다고 생각한다.
일정관리 개인과제 해설
- commit 자주 해주세요 -> 날아가지 않도록(ex) 레벨별로 커밋하기)
<필수과제>
Lv1, Lv2
- 필요 없는 dependency 넣지 말기 (ex)thymleaf)
- 패키지 구조부터 잡기
- DTO, Entity -> 무지성으로 @Getter 붙이기
[Schedule] Entity
- 생성자 만들어주기
[Repository]
: 데이터 저장 용도, JPA에서는 DTO 사용하지 않고 Entity 리턴
- 단건 조회 시, null 될 수 있으니 Optional<Schedule> 사용하기
* 변수 수정방법(생활화하기)
shift+F6 한 번에 수정 가능
[Service]
@Service
@RequiredArgsConstructor vs @AllArgsConstructor
: final만 생성자 만들어줌 : final 여부 상관없이 무조건 다 생성자 만들어줌
public ResponseDto save(requestDto dto){
Schedule schedule = new Schedule(dto.getTask()); //DB 저장 전 스케줄
Schedule savedSchedule = repository.save(schedule); //DB 저장 후 스케줄
return new ResponseDto(savedSchedule.getId(),
savedSchedule.getTask(),
savedSchedule.getMember(),
savedSchedule.getCreatedAt(),
savedSchedule.getUpdatedAt())
}
public List<ResponseDto> findAll(requestDto dto){
List<Schedule> schedules = repository.findAll();
List<ResponseDto> dtos = new ArrayList<>();
for ( Schedule schedule : schedules){
ResponseDto dto = new ResponseDto(schedule.getId...);
dtos.add(dto);
}
return dtos;
}
[Controller]
@RestController
@RequiredArgsConstructor
[RequestDto] 요청
@Getter
[ResponseDto]
모두 private final -> 생성자 초기화하기(password 제외)
- DATE 보다는 BETWEEN을 사용하는 것이 더 좋은 답이라고 하셨다.
- DTO는 save, update, 일반 등으로 각각 분리하라고 하셨다.
- 애매하면 POST를 사용하라고도 하셨다.
<도전과제>
Lv 3 연관관계
CONSTRANT : 구속, 제약, 강제
ex) 연인은 제약이 없지만, 부부는 제약이 있다.
- memberRepository도 확인하기 - 검증
- 비밀번호 DB에 그대로 저장하면 안된다 -> 암호화, 인증/인가 필요하다
- 존재하는 멤버인지 진짜 작성자가 수정하는지 확인해야 한다.
Lv 4 페이지네이션
LIMIT ? OFFSET?
Lv 5 예외처리
Global -> Application 커스텀
- common errorsms 사용시, 주의하기
isDeleted - boolean 보다
deletedAt - 날짜 선호 null or 삭제일
Lv 6
@NotBlank(message="")
->Global Handler
Method(Argument Not Valid)
Lv 6까지 다했다고 생각했지만...
내가 다 하지 못한 부분이 있어서... 완벽하지는 않았다.
그래도 도전까지 도전했다는 것에 의의를 두고 싶다.
베이직 세션 6,7회차를 다시 보았다.
7회차에서는 직접 따라 쳐보는데
강의를 멈추고 나서 스스로 생각하고 쳐보고 나서 다시 플레이를 반복했다.
어느 정도 흐름을 알고 있다고 생각했는데 막상 해보려니 막힐 때가 있었다.
사실 지금도 완벽한 느낌은 아니다.
나는 계속 스탠다드반에 있는 것이 맞는지에 대해 고민중이다.
그러나 다른 수준별 학습반 강의도 녹화본은 있어서
결국은 내가 부지런하게 공부하면 된다는 결론을 얻었다.
숙련 Spring 1주차
@ModelAttribute와 @RequestBody 차이점
@ModelAttribute
- 각각의 필드 단위로 바인딩
- 특정 필드 바인딩이 실패하여도, 나머지 필드는 정상적으로 검증 처리 가능
- 특정필드 변환 실패
- 컨트롤러 호출, 나머지 필드 Validation 적용
@RequestBody
- 필드별로 적용되는것이 아니라 객체 단위로 적용된다.
- MessageConverter가 정상적으로 동작하여 Object로 변환하여야 Validation이 동작한다.
- 특정필드 변환 실패
- 컨트롤러 미호출, Validation 미적용
추가내용
- bindingResult.getAllErrors()는 FieldError와 ObjectError 모두 반환한다.
- Spring은 MessageConverter를 이용해 Error 객체들을 변환하여 응답한다.
- RequestDTO 의 경우, 생성, 수정, 삭제, 모두 비슷하게 생겼어도 따로 분리해서 사용하자.
- 작성한 코드는 예시일 뿐 실제로는 API Spec에 맞는 응답을 만들어 클라이언트에 전달 해야한다.
- @ControllerAdvice
이것만은 꼭 기억하기
- Spring Container
- Bean 관리, 의존성 주입
- Spring Bean
- Spring Container가 관리하는 Java 객체
- IOC/DI
- 제어의 역전(IOC)
- 객체 생성과 의존성 관리를 개발자가 아닌 Spring이 담당
- 의존성 주입(DI)
- 객체 간의 의존성을 Spring Container가 주입
- 제어의 역전(IOC)
- 싱글톤 패턴
- Spring Bean은 기본적으로 싱글톤 패턴으로 관리되어 하나의 인스턴스만 생성
- 상태를 가져서는 안된다.
- Spring Bean은 기본적으로 싱글톤 패턴으로 관리되어 하나의 인스턴스만 생성
- Spring Bean 등록
- 자동 등록(권장)
- @ComponentScan(Spring Boot) + @Component(@Controller, @Service, @Repository)
- 수동 등록
- @Configuration + @Bean
- 자동 등록(권장)
- 의존관계 주입
- 생성자 주입
- 생성자 + @Autowired를 통해 의존성을 주입받는다. 불변, 실수 방지
- @RequiredArgsConstructor
- final 필드에 자동으로 생성자를 생성해 주입한다.
- 생성자 주입
- Validation
- BindingResult
- Validation 오류 정보를 담는 객체
- Bean Validation
- Annotation 기반으로 Validation이 가능하도록 만들어진 표준 기술
- BindingResult
숙련 Spring 2주차
인증과 인가
인증(Authentication)
: 사용자가 누구인지 확인하는 과정
ex) 로그인
인가(Authorization)
: 사용자가 어떤 권한을 가지고 있는지 결정하는 과정
반드시 인증이 선행되어야 한다.
ex) 회원만 조회 가능한 게시글, 본인이 작성한 게시글 수정
쿠키(Cookie)
정의 : 웹 브라우저(Client 측)에 저장되는 데이터
용도 : 사용자의 방문 기록, 로그인 상태 유지, 개인 맞춤 설정 등을 저장, HTTP 특성 극복, 광고 정보
특징 : 클라이언트 측에 저장되며, 서버에 요청을 보낼 때마다 포함되어 전송됨.
수명 : 만료 날짜를 설정할 수 있음, 세션 쿠키(브라우저 종료 시 삭제)와 영속 쿠키(지정된 기간 동안 유지)로 구분됨.
세션(Session)
정의 : 사용자와 서버 간의 상태를 유지하기 위한 방법.
용도 : 로그인 정보, 사용자 활동 등을 서버 측에서 관리.
특징 : 서버 측에서 저장되며, 세션 ID가 쿠키에 저장되어 클라이언트와 연결됨.
수명 : 브라우저를 닫거나 일정 시간이 지나면 만료됨.
Session 관리
- 세션은 메모리를 사용한다.
- 세션이 많아지면 서버의 장애가 발생할 수 있다.(메모리 리소스 부족)
- 최소한의 데이터만 저장해야 한다.
- HttpSession은 LastAccessedTime을 기준으로 30분의 생명주기를 가지고 있다.
- 세션의 시간을 너무 오래 유지하여도 메모리 리소스가 부족할 수 있다.
- 적당한 시간 설정이 꼭 필요하다.(Default 30분)
Servlet Filter 정리
- Filter를 사용하려면 Filter Interface를 Implements 하여 구현한다.
- 구현한 Filter를 Bean으로 등록 한다.
- HTTP 요청이 오면 doFilter() 메서드가 호출된다.
- ServletRequest는 기능이 별로 없어서 HttpServletRequest로 다운 캐스팅 해야한다.
- chain.doFilter(request, response)
- (순서를 설정해둔)다음 필터가 있으면 Filter를 호출한다.
- 다음 실행할 필터가 없으면 Servlet을 호출한다.
- 해당 메서드를 호출하지 않으면 다음 단계로 진행되지 않는다.
- 다음 필터나 Servlet을 호출하지 않는다.
- Filter를 등록하는 방법은 여러가지가 있다.
- SpringBoot의 경우 FilterRegistrationBean 을 사용한다.
실습 코드
- WHITE_LIST
- LoginFilter를 적용하지 않을 URL 배열
- isWhiteList()
- WHITE_LIST 을 제외한 모든 경우에 인증 체크를 하도록 만든 메서드
- throw new RuntimeException()
- Login하지 않은 경우 즉, Session이 없는 경우 예외처리
단일 책임 원칙
공통 관심사(로그인 인증)를 Servlet Filter로 해결하였다.
로그인 인증 로직이 바뀌거나 WHITE_LIST 가 추가되어도 LoginFilter만 수정하면 된다.
단일 책임 원칙을 잘 지켰다.
JWT
Spring Security 는 JWT, OAuth와 같은 인증을 표준화된 방식으로 지원한다.
Spring Security를 사용하면 보안 결함의 위험을 줄이고 코드의 일관성을 유지할 수 있다.
Servlet Filter 로도 JWT를 구현할 수 있지만 Spring Security를 사용하면 인증/인가 로직을 더 안전하고 관리하기 쉽게 구성할 수 있다.
이것만은 꼭 기억하기
Cookie
- 웹 브라우저에 저장되는 데이터
- 서버가 클라이언트의 상태를 기억하도록 도와준다.
- 로그인 상태 유지 등에 활용된다.
- 보안에 취약하다.
- 민감한 정보를 저장하지 않아야한다.
- 사용자 임의 수정이 가능하다.
Session
- 서버에서 중요한 정보를 보관하며 로그인을 유지하는 방법
- SessionId를 탈취하여도 민감한 정보가 없다.
- 만료 시간을 설정해서 탈취 문제를 최소화한다.
- HttpSession은 최근 Session을 요청한 시간을 기준으로 만료 시간을 유지한다.
Token
- 인증/인가 과정에서 사용되며 사용자 또는 시스템의 신원과 권한을 증명하고 요청의 유효성을 검증하는 데 사용되는 디지털 문자열
- Session과는 다르게 Client가 데이터(Token)를 저장하고 있다.
- Stateless를 기반으로 하여 확장성이 뛰어나다.
- Mobile과 같이 Cookie를 사용할 수 없는 경우에도 사용할 수 있다.
- Payload는 암호화되지 않는다.
- 만료 시간으로 Token 탈취를 대비한다.
JWT
- 인증에 필요한 정보들을 암호화시킨 JSON 형태의 Token
- Signature를 통해 Token을 안전하게 관리한다.
- JWT의 목적은 정보 보호가 아닌, 위조 방지에 있다.
Filter
- 공통 관심 사항을 하나의 입구에서 처리할 수 있게 만들어준다.
'CODING > 스파르타 내일배움캠프 TIL' 카테고리의 다른 글
일정 관리 앱 Develop 개인과제 관련 트러블슈팅 TIL 모음 (0) | 2025.02.06 |
---|---|
36_직사각형 별찍기_스탠다드 트랜잭션, 인덱스_숙련 Spring 3주차_25.2.5(수) (0) | 2025.02.05 |
34_문자열 다루기 기본_스탠다드 데이터베이스 연관관계 매핑_일정관리 과제 Lv 5 구현완료_25.2.3(월) (0) | 2025.02.03 |
일정관리 개인과제 관련 트러블슈팅 TIL 모음 (0) | 2025.02.03 |
33_부족한 금액 계산하기_스탠다드 DI, IoC_일정관리 과제 Lv 4,5,6 일부 구현완료_25.1.31(금) (0) | 2025.01.31 |