Optional<T>제네릭 클래스로 T 타입의 객체를 감싸는 Wrapper 클래스이다. 최종 연산의 결과를 Optional 객체에 담아서 반환하면 반환된 결과가 null인지 체크할 필요 없이(NullPointerException의 위험 없이) 간단하고 안전하게 사용할 수 있다. (자바의 정석 p835)

 

1. Optional 객체를 생성할 때는 of() 대신 ofNullable()을 사용

 

Optional을 사용하는 방법과 주의 사항을 간단하게 정리하면 먼저 Optional 객체를 생성할 때는 of() 또는 ofNullable()을 사용한다.

말 그대로 Nullable은 null을 허용하기 때문에 참조변수가 null의 가능성이 있으면 ofNullable()로 생성하는 것이 좋지만 Optional을 사용하는 것 자체가 null이 올 수 있기 때문에 사용하는 것이라 그냥 ofNullable()로 사용하는 것이 좋다.

 

2. Optional 객체의 값을 가져올 때는 get(), orElse() 대신 orElseGet()을 사용

 

Optional 객체의 값을 꺼낼 때는 get(), orElse(), orElseGet(), orElseThrow()를 사용하면 되는데 먼저 get()은 값이 null일 경우 NoSuchElementException이 발생하기 때문에 사용하지 않는 것이 좋다.

 

orElseThrow()는 예외를 던지는 것이니 그렇다 치고 orElse(), orElseGet()은 뭔가 비슷해서 무슨 차이가 있나 찾아보았다.

 

orElse() vs orElseGet()

  • orElse(): returns the value if present, otherwise returns other
  • orElseGet(): returns the value if present, otherwise invokes other and returns the result of its invocation

설명을 보면 둘다 만약 값이 존재하지 않을때 다른 other를 반환한다고 나와있지만 테스트를 해보면 orElse()의 경우에는 값이 존재할 때도 항상 호출이 된다. null이 아니더라도 계속 객체가 생성되고 있는 것이다. 그리고 메서드가 DB에 저장하는 로직이 있는 경우에는 더 큰 문제가 생길 수 있다. 그래서 성능상 orElseGet()을 사용하는 것이 더 나은 선택이다.

 

JMH로 간단하게 테스트 해봤는데 계속 이전에 테스트하던거랑 같이 실행이 되서 쩔쩔 메다가 OptionsBuilder()로 급하게 처리했는데 Logger도 뭐가 문제인지 제대로 안 되고 가볍게 해보려던 거에 시간을 많이 쓰니 멘탈이 흔들린다. (ㅠㅠ) 얕게 알면 이래서 위험하다. 다시 공부를 해봐야겠다.

 

 

 

JMH(Java Microbenchmark Harness) 사용법

개발을 진행하다가 보면, 성능문제를 해결해야 하는 경우는 매우 많다. 성능 문제를 해결하기 위해서는 우선 성능을 측정해야하며, 성능을 측정하는 방법와 도구는 셀수도 없이 많다. 대부분의

ysjee141.github.io

 

자바 Optional: 5. Optional 톺아보기

Optional 클래스를 의도에 맞게 잘 사용하려면 어떻게 해야할까?

madplay.github.io

 

Java Optional - orElse() vs orElseGet() | Baeldung

Explore the differences between Optional orElse() and OrElseGet() methods.

www.baeldung.com

 

Optional 과 null 에 대해 ⌥␀

런타임에서 발생하는 NullPointException 방어를 위해 만들어둔 로직체크는 코드의 가독성과 유지 보수성이 떨어진다. 어떻게 null…

tecoble.techcourse.co.kr

 

 

SwaggerREST API를 문서화하여 보기 편하게 시각화하고, 테스트할 수 있는 라이브러리로 서버 가동시 @RestController를 읽어서 API 분석을 해서 HTML로 문서화를 하기 때문에 API 문서를 직접 만들어서 수정시마다 일일이 수정하는 번거로움이 없어진다.

 

1. build.gradle

 

springfox-boot-starter로 추가하면 필요한 하위 라이브러리들이 전부 추가된다.

 

 

2. application.properties

 

spring boot 2.6.0 버전 이상인 경우에는 application.properties에서 spring.mvc.pathmatch.matching-strategy=ant_path_matcher을 추가하거나 2.6.0 밑으로 버전을 낮춰야 한다.

 

 

3. SecurityConfig

 

 

 

스프링 시큐리티를 사용하는 경우 해당 경로가 필터에 걸리지 않도록 permit해준다.

 

 

4. SwaggerConfig

 

