주특기 숙련 3일차 TIL - JWT, 토큰 유효성 검사, 쿠키와 예외

LIHA·2023년 2월 13일
1

항해99

목록 보기
42/54
post-thumbnail

정영호 매니저님 세션 - 숙련주차의 과제에 대해

  • @PostConstruct 는 Spring 서버가 뜰때 실행되는 것

  • @Value 사용하면 application.properties 에 있는 값을 쓸 수 있다. 그래서 반드시 secret key를 써야하는건 아님.

  • 포스트맨에서 넣는 방법은 토큰을 받는 작업이 필요함. 실제 코드에서는 코드를 헤더에 담아주라고 미리 설정해놓을 것.

  • 만들때는 builder, 뜯을때는 parserbuilder. jwt 토큰이 암호처럼 되어 있기 때문에 그걸 풀어줘야 한다.

  • 헤더에 JWT가 발급한 토큰을 같이 담아준다. 그래서 httpservletresponse 추가됨.

  • 토큰을 만드는것과 뜯는건 본인이 원하는 데이터를 담아서 만들도록 구현할 수 있다.
    -> 예제에서는 username을 받아서 만들었지만, 내가 email을 받길 원한다면 email을 받아서 JWT에 넣고 만들수도 있다.
    -> 그리고 예제에서는 반환타입이 void였지만 String으로 선언할 경우 바로 그 값을 문자열로 받아 다른데서 쓸수도 있음.

  • 번번이 토큰검사 하는것 때문에 코드가 길고 지저분해지는데, 방법이 없을까요?
    -> 토큰 검사부를 하나의 메서드로 빼도 되고, JWT 유틸 부분을 이용해도 된다.

▶ 이를테면 토큰을 풀고(resolveToken),
▶ 그 풀어낸 토큰 스트링을 validateToken()에 집어넣어서 유효성 검사 하고,
▶ 유효성 검사 됐으면 getUserInfoFromToken(스트링) 형태로 집어넣으면 된다.
▶ 이것의 반환타입을 boolean으로 해서 true면 동작하고 false면 예외처리 하면 된다.


여기서부터는 Lv. 3의 이야기

  • JWT 토큰은 알겠는데 쿠키는 어떻게 해요?
    -> Spring에 쿠키에 대한 코드가 있음. 보안 되는지, http만 쓸건지, 만료일은 언젠지, 경로는 어딘지.
    response.addCookie(cookie);
    -> 꺼내오는거 어렵지 않다. request.getheader("이름") 해주면 된다. JWT든 쿠키든.

  • 반환타입이 무조건 List<PostResponseDto> 인데 에러에 Http코드랑 그런걸 어떻게 보내지? 그런 코드 리턴하려면 ResponseEntity 타입을 return해야 하는데.

나는 Service랑 Controller 바꾸기 싫고 에러처리를 바깥에서 하고 싶다면 -> GlobalExceptionHandler 하나 만들어서 거기서 다 관리하게 하면 된다.

  • EntityNotfoundException 이란걸 선언해줬음.
    -> @RestControllerAdvice를 클래스 위에 걸어주고,
    -> 아래쪽의 각 예외마다 @Exceptionhandler도 사용해줌. (value = 예외이름.class) 라고 써줄 것.
    = 나는 이 이름의 에러 처리할거야 라고 써준 것.

  • IllegalArgumentException을 보통 많이 썼을 것임
    -> 엄밀히는 모든 예외에 다 이걸 써도 되는건 아니다. 나중가면 예외의 종류별로 구분해줄 필요가 있음.

  • NPE는 어떻게 하나요? 얘는 뭔가요? 어디로 분류되나요?
    -> Spring에서는 동일한게 있다면 더 자세한걸 찾게 됨. NPE는 RuntimeException으로 감.
    -> 그래서 보통 ExceptionHandler에 그냥 Exception하고 RuntimeException 두개 정도만 만들어놔도 어지간한 예외는 다 잡아낼수 있다.
    -> 아니면 에러를 Enum으로 만들어놔도 된다. enumset 이라는 식의 패키지 하나 만들어서 Errortype 이라는 식의 이름 선언하고 쓰면 됨.

나는 특정 컨트롤러에만 작동하는 예외 핸들러를 만들고 싶은데?

  • 그러면 내가 만들면 된다!
    -> 내가 만들고싶은 Exception을 새로 만들고 RuntimeException을 상속받으면 -> 그 컨트롤러의 예외는 다 여기로 잡힌다.

