들어가며

객체지향을 추구하던 Java는 8버전 부터 큰 변화를 시도하였습니다.
Java8 버전에 함수형 패러다임이 추가되었는데, 그 부분에서 가장 큰 역할을 하는 것이 람다와 함수형 인터페이스가 아닐까라고 생각합니다.
이번 포스팅에선 함수형 인터페이스의 선언과 자주 사용하는 인터페이스 몇가지를 소개드릴까 합니다.

다만, 이번 포스팅을 읽기전에 람다와 익명클래스에 관해 간단히 읽어 보시면 좋을거 같습니다!!
JAVACOFFEE :: Java Java8 - 람다 표현식 사용하기 | Lambda | 익명클래스


함수형 인터페이스 선언

함수형 인터페이스란 한개의 추상 메서드로 이루어진 인터페이스를 말합니다.
간단한 예제를 통해 알아보겠습니다.

@FunctionalInterface
public interface FunctionalInterfaceExample {
    void printMsg(String msg);
    //void printName(String name);

    default void defaultMethod() {
        System.out.println("defalut Method");
    }

    static void staticMethod() {
        System.out.println("static Method");
    }
}
  • @ FunctionalInterface를 선언하여 줍니다
  • 추상메서드는 하나만 선언할 수 있습니다
  • 두 개 이상시 컴파일 에러가 발생합니다
  • default, static 메서드는 사용 가능합니다

함수형 인터페이스 사용

생성한 함수형 인터페이스를 사용해보도록 하겠습니다.
먼저 Yunho.class

public class Yunho implements FunctionalInterfaceExample {
    @Override
    public void printMsg(String msg) {
        System.out.println(msg);
    }
}
public class FunctionMain {
    public static void main(String[] args) {
        FunctionalInterfaceExample yunhoInterface = new Yunho();
        yunhoInterface.printMsg("안녕하세요");
        yunhoInterface.defaultMethod();
        FunctionalInterfaceExample.staticMethod();
    }
}

위의 main()을 실행하게 되면
추상메서드, default 메서드, static 메서드가 아래와 같이 실행됩니다.

안녕하세요
defalut Method
static Method

자주 사용하는 함수형 인터페이스

자바에서 기본적으로 제공하는 함수형 인터페이스는 다음과 같은 것들이 있습니다.

Function<T,R> : <T> -> <R>
Consumer<T> : <T> -> Void
Predicate<T> : <T> -> Boolean
Supplier<T> : lazy evaluation

이외에도 다양한 인터페이스를 제공합니다. java.util.function (Java Platform SE 8 )

Predicate

T타입 인자를 받고 결과로 Boolean을 리턴합니다.

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

주요 메서드로 test가 있고, and, or 등의 메서드를 제공합니다

public class PredicateExample {

    public static void main(String[] args) {
        Predicate<Integer> integerPredicate = num ->  num > 10;
        Predicate<Integer> integerPredicate1 = num -> num < 20;

        System.out.println(integerPredicate.test(5));
        System.out.println(integerPredicate.and(integerPredicate1).test(15));
    }
}

and는 Predicate를 파라미터로 받기 때문에 위와 같은 연산을 수행할 수 있습니다.

Consumer

T 타입의 객체를 인자를 받고 내부적으로 값을 연산합니다. 리턴값은 없습니다.

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Accept, andThen 메서드를 제공합니다

public class ConsumerExample {

    public static void main(String[] args) {
        Consumer<List<Integer>> numberConsumer = list -> {
            for (int i = 0; i < list.size(); i++) {
                list.set(i, list.get(i) * list.get(i));
            }
        };
        Consumer<List<Integer>> printConsumer = list -> {
            for (Integer num : list) {
                System.out.println(num);
            }
        };
        List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
        numberConsumer.andThen(printConsumer).accept(numbers);
    }
}

andThen은 Consumer를 Parameter로 받기 때문에 복합 연산을 수행할 수 있습니다.

Supplier

인자를 받지 않고 T 타입을 리턴합니다.

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

get 메서드를 제공합니다

public class Student {

    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

public class SupplierExmaple {

    public static void main(String[] args) {
        Supplier<String> supplier= () -> "hello world";
        System.out.println(supplier.get());

        Supplier<Student> studentSupplier = () -> new Student("황윤호", 20);
        System.out.println(studentSupplier.get());
    }
}

Function

T타입의 인자를 받고, R타입의 객체를 리턴합니다.

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

apply 이외에 compose, andThen 등의 메서드를 제공합니다

public class FunctionExample {

