2022-03-11-TIL

Today I Learned

Spring에서 application.yml 환경변수 사용하기

@Valid 애너테이션을 통해서 설정 파일에 지정된 환경변수를 로딩할 수 있다.

  • https://velog.io/@ewan/What-is-Spring-YML-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%ED%8E%B8
  • https://www.baeldung.com/spring-inject-static-field
  • https://rutgo-letsgo.tistory.com/93
  • https://bitlog.tistory.com/70

Facade 패턴

파사드 인터페이스를 가지고 서비스가 그냥 구현하는 형태로 개발한다면 별로 큰 의미가 없는 것 같다. 그저 바이트 코드 용량만 차지할 뿐이다. 문제는 ‘제대로 된 파사드 패턴의 적용을 하였는가?' 이다.

  • https://lalwr.blogspot.com/2016/03/adapter-vs-facade-vs-decorator.html
  • https://corock.tistory.com/374
  • https://kscory.com/dev/design-pattern/facade
  • https://www.ionos.com/digitalguide/websites/web-development/whats-the-facade-pattern/
  • https://springframework.guru/gang-of-four-design-patterns/facade-pattern/
  • https://www.baeldung.com/java-facade-pattern
  • https://dzone.com/articles/the-facade-pattern
  • https://blog.appsignal.com/2020/03/18/facade-pattern-in-rails-for-performance-and-maintainability.html

사내 QnA 구축

사내에서 전사적인 범위에 대해 질문을 올리고 답변을 해줄 수 있는 플랫폼이 없을까? 그래서 찾아보니 아틀라시안에서 이미 툴로서 제공되고 있으며, 그 유명한 스택오버플로우에서도 팀 내 구축 서비스를 제공한다. 하지만 이를 직접 구현해보면 어떨까 생각중이다. QnA와 블로그, 커뮤니티의 기능을 모두 갖춘 플랫폼으로 구현할 생각이다.

  • https://www.atlassian.com/ko/software/confluence/questions
  • https://stackoverflow.co/teams/tour/
  • https://stackoverflow.blog/2021/03/17/stack-overflow-for-teams-is-now-free-forever-for-up-to-50-users/

Stream 요소중에서 특정 필드의 값을 변경

  • https://cornswrold.tistory.com/299
  • http://www.tcpschool.com/java/java_stream_intermediate
  • https://stackoverflow.com/questions/44370676/java-8-peek-vs-map
  • https://syntaxfix.com/question/5345/modifying-objects-within-stream-in-java8-while-iterating
  • https://softwareengineering.stackexchange.com/questions/308977/is-it-an-antipattern-to-use-peek-to-modify-a-stream-element
  • https://www.baeldung.com/java-streams-peek-api
  • https://stackabuse.com/java-8-streams-guide-to-findfirst-and-findany/
  • https://stackify.com/streams-guide-java-8/
  • https://howtodoinjava.com/java/stream/java-streams-by-examples/

Stream.peek() 내부에서 콜렉션 요소의 값을 변경

peek은 원래 조회만을 위한 중간연산을 수행하기 위해서 만들어진 메서드이다. 스트림의 중간연산으로써 디버깅을 하는 등의 용도로 사용된다. 따라서 peek을 통해서 요소의 값을 변경하는 것은 안티패턴이라고 말한다. peek 호출이 내부적으로 최적화 과정을 거쳐서 lazy 로딩이 될 가능성이 있어서 중간연산으로써 값을 변경하는 동작을 하는 것이 권장되지는 않는다고 한다.

List<TrackResponse> content = results.stream()
        .peek(v -> {
            v.setArtistImageUrl(CDN_URL + v.getArtistImageUrl());
            v.setAlbumImageUrl(CDN_URL + v.getAlbumImageUrl());
        }).collect(Collectors.toList());

위의 코드를 peek을 사용하지 않는 방식으로 바꾸려면 여러가지 방법이 있다.

방법1) forEach로 결과연산에서 수행

results.forEach(v -> {
    v.setArtistImageUrl(CDN_URL + v.getArtistImageUrl());
    v.setAlbumImageUrl(CDN_URL + v.getAlbumImageUrl());
});

굳이 list를 리턴할 필요가 없다면, forEach를 사용하여 Consumer에 변경 코드를 넣으면 된다. 단순하게 반복문을 수행하는 것과 같다.

방법2) map을 사용한다.