김영철 매니저님의 강의(?)

  • 토큰 유효성 검사 메소드 같은 경우 여기저기 쓰이니까 static을 선언해줘도 좋을 것.

  • 변수명을 짓는데 신경을 써야하는 이유 -> 나중에 오타를 내면 컴파일러가 관리해줄 수 있기 때문. Enum처럼 관리할 수 있다.

  • claim은 뭘까? -> JWT의 구성요소임. Payload에 들어있는게 claim임. 안써도 상관없음. 근데 굳이 써주는 이유 뭘까?
    -> JWT 토큰은 claim 부분 자체는 아무나 decode해서 내용물을 볼 수 있다. -> 그래서 원빈멘토님 강의에서 여기에 중요정보 넣지 말라고 함.
    -> JWT 토큰이 의미를 가지는 이유는 expiration 설정과 signature 부분에 있는 암호화 알고리즘 때문임.

  • Base64는 암호화 방식임. 64진수로 바꾼다는거임. '모든 데이터는 serialize 된다' 고 한다. 저 Base64도 그것의 일환임.
    -> signwith는 단방향 암호인데, 어떤 언어를 써도 같은 글자수를 가진다. 그래서 HS256은 단방향 알고리즘이며 256자의 값으로 나온다는 것.
    -> 그런 의미에서 HS512는 512자로 나온다는 것이므로 브루트 포스로 대조할 가능성이 줄어 보안은 조금 더 좋지만, 길이때문에 부하가 증가한다.
    보안쪽은 항상 Trade off임. 보안과 용량이 비례하기 때문. '가벼우면서 보안성도 좋다' 라는건 사실 꿈같은 얘기다. 이렇게 하기 어렵다.

  • JWT도 BEARER 같은거 꼭 안 붙여줘도 되긴 하는데, 일종의 규약임. JWT는 명세도 따로 있음. 이 부분은 사실 붙였다 뗐다 번거롭기만 한데 왜 써주냐? 싶은데, BEARER 방식으로 구워진 토큰이다 라는 표시라고 보면 됨.


  • if문에 조건을 여러개 걸 경우, 항상 맨 앞부터 수행되는걸 알고 있는지?
    -> 그러므로 Null과 Empty를 체크하고 싶으면, Empty부터 해줘야 한다. 큰 영역부터 확인해서 들어가는게 좋다.
    '잘 보이는 쓰레기부터 치우는게 좋다' 는 말을 기억할것.

  • @Transactional에 대해 아는지? 더티체킹?
    Proxy 객체를 쓴다. 빈 객체를 쓰는데, 진짜 객체는 아님.
    불러올때 내용이 다르면 Transactional을 돌면서 return 전에 항상 commit을 진행한다.
    더티랑 프록시랑 비교를 했을때 같지 않으면 바뀐걸로 자동으로 save 되어서 올라간다.
    @Transactional은 AOP임. Proxy 객체는 앞으로 많이 쓸것임. 어떻게 다루는지에 대해서는 공부해보면 좋을 것.

findbyusername으로 repository에서 부른다면 -> Proxy로 부르는게 아니라, 진짜 객체를 부르는데 Proxy에 저장만 하는거임.
영속성 컨텍스트 안에서 진행된다. Hibernate가 함.

Exception도 공통된다면 새로 패키지를 만들어서 따로 빼고 import 해도 좋다. Exception은 사실 다루는 방법이 여러가지임.
나중가면 외부 API 붙이고 Swagger 쓰고 하면서 마땅히 어디다 놓기 애매한 것들이 들어올거임. 그런 공통된 것들을 common으로 만들어 따로 뺀다.

JPA라는 기술이 reflection으로 DDL을 생성함. 그래서 Entity에서는 항상 NAC가 필요함. 그래야 Table을 만들 수 있음.
-> 엥? 리플렉션을 쓰는데 NAC가 왜 필요해요?
-> 변수를 갖다 쓰려면 초기화를 해야하니까 생성자로 초기화 해줘야 하는것

@Column에 대해서 아는가? -> 테이블의 컬럼을 만드는 어노테이션.