Swagger 3.0을 사용하는 경우 Swagger2.x에서 사용하던 @EnableSwagger2 애노테이션을 사용하면 안 되고 Docket 생성시 DocumentationType.OAS_30으로 설정을 해야한다.

 

Swagger UI 화면을 보면 Contact와 ApiInfo에 입력한 정보들이 어디에 입력이 되는지 비교가 될 것이다.

 

 

그리고 JWT를 사용하기 때문에 관련 설정들을 해줘야 하는데 securitySchems는 API를 보호하는데 사용되는 보안 체계를 설정하는 것으로 ApiKey(또는 BasicAuth, OAuth)를 등록해서 JWT가 Authorization Header에 포함되도록 한다.

securityContext는 ApiKey로 정의한 JWT의 authorizationScope를 설정해서 SecurityReference를 포함해서 생성을 한다.

 

이제 실행을 하고 http://localhost:8080/swagger-ui/index.html 로 접속을 하면 아래와 같은 메인 화면이 뜬다. 

 

 

Authorize를 누르면 ApiKey로 등록한 정보가 나온다.

 

 

 

 

Spring Boot를 이용한 RESTful Web Services 개발 - 인프런 | 강의

이 강의는 Spring Boot를 이용해서 RESTful Web Services 애플리케이션을 개발하는 과정에 대해 학습하는 강의으로써, REST API 설계에 필요한 기본 지식에 대해 학습할 수 있습니다., - 강의 소개 | 인프런..

www.inflearn.com

 

Springfox Reference Documentation

The Springfox suite of java libraries are all about automating the generation of machine and human readable specifications for JSON APIs written using the spring family of projects. Springfox works by examining an application, once, at runtime to infer API

springfox.github.io

 

[swagger3] 설정 및 authroize button 활성화하기(Bearer 사용)

버전 2보다 좋은 점은 url에 다음과 같이 되어있을때 http://localhost:9001/swagger-ui/index.html#/1.Login/loginUsingPOST 브라우저로 접속하면 해당 api가 바로 펼쳐지면서 이동한다. (아마 그게 전부... 대신..

lemontia.tistory.com

 

Spring Boot Swagger 3.x 적용

1. Swagger 란? Swagger 는 OAS(Open Api Specification)를 위한 프레임워크입니다. 개발자들의 필수 과제인 API 문서화를 쉽게 할 수 있도록 도와주며, 파라미터를 넣어서 실제로 어떤 응답이 오는지 테스트도

bcp0109.tistory.com

 

Spring Boot2.6에서 Springfox3 실행 실패 에러

Intro Kotlin 프로젝트 였지만, Spring Boot 설정과 관련된 내용이기 때문에 java 로 프로젝트를 진행 하시는 경우에도 문제 해결을 하실 수 있습니다. Kotlin 과 스프링 부트를 이용해 API 서버를 만드는

shanepark.tistory.com

 

SpringBoot 2.6 이상 springfox-swagger3.0 적용 시 에러 해결

원인 spring boot 2.6.0부터 요청 경로를 ControllerHandler에 매칭시키기 위한 전략의 기본값이 ant_path_matcher 전략 -> path_pattern_parser 전략으로 변경되었기 때문이다. 해결 방안 2가지 application

velog.io

 

REST API로 간단한 프로젝트를 만들어보고 있었는데 뭔가 만든다고는 하는데 막상 REST API가 뭔지 설명은 못하다가 좋은 영상을 보게 되었다.

 

 

REST API란 REST 아키텍쳐 스타일을 따르는 API로 REST는 서버와 클라이언트의 독립적인 진화를 위해 나오게 되었는데 REST를 구성하는 스타일은 다음과 같다.

 

1. client-server 구조

2. 무상태성(stateless)

3. cache

4. uniform interface

5. layered system

7. code-on-demand (Optional) - 서버에서 코드를 클라이언트로 보내서 실행할 수 있어야 한다. (Js)

 

대부분은 HTTP 특징을 잘 따르면 만족을 하는데 Uniform Interface는 처음 들어보는 용어인데 대부분 지키기가 어렵다고 한다.

 

Uniform Interface

 

1. identification of resources

2. manipulation of resources through representations

3. self-descriptive messages

4. hypermedia as ther engine of application state (HATEOAS)

 

 

1. identification of resources

리소스를 uri로 식별한다는 것으로 처음 Rest API를 공부할 때도 이 부분만 지키려고 했었다. (행위는 HTTP 메소드로 표현)

 

2. manipulation of resources through representations

representation이 조금 이해가 안 되어서 더 찾아보다가 좋은 글을 발견했다. (글을 쓰다 알았는데 위 영상에 나오시는 분이 이 글을 쓰신 분이였다..)

 

 