List<TrackResponse> content = results.stream()
        .map(v -> {
            v.setArtistImageUrl(CDN_URL + v.getArtistImageUrl());
            v.setAlbumImageUrl(CDN_URL + v.getAlbumImageUrl());
            return v;
        }).collect(Collectors.toList());

이렇게 사용하면 peek과 내부동작이 다를바가 없어서 인텔리제이가 peek으로 바꿔도 마찬가지라고 알려준다. 그러면 peek을 쓰면 안되는 이유를 해결하지 못한다. 따라서 새로운 인스턴스를 생성하는 형태로 map을 사용해야한다. (참고링크)

List<TrackResponse> content = results.stream()
        .map(v -> {
            TrackResponse t = new TrackResponse(v); // 새 인스턴스를 생성
            t.setArtistImageUrl(CDN_URL + t.getArtistImageUrl());
            t.setAlbumImageUrl(CDN_URL + t.getAlbumImageUrl());
            return t;
        }).collect(Collectors.toList());

이때 객체를 파라미터로 받는 생성자를 추가해야한다.

public TrackResponse(TrackResponse trackReponse) {
    this(fields...);
}

이를 좀 더 간결하게 바꾸려면 setter를 사용하는 부분을 해당 객체의 정적 팩토리 메서드로 빼낼 수 있다. 그러면 참조를 이용하여 좀 더 간결하게 작성할 수 있다.

List<TrackResponse> content = results.stream()
        .map(TrackResponse::createUrlMapped)
        .collect(Collectors.toList());
public static TrackResponse createUrlMapped(TrackResponse param) {
    TrackResponse trackReponse = new TrackResponse(param);
    trackReponse.setArtistImageUrl(CDN_URL + trackReponse.getArtistImageUrl());
    trackReponse.setAlbumImageUrl(CDN_URL + trackReponse.getAlbumImageUrl());
    return trackReponse;
}
  • https://dzone.com/articles/peeking-inside-java-streams-with-streampeek
  • https://ramees.tistory.com/46
  • https://cornswrold.tistory.com/299
  • https://softwareengineering.stackexchange.com/questions/308977/is-it-an-antipattern-to-use-peek-to-modify-a-stream-element
  • https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek-java.util.function.Consumer
  • https://dev-kani.tistory.com/34
  • https://goodgid.github.io/Java-8-Stream-Debug-Peek/
  • https://www.geeksforgeeks.org/stream-peek-method-in-java-with-examples/
  • https://4comprehension.com/idiomatic-peeking/
  • https://stackoverflow.com/questions/33635717/in-java-streams-is-peek-really-only-for-debugging
  • https://stackoverflow.com/questions/38496455/modify-property-value-of-the-objects-in-list-using-java-8-streams
  • https://touk.pl/blog/2017/08/30/idiomatic-peeking-with-java-stream-api/
  • https://www.codurance.com/publications/2015/05/04/side-effects-and-java-8-streams
  • https://blog.jooq.org/3-reasons-why-you-shouldnt-replace-your-for-loops-by-stream-foreach/
  • https://youtrack.jetbrains.com/issue/IDEA-201111
  • https://quick-adviser.com/when-to-use-peek-vs-map-in-java/
  • https://multifrontgarden.tistory.com/128
  • https://www.jianshu.com/p/4fabc8a7abca
  • https://stackoverflow.com/questions/35377840/how-to-call-setter-in-chain-of-stream
  • https://stackoverflow.com/questions/58505132/java-streams-using-a-setter-inside-map
  • https://stackoverflow.com/questions/33517624/java-8-chaining-constructor-call-and-setter-in-stream-map
  • https://stackoverflow.com/questions/28888281/use-setter-methods-while-iterating-over-collections-using-lambdas
  • https://medium.com/quick-code/java-8-functional-programming-how-i-do-f11239a0aa90
  • https://stackoverflow.com/questions/51648176/map-vs-peek-intellij-suggestions
  • https://stackoverflow.com/questions/42117419/better-way-than-stream-peek
  • https://stackoverflow.com/questions/48110576/how-to-update-each-element-in-a-list-in-java-8-using-stream-api
  • https://stackoverflow.com/questions/38302531/java-8-modify-stream-elements

Stream으로 리팩터링하기

  • https://blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=yjw2288&logNo=221345788426

Java 8 to 17

  • https://reflectoring.io/java-release-notes/