    public static void main(String[] args) {
        Function<Integer, Integer> multiplyFunction = number -> number * number;
        System.out.println(multiplyFunction.apply(10));

        Function<Integer, Integer> minusFunction = number -> number - 10;
        Integer result = multiplyFunction.andThen(minusFunction).apply(10);
        System.out.println(result);
    }
}

마찬가지로 andThen을 이용하면 복합 연산을 이용할 수 있습니다


마치며

이번 포스팅에서는 함수형 인터페이스에 대하여 알아보았는데요, 개인적으로는 Java8에서 꽃은 람다, 스트림, 함수형인터페이스 라고 생각합니다. 그만큼 중요하고, 많이 쓰이고 이해가 어려운 부분이라, 이번 포스팅에서 간단한 이해를 하시고 실제로 많은 연습을 통해 익히시는 걸 권해드립니다 @.@


참고

모던 자바 인 액션 - YES24
Java8 - 함수형 인터페이스(Functional Interface) 이해하기
java-self-study/src/main/java/fi at master · yhmane/java-self-study · GitHub

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

들어가며

인터페이스는 직접 객체화할 수 없기 때문에 구현 클래스를 이용합니다. 다만, 일회성으로 사용하는 구현 객체를 계속 선언하는 것은 옳지 않기에 익명 클래스람다를 이용합니다.


익명 클래스

익명클래스는 이름이 없는 클래스이며 new 와 동시에 부모클래스를 상속받아 내부 메서드를 오버라이딩 하여 사용합니다. 익명 클래스는 코드가 길고 가독성이 떨어져 함수형 프로그래밍 방식에 적합하지 않다는 단점이 있습니다.


람다

람다가 기술적으로 자바8 이전의 자바로 할 수 없었던 일은 제공하는 것은 아닙니다. 다만, 동적 파라미터를 이용할 때 익명 클래스 등 판에 박힌 코드를 구현할 필요가 없다는 장점이 있습니다.

어떠한 장점이 있어 람다를 사용하는지 코드를 통해 알아보겠습니다. 먼저, 람다를 사용하지 않은 코드입니다.

1
2
3
4
5
Comparator<Apple> byWeight = new Comparator<Apple>() {
    public int compare(Apple a1, Apple a2) {
        return a1.getWeight().compareTo(a2.getWeight));
    }
}
cs

다음으로 람다를 사용한 코드입니다.

1
Comparator<Apple> byWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight));
cs

람다는 새로운 기능이 추가되었다기 보다는 기존의 코드를 더 의미있고 간결하게 사용하도록 도와주고 있습니다.


람다의 특징

  • 익명 : 보통의 메서드와 달리 이름이 없으므로 익명이라 표현합니다
  • 함수 : 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부릅니다. 하지만 메서드처럼 파라미터 리스트, 바디, 반환형식, 가능한 예외 리스트들을 포함합니다
  • 전달 : 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있습니다.
  • 간결성 : 익명 클래스처럼 많은 자질구레한 코드를 구현할 필요가 없습니다.

람다 표현식

람다 표현식은 파라미터, 화살표, 바디로 이루어 집니다

1
2
3
                   -화살표- 
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight));
---- 파라미터 ----                    --- 바디 ---
cs
  • 기본 구조
    • 파라미터 리스트 : 사과 2개
    • 화살표 : 람다 파라미터와 람다 바디를 구분한다
    • 람다 바디 : 람다의 반환값에 해당하는 표현식이다
  • 람다는 파라미터와 화살표(->) 바디로 구분합니다
  • 파라미터가 하나일 경우 매개변수를 생략 할 수 있습니다.
  • 바디가 단일 실행문이면 괄호{}를 생략 할 수 있습니다.
  • 바디가 return문으로만 구성되어 있는 경우 괄호{}를 생략 할 수 없습니다.

아래의 예제를 보겠습니다.

1
2
3
4
5
() -> {}
() -> "Raoul"
() -> { return "Mario"; }
(Integer i) -> return "Alan" + i; // {return "Alan" + i;} 가 와야 합니다
(String s) -> {"Iron Man";} // (String s) -> "Iron Man" 또는 (String s) -> { return "Iron Man";}이 와야합니다
cs

다음 포스팅에서는 함수형 인터페이스에 대하여 알아보도록 하겠습니다

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