REST의 representation이란 무엇인가

사실 서버가 보내준 것은 리소스가 아니다. 다음과 같은 HTTP GET 요청을 서버에 보내서 GET Host: example.org Accept: text/plain, text/html; q=0.9 *; q=0.1 Accept-Language: en, ko; q=0.9, *; q=0.1 “hello”라는 메시지를 

blog.npcode.com

 

먼저 HTTP GET 메서드의 정의를 보면 Get 메서드가 타겟 리소스를 위해 현재 선택된 representation을 전송한다고 나와있다. 

The GET method requests transfer of a current selected representation
for the target resource.

 

이는 리소스를 표현하는 representation이 있고, replresentation이 하나 이상일 수 있으며 그 중 하나를 선택한다고 이해할 수 있다.

 

리소스는 HTTP 요청의 대상인데 회원에 대한 리소스를 요청을 했으면 아이디, 이름 등은 현재 회원이라는 리소스를 표현하는 데이터가 된다.

 

representation은 어떤 리소스의 특정 시점의 상태를 반영하고 있는 정보로 아이디가 바뀐다면 해당 리소스의 representation이 바뀌는 것이다.

 

김영한님 HTTP 강의에서 HTTP 표준 RFC7230 부분에도 나와있는데 Representation(표현)은 표현 메타데이터(헤더)와 표현 데이터(메시지 바디)로 구성이 되는데 표현 메타데이터는 표현 데이터를 해석할 수 있는 정보를 제공한다고 보면 된다. (Content-Type, Content_Lenght 등)

리소스에 대한 표현은 여러개가 될 수 있고 그 중 요청에 적합한 'a current selected representation' 을 선택해서 반환하는 것이다.

여기서 말하는 선택은 Request 요청 시 Accept 정보에 따라 서버에서 적절한 representation을 선택하는 것을 말하고 이를 협상(컨텐츠 네고시에이션)이라고 한다. (Accept-Language: ko 헤더를 추가하여 한국어 representation으로 응답을 받거나 Accept: text/html; charset=UTF-8을 추가하여 html로 응답을 받는 등 요청에 따라 응답이 달라진다.)

 

HTTP에서의 representation 개념은 REST에서 온 것인데 REST(Representational State Transfer)에서 State는 웹 애플리케이션의 상태를, Transfer은 상태의 전송을 의미한다.

브라우저가 보여주는 페이지가 바뀌는 것을 웹 애플리케이션의 상태가 변경되었다고 말하는데 표현(representation)을 통해 웹 애플리케이션의 상태(State)가 변경(Transfer)되는 것이다.  

 

이제 메시지 바디에 Representation을 담아서 리소스를 조작(생성, 변경, 삭제 등)한다는 것이 조금 이해가 되었다.

 

 

3. self-descriptive messages

self-descriptive message는 메세지가 스스로 설명 가능해야 한다는 것인데 json으로 응답을 하는 경우 Content-Type을 명시해주고 해당 json 값이 무엇을 의미하는지 json patch 명세를 확인해서 정의하는 등의 정보들을 제공해야한다.

 

 

4. hypermedia as ther engine of application state (HATEOAS)

HATEOAS는 애플리케이션의 상태가 하이퍼링크를 통해 전이가 되어야 한다는 것으로 HTML의 경우 단순하게 <a href=> 태그를 통해 그 다음 상태로 이동할 수 있고 json은 링크라는 것을 추가해서 다음 상태로 전이되도록 할 수 있다.

 

 

REST API는 대부분 Json으로 응답을 하기 때문에 HTML과 비교하면 self-descriptive, HATEOAS를 지키기가 어려운데 영상에 해결책이 나와있지만 확실히 HTML에 비해 까다로운 것 같다. 그래도 REST API가 무엇인지 이런 부분들을 좀 공부하니 내가 뭘 만드는지 조금 정리가 됐다.

 

간단하게 프로젝트에 스프링 HATEOAS를 추가해서 링크를 바디에 추가했는데 링크를 추가할 객체를 EntityModel.of()에 넣어주는데 new 생성자는 더 이상 사용 안하기 때문에 of()를 사용한다.

 

그리고 링크 빌더를 통해 readMemberList() 메서드의 url을 생성해주고 EntityModel에 담아서 보내면 되는데 사용자 리스트를 보여주는 메소드 링크를 연결하였다.

 

 

 

 

모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의

실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...

www.inflearn.com

 

Spring Boot를 이용한 RESTful Web Services 개발 - 인프런 | 강의