String의 기본형태를 아는가? varchar임. 그 varchar의 크기제한을 안하면 기본크기인 255가 선언됨.
varchar(255) -> 6만자가 넘는다? 255는 byte수?
-> 예전에는 255글자였는데 현재는 65535 글자.

  • List는 왜 초기화 했을까? -> List 같은 경우는 초기화 안하면 NPE이 뜨기 때문.

  • List에 ? 쓰는건 뭐에요? - Generic에서 와일드카드 쓰는것.
    -> 와일드카드는 경계 - 상한과 하한을 만들수 있음. 모든 클래스의 조상은 Object니까 Object가 상한.
    -> 그래서 Object를 쓰면 모든걸 다 상속 허용 하겠다는 것임. 그런데 와일드카드를 쓰면 그 상속 범위에 제한을 걸 수 있다.

  • ResponseDTO에서 Getter를 쓸 일이 있나요?
    -> 대부분의 Response는 우리가 뭔가 응답을 만들어서 보내주기 때문에 데이터를 얻어올 일은 없다.
    -> 그러나, 그럼에도 불구하고 @Getter를 지우면 런타임 에러가 뜬다. 왜?
    -> JSON 타입으로 데이터를 정제해서 보낼때 Getter가 없으면 데이터 정제를 못한다.
    -> Request에는 일단 무조건 Getter가 있어야함. 저쪽에서 가져오는 데이터를 deserialize를 아예 못함.

  • CASCADE를 ALL과 DELETE 중 뭘 쓰는지에 따라 메모리 영향이 있나?
    -> 그건 딱히 없다. 그러나 영속성에 대한 내용이 있기 때문에 주의해야 한다.
    @ManyToOne에 CASCADE가 걸렸을때 위험하므로 조심해야 한다. 원하지 않는 테이블이 삭제되는 경우가 있기 때문.

  • GENERATIONTYPE 옵션은 뭐가 다를까? -> AUTO, IDENTITY 등...

  • DB에는 수정된 시간이 제대로 보이는데, 포스트맨에는 방금 수정된걸로 보여요!
    -> FLUSH 처리를 해보는 것도?

  • FLUSH와 COMMIT은 뭐가 다를까? FLUSH는 실제로 뭔가 날리는건 아니다. 근데 COMMIT은 실제로 뭔가를 날림.
    -> 여기의 FLUSH는 깃헙의 COMMIT, 여기의 COMMIT이 깃헙의 PUSH라고 보면 된다.

여기서 잠깐 - SQL의 명령어 종류에 대해 알고가자

  • DLL? DCL? DML? TCL? -> 전부 SQL에 속하는 것들. 명령어의 세부분류.

  • DDL: Data Definition Language. 데이터 정의 언어. CREATE, ALTER, DROP...
    -> DB구조 혹은 스키마 정의에 사용.
    얘네는 직접 DB 테이블에 영향을 미침. AUTO COMMIT 되므로 주의!

  • DCL: Data Control Language. 데이터 제어 언어. GRANT, REVOKE...
    -> DB에 권한 부여. (GRANT = 권한부여, REVOKE = 철회)
    얘네도 직접 DB 테이블에 영향을 미침. AUTO COMMIT 되니 주의!

  • DML: Data Manipulation Language. 데이터 조작 언어. SELECT, INSERT, UPDATE, DELETE, MERGE, CALL...
    -> DB의 데이터 관리에 사용. 자동으로 커밋되지 않음. 그래서 롤백도 가능!
    DML은 조작하려는 테이블을 일단 메모리 버퍼에 올려서 작업을 하기 때문에, 버퍼에서 처리한 명령어는 COMMIT 명령어를 따로 쳐서 TRANSACTION을 종료시켜야 한다.
    그러나 SQL Server상에서 하는 경우 DML도 AUTO COMMIT이므로 명령어 입력 필요없음!

  • TCL : Transaction Control Language. Transaction 제어 언어. COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION...
    -> 데이터의 보안, 회복, 무결성, 병행 수행제어 등을 정의할때 사용.

profile
갑자기 왜 춤춰?

1개의 댓글

comment-user-thumbnail
2023년 2월 14일

주특기 입문 1일차부터 글을 쭉 봤습니다 🙂 제가 맨 처음에 스프링을 접하고 배우면서 들었던 생각들과 너무 비슷해서 공감 가는 내용이었어요~
지금 공부하시면서 적어 놓으신 내용들을 나중에 다시 돌아보시면서 봤을 때에는 분명히 다른 느낌이 들 것이라는 확신이 드네요. 열심히 앞으로 나아가는 모습을 응원합니다!!

답글 달기