들어가며



 이전 글에서 [ https://yhmane.tistory.com/121, Java의 Date, Calendar의 단점을 얘기하며 Java8부터 새로 출시된 Time API에 대하여 포스팅하였습니다. 다만, 타임존이 제외된 날짜와 시간에 대해서만 LocalDate, LocalTime, LocalDateTime 언급하였기에, 이번 포스팅에선 ZonedDateTime 클래스에 대하여 포스팅 하도록 하겠습니다.



ZonedDateTime

 

* ZonedDateTime 클래스에 대하여


ZonedDateTime 클래스는 'ZonedDateTime = LocalDateTime + 시차/타임존' 이라고 보시면 쉽게 이해하실 수 있을겁니다. 날짜/시간 이외에 시차, 타임존이 필요할 경우 사용되어 집니다. Public 생성자를 지원하지 않기 때문에, now(), of() 라는 정적 메서드를 이용하여 객체를 생성합니다.


ZonedDateTime nowSeoul = ZonedDateTime.now();
System.out.println("Seoul is " + nowSeoul);

ZonedDateTime nowBerlin = ZonedDateTime.now(ZoneId.of("Europe/Berlin"));
System.out.println("Berlin is " + nowBerlin);

ZonedDateTime now = ZonedDateTime.of(2020, 10, 04, 20, 30, 0, 0, ZoneId.of("Asia/Seoul"));
System.out.println("now is " + now);
Seoul is 2020-10-04T20:49:36.509+09:00[Asia/Seoul]
Berlin is 2020-10-04T13:49:36.510+02:00[Europe/Berlin]
now is 2020-10-04T20:30+09:00[Asia/Seoul]

위와 같이 now(), of() 메서드를 이용하여 객체를 생성할 수 있습니다.


ZonedDateTime now = Year.of(2020).atMonth(10).atDay(04).atTime(20, 30).atZone(ZoneId.of("Asia/Seoul"));

또한, 좀더 명시적인 표현을 위해 위와 같이 표현할 수 있습니다.


타임존테이블 https://en.wikipedia.org/wiki/List_of_tz_database_time_zones


ZoneId, ZoneOffset 


 ZonedDateTime은 시차, 타임존으로 구성됩니다. ZoneId, ZoneOffset는 각각 타임존, 시차를 다룹니다. 타임존은 코드로 'Asia/Seoul', 'Europe/Berlin' 과 같이 표기하고 offset의 경우 UTC 타임을 기준으로 '+09:00', '+02:00' 의 +,- 값으로 표기하여 줍니다. 간단히 사용법을 알아보도록 하겠습니다.


ZoneOffset seoulZoneOffset = ZoneOffset.of("+09:00");
System.out.println("+0900 Time = " + ZonedDateTime.now(seoulZoneOffset));
ZoneId seoulZoneId = ZoneId.of("Asia/Seoul");
System.out.println("Seoul Time = " + ZonedDateTime.now(seoulZoneId));


ZoneOffset berlonZoneOffset = ZoneOffset.of("+02:00");
System.out.println("+0200 Time = " + ZonedDateTime.now(berlonZoneOffset));
ZoneId berlonZoneId = ZoneId.of("Europe/Berlin");
System.out.println("Berlin Time = " + ZonedDateTime.now(berlonZoneId));
+0900 Time = 2020-10-04T21:15:40.845+09:00
Seoul Time = 2020-10-04T21:15:40.948+09:00[Asia/Seoul]
+0200 Time = 2020-10-04T14:15:40.949+02:00
Berlin Time = 2020-10-04T14:15:40.952+02:00[Europe/Berlin]


 서울의 경우 Asia/Seoul의 타임존 코드나 +09:00 Offset 값을 사용해도 무방하지만, 많은 나라들이 매번 동일한 시차를 적용하는 것은 아닙니다. 써머타임의 경우도 있고, 특정년도에 다른 나라의 시차를 적용한 기간도 있기 때문입니다. 따라서  ZonedDateTime 객체를 만들때, ZoneId는 시차를 내부적으로 계산해 처리해주기 때문에, ZoneOffset보다 ZoneId를 이용하는 것이 오류를 방지하는 것에 유리합니다.



출처


https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html

https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

https://www.daleseo.com/java8-zoned-date-time/




블로그 이미지

사용자 yhmane

댓글을 달아 주세요

들어가며


  자바에서는 기본적으로 날짜와 시간 관련된 많은 클래스를 제공하여 줍니다. 아주 오래전부터 제공된 Date Calender 클래스로부터 java8 부터 제공된 LocalDateTime이나 ZonedDateTime까지 많은 시간 관련 클래스를 제공하여 줍니다. 하지만 가장 오래되고 많이 사용하였던 Date/Calender에는 몇가지 문제점이 있습니다. 먼저, 이 둘의 사용법과 문제점을 알아보고 왜 다른 클래스 사용을 권하는지 알아보도록 하겠습니다.





Date, Calendar 클래스

 


public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date)); // 2020-08-30