이 강의는 Spring Boot를 이용해서 RESTful Web Services 애플리케이션을 개발하는 과정에 대해 학습하는 강의으로써, REST API 설계에 필요한 기본 지식에 대해 학습할 수 있습니다., - 강의 소개 | 인프런..

www.inflearn.com

 

RESTful API 설계 가이드

1. RESTful API 설계 가이드본 문서는 REST API를 좀 더 RESTful 하게 설계하도록 가이드할 목적으로 만들어졌다.따라서, 기본적인 REST API 개념 설명은 아래의 링크로 대신한다. REST API 제대로 알고 사용

sanghaklee.tistory.com

 

면접에서 리다이렉트(Redirect)와 포워드(Forward)의 차이점을 물어보는 질문이 나왔는데 포워드가 정확히 기억이 안 나서 대답을 못 했다.

 

먼저 리다이렉트는 웹 브라우저에게 해당 url로 다시 요청을 하라고 응답을 보낸다. 그래서 새로운 요청이 보내지기 때문에 url도 바뀌게 된다. 리다이렉트는 주로 POST 요청에서 사용을 하는데 HTTP 메서드중 POST는 예외적으로 멱등성이(똑같은 요청에 대해 같은 결과가 나오는 것) 성립하지 않기 때문에 새로고침 같은 반복 요청이 올 경우 리소스 생성이 여러번 일어나면서 문제가 생길 수 있다. 그래서 일반적으로 PRG(Post -> Redirect -> Get) 패턴으로 리다이렉트를 해준다.

 

리다이렉트를 할 때 redirectAttributes에 addAttribute() addFlashAttribute()를 사용하는 이유는 addAttribute의 경우에는 GET 요청 시 쿼리파라미터로 생성된 게시글의 id값을 넘겨주기 위함이고, addFlashAttribute()는 쿼리 파라미터로 넘겨지지 않고 일회성 용도로 사용이 된다. (저장이 완료되었다는 알림창을 띄우는 등)

 

redirect:/ 를 사용하면 UrlBasedViewResolver가 viewName이 "redirect"로 시작하는 것을 인식하고 동작을 한다.

 

 

타임리프의 th:if 문법으로 result의 값이 true일 경우 리다이렉트로 넘어온 것을 확인해서 저장이 완료되었다고 출력하게 하였다.

 

그리고 redirect 과정이 어떻게 되는지 보려고 디버깅을 해보았는데 블로그분처럼 따라가는게 어려워서 나중에 다시 해봐야겠다. 

(invokeForRequest 반환으로 returnValue에 "redirect:/board/read"가 넘어오는 것까지 확인)

 

중요한 것은 리다이렉트와 포워드의 차이점인데 리다이렉트는 302 상태코드로 응답을 하고 Location으로 새로운 GET 요청을 한다.

아래와 같이 응답 리다이렉트를 받고 다시 요청이 오게 된다.

반면 포워드는 온전히 서버측에서 발생하는데 웹 브라우저로 이동하여 새로운 요청이 생기는 것이 아니라 서블릿 컨테이너에서 동일한 요청을 해당 Url로 다시 보내는 것이기 때문에 url은 브라우저에서 바뀌지 않고 처음 요청한 url로 보이게 된다. (Request 객체가 살아있는 것)

사실 리다이렉트만 필요시 사용을 해보고 포워드를 활용해서 다른 url로 넘겨서 사용해본 적이 없어서 어떤 상황에 쓰이는지 잘 모르겠다.

 

 

 

IntelliJ 디버깅 해보기

안녕하세요? 이번 시간엔 intellij의 debugging 을 간단하게 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하는 Github와

jojoldu.tistory.com

 

Spring) 스프링의 "redirect:" 리다이렉트 처리

Intro Spring Framework 를 사용한다면 컨트롤러에서 리턴타입은 String으로 하고 view 이름 대신 "redirect:" 로 시작하는 문자열을 반환 하면 해당 주소로 리다이렉트를 시켜 줍니다. "redirect:" 를 했는데 리

shanepark.tistory.com

 

A Guide To Spring Redirects | Baeldung

A guide to redirect and forward in Spring MVC, with a focus on the code and implementation of each strategy.

www.baeldung.com

 

 

[Web] Forward와 Redirect 차이

웹은 현재 작업중인 페이지에서 다른 페이지로 이동하기 위해 2가지 페이지 전환 기능을 제공합니다. 오늘은 2가지의 페이지 전환 방법의 차이와 사용법에 대해 알아보도록 하겠습니다. 1. Forward

mangkyu.tistory.com

 

+ Recent posts