cal.add(Calendar.MONTH, 1);
date = cal.getTime();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date)); // 2020-09-30
}

오늘날짜와 한달 후에 날짜를 출력 해보았습니다. 이렇게만 보면, 큰 문제는 없어 보입니다. 하지만, 몇가지 혼선을 줄수있는 api를 제공하고, 문제점이 있습니다. 




Date, Calendar 클래스의 문제점



우선, 너무나도 잘 작성되어 있는 글이 있어 출처를 밝힙니다. 아직, 읽어 보시지 않았다면 꼬옥 읽어 보셨으면 하네요.

[출처] https://d2.naver.com/helloworld/645609


  • 불변 객체가 아니다

Date, Calendar 클래스는 set 메서드를 제공합니다. 날짜라는 특수성이 있지만, 불변객체가 아니기에 여러곳에서 공유 되었을때 원치 않는 결과값을 얻는 문제가 발생합니다.


  • int 상수 필드의 남용

cal.add(Calendar.DATE, 1); // 하루를 더함

 하루는 더하는 계산이지만, cal.add(Calendar.DECEMBER, 1) 이라는 값이 와도 컴파일 과정에서 오류를 잡을 수 없습니다.

  • 헷갈리는 월 지정

cal.set(2020, 8, 30); // 2020-09-30

2020-08-30 일을 출력을 기대하였지만, Calendar 월의 상수값은 0부터 시작합니다.

  • 일관성 없는 요일 상수

// 2020-08-30 SUNDAY
cal.get(Calendar.DAY_OF_WEEK); // 1
Date date = cal.getTime();
date.getDay(); // 0

Calendar 일요일 상수값은 1 Date 일요일 상수값은 0 입니다.

  • 오류에 둔감한 timezone id 지정

TimeZone zone = TimeZone.getTimeZone("Asia/Seoul"); // Asia/Seoul
zone.getID();
TimeZone testZone = TimeZone.getTimeZone("Seoul/Asia");
testZone.getID(); // GMT

Time Zone ID에 Seoul/Asia는 존재하지 않지만 오류는 발생하지 않습니다.

  • Java.util.Date의 하위 클래스 문제

eqauls 대칭성 문제가 있는데,  하위 클래스 timestamp에 대하여 객체 a.equal(b) true인데 b.eqauls(a) false가 나오는 문제가 있습니다.




java.time.*



 이해하기 쉽게 설명하자면 java.util.Date(1.0) -> java.util.Calendar(1.1) -> java.time.* (1.8) 이 시간순이라고 보면 됩니다. 초기에 출시된 Date와 Calendar 클래스는 위에서 설명한 문제점들이 있었고, Java 개발자들은 날짜와 시간 클래스를 계산할 때 종종 혼선을 빚기도 하였습니다. 이러한 문제점들은 개선하여 나온 것이 java.time 패키지인데 LocalDate, LocalTime, LocalDateTime이 있습니다. 각각 날짜와 시간을 위해 사용되는 클래스입니다. Local이라는 단어에서 알 수 있듯이 여러 지역대의 Timezone id는 포함하지 않습니다. 



간단한 사용법을 알아보도록 하겠습니다.


  • LocalDate 날짜 클래스

LocalDate curDate = LocalDate.now(); // 2020-08-30
LocalDate targetDate = LocalDate.of(2020, 8, 30); // 2020-08-30

캘린더에서와 다르게 month의 상수값은 우리가 사용하는 달력과 일치합니다.

  • LocalTime 시간 클래스

LocalTime curTime = LocalTime.now(); // 22:09.02.831
LocalTime targetTime = LocalTime.of(22, 8, 30); // 22:08:30 인자를 4개까지 쓸 수 있는데 nano 시간

시간클래스이고, 매우 직관적입니다.

  • LocalDateTime 날짜 + 시간 클래스

LocalDateTime curDateTime = LocalDateTime.now();

LocalDate curDate = LocalDate.now();
LocalTime curTime = LocalTime.now();
LocalDateTime targetDateTime = LocalDateTime.of(curDate, curTime);

System.out.println(curDateTime); // 2020-08-30T22:12:43.946
System.out.println(targetDateTime); // 2020-08-30T22:12:43.946


날짜와 시간을 모두 표현하고 싶으면 LocalDateTime을 이용하시면 됩니다. 

마지막으로, LocalDateTime -> String 변환까지 알아보도록 하겠습니다. 

System.out.println(curDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));



정리


자바는 다음과 같이 시간의 순서로 날짜/시간 클래스를 제공하였습니다. java.util.Date(1.0) -> java.util.Calendar(1.1) -> java.time.* (1.8). Date/Calendar의 문제점을 해결하고자 time 패키지가 나왔고, legacy가 아닌 java8 이상의 프로젝트에서는 가급적 time 패키지 사용을 권합니다. 


LocalDate + LocalTime => LocalDateTime
LocalDateTime + timezone => ZonedDateTime

  • Java8 이상을 사용한다면 time 패키지를 사용
  • 한국에서만 서비스한다면 LocalDateTime으로 처리
  • 글로벌 서비스까지 고려한다면 timezone이 추가된 ZonedDateTime 사용을 고려
 다음 포스팅에선 timezone 관련하여 글을 작성하도록 하겠습니다


출처



[출처] https://d2.naver.com/helloworld/645609

[자바의 정석 - 남궁 성 지음]

[Just 자바 - 황희정님 지음]

블로그 이미지

사용자 yhmane

댓글을 달아 주세요


Stream 이란?




A sequence of elements supporting sequential and parallel aggregate operations. 


순차 또는 병렬의 연산을 지원하는 요소의 시퀀스라고 합니다.



또한 IntStream, DoubleStream 등을 지원하는 java8에 추가된 인터페이스라고 합니다.


[출처] 


https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html






자바를 처음 접한다면 생소할 수도 있지만,


Arrays와 Collection을 처리할 때, Stream과 Lambda를 병행하여 사용한다면


코드의 가독성을 높일 수 있고, 효율을 극대화 시킬 수 있습니다.




1
2
List<ResponseVO> responseVO = objectVO.getResponses().stream().collect(Collectors.toList());
List<Integer> values = responseVO.stream().map(i -> i.getValue()).collect(Collectors.toList());
cs



objectVO안에 있는 ResponseVP List의 value 값들을 구할 때,


위와 같이 stream 연산으로 손쉽게 구할 수 있습니다.







Stream 사용법


Stream은 다음과 같이 세가지 과정을 거칩니다.



  • 스트림 생성 stream()
  • 중개 연산 map() filter()  limit() skip() ....
  • 최종 연산 collect() count() anyMatch() allMatch() noneMatch() ...


위 연산에서는 .() 체인 스코프를 이용해 값을 구할 수 있습니다.



스트림 생성

Stream<Double> stream = Stream.of(4.2, 2.5, 3.1, 1.9);
stream.forEach(System.out::println);


결과


4.2
2.5
3.1
1.9



스트림 중개 연산
IntStream stream1 = IntStream.of(7, 5, 5, 2, 1, 2, 3, 5, 4, 6);
IntStream stream2 = IntStream.of(7, 5, 5, 2, 1, 2, 3, 5, 4, 6);

// 스트림에서 중복된 요소를 제거함.
stream1.distinct().forEach(e -> System.out.print(e + " "));
System.out.println();

// 스트림에서 홀수만을 골라냄.
stream2.filter(n -> n % 2 != 0).forEach(e -> System.out.print(e + " "));



결과

7 5 2 1 3 4 6 

7 5 5 1 3 5 


[출처]

http://tcpschool.com/java/java_stream_intermediate


Stream 사용시 주의 사항



* stream은 재사용 할 수 없습니다.

* 무한 stream 생성에 주의!!

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

aws에 java를 build 하기 위해 메이븐을 설치 해보도록 하겠습니다.

아래 코드와 같이 메이븐을 설치한다면

1
2
3
sudo wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -/etc/yum.repos.d/epel-apache-maven.repo
sudo sed -i s/\$releasever/6//etc/yum.repos.d/epel-apache-maven.repo
sudo yum install -y apache-maven
cs




mvn --version으로 확인을 해보면 java7이 잡히는 것을 확인 할 수 있습니다.

분명히 java7을 지우고 8을 설치하였는데 메이븐을 설치하면 7이 설치 되고 default로 7이 잡히네요.

혹시나 해서 searching 해보니 옵션을 바꿔줘야 한다고 합니다.

1
2
sudo /usr/sbin/alternatives --config java
sudo /usr/sbin/alternatives --config javac
cs



다음과 같이 java8을 기본 실행으로 바꾸고, 기본 컴파일로러 설정하여 줍니다.

이제 mvn --version으로 확인해보겠습니다.


이제 java8이 기본 설정으로 잡히는 것을 확인할 수 있습니다.

다음 포스팅에선 git 설치후 build 하여 서버에 배포해보도록 하겠습니다!!

[출처]

https://docs.aws.amazon.com/ko_kr/neptune/latest/userguide/iam-auth-connect-prerq.html

블로그 이미지

사용자 yhmane

댓글을 달아 주세요