반응형

이 포스트는 google cloud shell 커맨드에서 
제공하는 편집기와 터니널을 이용해 docker image 를 생성하고 google cloud 도커이미지 저장소인

Artifact Registry 에 도커이미지를 저장하는 방식에 대한 튜토리얼입니다.

 

  1. Google Cloud API가 사용 설정됩니다.
    • Cloud Build API
    • Artifact Registry API

 

빌드할 소스 파일 준비

  1. Cloud Shell 세션을 엽니다. 
  2. quickstart-docker라는 이름의 새 디렉터리를 만들고 디렉터리로 이동합니다.
    mkdir quickstart-docker cloudshell workspace \ quickstart-docker
     
     
  3. Cloud Shell의 파일 편집기에서 파일 > 새로 만들기를 선택하여 quickstart-docker 디렉터리에서 다음 내용으로 quickstart.sh 파일을 생성합니다.
    #!/bin/sh echo "Hello, world! The time is $(date)."
  4. Cloud Shell의 파일 편집기에서 파일 > 저장을 선택하여 파일을 저장합니다.
  5. 같은 디렉터리에서 다음 내용으로 Dockerfile 파일을 만듭니다.
    FROM alpine
    COPY quickstart
    .sh /
    CMD
    ["/quickstart.sh"]
  6. Cloud Shell의 파일 편집기에서 파일 > 저장을 선택하여 파일을 저장합니다.
  7. 터미널 열기를 클릭하여 터미널 창을 엽니다.
  8. 터미널 창에서 다음 명령어를 실행하여 quickstart.sh를 실행 가능하게 만듭니다.
    chmod +x quickstart.s

Artifact Registry에서 Docker 저장소 만들기

  1. us-west2 위치에 'Docker 저장소' 설명과 함께 quickstart-docker-repo라는 새 Docker 저장소를 만듭니다.
    gcloud artifacts repositories create quickstart-docker-repo --repository-format=docker \
       
    --location=us-west2 --description="Docker repository"
  2. 저장소가 만들어졌는지 확인합니다.
    gcloud artifacts repositories list
    표시된 저장소 목록에 quickstart-docker-repo가 표시됩니다.

 

화면 

 

빌드 구성 파일을 사용하여 이미지 빌드

  1. quickstart.sh  Dockerfile이 포함된 동일한 디렉터리에서 다음 내용으로 cloudbuild.yaml이라는 파일을 만듭니다.
    steps:
    - name: 'gcr.io/cloud-builders/docker'
     
    args: [ 'build', '-t', 'us-west2-docker.pkg.dev/commerce-api-412314/quickstart-docker-repo/quickstart-image:tag1', '.' ]
    images:
    - 'us-west2-docker.pkg.dev/commerce-api-412314/quickstart-docker-repo/quickstart-image:tag1'
  2. 다음 명령어를 실행하여 빌드를 시작합니다.
    gcloud builds submit \ --region=us-west2 --config \ cloudbuild.yaml
     
     

빌드 구성 파일을 사용하여 quickstart-image를 빌드하고 Artifact Registry에 푸시했습니다.

 

빌드 세부정보 보기

  1. Cloud Build 페이지를 엽니다.빌드 기록 페이지가 표시됩니다.
  2.  Cloud Build
  3. 리전 드롭다운 메뉴에서 us-west2를 선택하여 해당 리전의 빌드를 확인합니다.
  4. 특정 빌드를 클릭하면 빌드 세부정보 페이지가 표시됩니다.
  5. 빌드의 아티팩트를 보려면 빌드 요약에서 빌드 아티팩트를 클릭합니다.
  6. 빌드의 출력이 표시됩니다. 이 페이지에서 Artifact Registry의 빌드 로그를 다운로드하고 이미지 세부정보를 볼 수 있습니다.

 

삭제

이 빠른 시작에서 사용한 리소스의 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 단계를 따르세요.

  1. Artifact Registry 페이지를 엽니다.
  2.  Artifact Registry
  3. quickstart-docker-repo를 선택합니다.
  4. 삭제를 클릭합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

https://cloud.google.com/build/docs/build-push-docker-image?hl=ko 

 
반응형
반응형

 

구글 클라우드 플랫폼(GCP) 시작하기

구글 클라우드 플랫폼(GCP)를 사용하려면 먼저 계정을 등록시켜야 합니다. Gmail에 사용하는 구글 계정이 있는경우 이를 통해 로그인을 진행 할 수 있지만 클라우드 계정이 없다면 클라우드 계정에 가입해야합니다. 구글 클라우드 플랫폼은 90일간 $300을 사용할 수 있는 무료 크레딧을 제공해 주기 때문에 이를 통해 구글 클라우드 플랫폼을 체험해 볼수도 있습니다.

 

구글 클라우드 플랫폼 등록을 맞추면 클라우드 콘솔로 이동하고 My First Project라는 새로운 프로젝트가 자동으로 만들어 줍니다. 또한 페이지의 왼편에는 컴퓨팅, 서버리스, 저장소등과 같이 구글 클라우드 플랫폼이 제공하는 서비스가 속한 카테고리와 프로젝트별 구성란이 있습니다.

 

1. 프로젝트 선택하기

 

2. cloud shell

cloud shell 활성화하기

cloud shell 로 한 프로젝트에 속한 application 들을 관리

 

gcloud auth list

 

gcloud config set account `이메일계정`

 

다음과 같이 output 이 나오면 인증 되었고, 아래 명령어로 프로젝트를 확인하면 된다.

gcloud config list project

 

정상 output 이다 

안된다면 아래 명령어로 project 를 설정하자

gcloud config set project <PROJECT_ID>



참고

https://codelabs.developers.google.com/codelabs/cloud-app-engine-springboot#0

반응형
반응형

NVM이란?

Node Version Manager.
노드 버전 관리자이다.

프로젝트마다 다른 노드 버전을 관리하기에 유용하다.

 

2. NVM 설치

1. Homebrew 설치

Homebrew는 Mac용 패키지 관리자이다. 사용하면 간단하게 명령어로 필요한 패키지를 설치할 수 있다.

Homebrew: https://brew.sh/

터미널을 열어 명령어로 Homebrew를 설치하고 잘 설치 됐는지 확인해보자.

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

$ brew --version
Homebrew 3.6.20

 

2. NVM 설치

homebrew를 통해 NVM을 설치한다.

$ brew install nvm

 

3. .nvm 폴더 생성

홈 폴더에 .nvm 폴더를 생성한다.

# 홈에 nvm 폴더 생성
$ mkdir ~/.nvm

 

4. 환경변수 설정하기

사용하고 있는 쉘의 종류에 따라 파일을 변경해준다. (.bashrc, .bash_profile, .zshenv 등등)

# bash 환경변수 파일 열기
vi ~/.bash_profile
 or
# zsh 환경변수 파일 열기
vi ~/.zshrc

 

 

아래 코드를 붙여넣기 하고 저장한다. (:wq)

 

# ~/.bash_profile 설정
export NVM_DIR="$HOME/.nvm"
[ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh"  # This loads nvm
[ -s "/usr/local/opt/nvm/etc/bash_completion" ] && . "/usr/local/opt/nvm/etc/bash_completion"  # This loads nvm bash_completion


# ~/.zshrc 설정
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh

 

source명령어로 저장한 코드를 적용시켜준다.

# bash 적용
$ source ~/.bash_profile
or
# zsh 적용
$ source ~/.zshrc

 

5. nvm 확인

$ nvm -v
0.39.3

 

nvm 으로 node 설치하기

노드 버전 설치하기

  • install 명령어를 사용해 특정 노드 버전을 설치할 수 있다.
nvm install v14.18.1

 

  • 만약 lts 버전(서버환경에서 장기적으로 안정적 지원을 제공하는 버전)를 설치하고 싶다면, 아래 명령어를 사용하자.
nvm install --lts

 

설치된 노드 목록 보기

만약 설치된 node 버전을 보고 싶다면 nvm ls

 

nvm 명령어 목록

# node의 리스트 확인
nvm ls

# node 설치 : install 뒤에 node 버전 입력
nvm install 17.5.0

# node 사용 : node에 대해 nvm을 이용하여 등록 처리
nvm use 17.5.0

# 특정 node 버전 삭제
nvm uninstall 17.5.0

# 여러버전의 node중에 어떤것으로 사용할 지 default 버전 설정
nvm alias default v12.18.2

# node 버전 확인
node --version
or
node -v

 

반응형
반응형

 

Pageable

Pagination 기능을 편리하게 사용할 수 있도록 JPA는 Pageable이라는 객체를 제공한다.

 

 

controller 에서 부터 pageable 관련 파라미터를 받을 수 있다. 

정렬 기능

@GetMapping("/")
public ResponseEntity getData(
              @PageableDefault(size = 10, sort = "reqDt", direction= Sort.Direction.DESC)
              Pageable pageable) 
// reqDt 에 대한 내림차순 정렬


@SortDefault 

위의 방식은 정렬을 한가지만 할 수 있어, 여러 정렬 조건을 추가하려면 @SortDefault 를 추가하면 된다. 

@GetMapping("/")
public ResponseEntity getData(
      		@SortDefault.SortDefaults({
              	@SortDefault(sort = "id", direction = Sort.Direction.ASC),
                @SortDefault(sort = "reqDt", direction = Sort.Direction.DESC)
              })
              @PageableDefault(size = 10)
              Pageable pageable) 
// id 오름차순 및 reqDt 에 대한 내림차순 정렬

 

controller 요청방법 

?page=0&size=10&sort=regDt,desc


PageRequest

다른 방법으로는 controller 에서 외에 paging 관련 데이터를 PageRequset 객체에 넣어 
Pagable 을 생성 후 find 쿼리 메소드에 객체를 전달하면 된다.

 

Pagable pageObj = PageRequest.of(0, 5, Sort.by("reqDt").descending().and(Sort.by("id")));

 

controller 에서 부터 PageRequest 를 세팅 하고 싶다면 Pageable을 대체하는 PageRequest 관련 객체를 따로 생성하면 된다.

public final class PageRequest {

    private int page;
    private int size;
    private Sort.Direction direction;

    public void setPage(int page) {
        this.page = page <= 0 ? 1 : page;
    }

    public void setSize(int size) {
        int DEFAULT_SIZE = 10;
        int MAX_SIZE = 50;
        this.size = size > MAX_SIZE ? DEFAULT_SIZE : size;
    }

    public void setDirection(Sort.Direction direction) {
        this.direction = direction;
    }
    // getter

    public org.springframework.data.domain.PageRequest of() {
        return org.springframework.data.domain.PageRequest.of(page -1, size, direction, "createdAt");
    }
 }
  • setPage(int page) 메서드를 통해서 0보다 작은 페이지를 요청했을 경우 1 페이지로 설정
  • setSize(int size) 메서드를 통해서 요청 사이즈 50 보다 크면 기본 사이즈인 10으로 바인딩
  • of() 메서드를 통해서 PageRequest 객체를 응답해줍니다. 페이지는 0부터 시작하니 page -1 합니다. 본 예제에서는 sort는 createdAt 기준으로 진행.

 


Repository

@Repository
public interface BoardRepository extends JpaRepository<Board, Long> {
    Page<Board> findAll(Pageable pageable);
}

find 객체의 리턴에 Page<객체명> 을 해주면 자동으로 count 쿼리를 jpa 가 요청하여, paging 에 필요한 데이터를 조회 후 객체에 추가해 준다. 

Pageable 에 해당 되는 size 및 page, sort 에 해당 되는 쿼리를 jpa 가 생성하여 보내준다.

 

결과가 아래와 같이 생성된다.

{
    "content": [
        {
            "id": 3,
            "name": "이름",
            "description": "설명",
            "createdAt": "2024-03-10T13:22:09",
            "updatedAt": "2024-03-10T13:22:09"
        },
        {
            "id": 2,
            "name": "이름2",
            "description": "자세한설명",
            "createdAt": "2024-03-10T13:22:09",
            "updatedAt": "2024-03-10T13:22:09"
        }
    ],
    "pageable": {
        "sort": {
            "empty": false,
            "sorted": true,
            "unsorted": false
        },
        "offset": 0,
        "pageSize": 2,
        "pageNumber": 0,
        "paged": true,
        "unpaged": false
    },
    "last": false,
    "totalPages": 3,
    "totalElements": 5,
    "size": 2,
    "number": 0,
    "sort": {
        "empty": false,
        "sorted": true,
        "unsorted": false
    },
    "first": true,
    "numberOfElements": 2,
    "empty": false
}
 

 

 

Page 객체는 totalPages 및 totalElements 값을 count 쿼리를 통해 가지고 있다.

totalCount를 얻기 위해서는 다음과 같이 getTotalElements() 메서드를 사용한다:

public interface Page<T> extends Slice<T> {
    static <T> Page<T> empty() {
        return empty(Pageable.unpaged());
    }

    static <T> Page<T> empty(Pageable pageable) {
        return new PageImpl(Collections.emptyList(), pageable, 0L);
    }

    int getTotalPages();

    long getTotalElements();

    <U> Page<U> map(Function<? super T, ? extends U> converter);
}

 

 

https://www.baeldung.com/spring-data-jpa-pagination-sorting [PageRequest 예시]

 
반응형
반응형

챗 gpt 책을 추천하려고 한다.

챗GPT 의 사전 지식부터 챗GPT 서비스에 대한 종류들 그리고 챗GPT 의 등장으로 인한 여러 변화들과
api 를 사용하는 방법 등등 그리고 챗GPT 를 활용하는 방법까지 이 책은 소개 하고 있어서 개발자부터 비개발자 전부 이 책을 활용 할 수 있을 것 같아 범용적인 책으로 소개하고 싶다.
하지만 아무래도 컴퓨터 관련 전공자가 책을 읽기 조금 수월하다. 

아래는 전체적인 내용을 요약한 개요다.

[챗GPT 개념과 동작 원리 이해]
ㆍ 임베딩, 인코딩, 디코딩, 자연어 처리 개념
ㆍ 자연어 처리 알고리즘과 챗GPT 동작 원리

[다양한 챗GPT 서비스 소개]
ㆍ 챗GPT 플러그인, GPT-4 모델
ㆍ 달리, 코덱스, 위스퍼, 빙, 코파일럿, 루프

[챗GPT 직접 사용해보기]
ㆍ 챗GPT 가입하고 질문하기
ㆍ API 키 획득, 퓨샷, 원샷, 제로샷 러닝
ㆍ 파인 튜닝, GPT-3 API 사용, 챗GPT API 사용
ㆍ 위스퍼 사용, 애저에서 챗GPT 사용

[챗GPT 활용 시나리오]
ㆍ 챗GPT 유스케이스, 코딩하기, 이미지 생성
ㆍ 업무에 활용: 업무 관련 질문, 엑셀에서 사용
ㆍ 일상생활 질문: 전등 교체나 요리법 등
ㆍ 과제하기, 챗GPT로 작성한 과제 찾기
 
아래는 챕터 내용이다.

1부. 알아 두면 쓸모 있는 사전 지식

1장. 자연어 처리, 일상생활의 언어를 이해하여 분석하다
자연어 처리를 이해하기 위해 미리 알아 두자
__단어를 수치로 표현하다: 임베딩
__컴퓨터와 인간에게 맞는 표현으로 변환한다: 인코딩과 디코딩
__자연어 처리란?
자연어 처리를 효율적으로: 자연어 처리 알고리즘
__순환신경망(RNN)
__순환신경망 장단기 기억(LSTM)
__seq2seq와 어텐션
__트랜스포머, 버트, GPT
생성형 언어 모델, 챗GPT

2부. 챗GPT, 베일을 벗다

2장. 챗GPT가 궁금해?
챗GPT, 너의 정체가 궁금하다
__새로운 셀럽의 등장, 챗GPT
__챗GPT의 성과
__챗GPT의 동작 원리
챗GPT 플러그인
GPT-4의 등장
__GPT-4 모델
챗GPT의 형제들
__GPT-3 서비스
__달리(DALL-E) 서비스
__코덱스(Codex) 서비스
__위스퍼(Whisper) 서비스
GPT의 발전 과정

3장. 챗GPT의 등장으로 인한 변화
챗GPT의 등장과 구글의 종말
챗GPT에게 도전장을 내밀다
책임 있는 AI란?
챗GPT의 진실과 거짓
챗GPT의 한계

4장. 오픈AI와 마이크로소프트
오픈AI와 마이크로소프트의 관계
__마이크로소프트의 12조 원 투자
__오픈AI의 챗GPT와 마이크로소프트의 챗GPT
마이크로소프트 빙
마이크로소프트 코파일럿
마이크로소프트 루프

3부. 챗GPT 시작하기, 파인 튜닝과 API

5장. 챗GPT 만들기
챗GPT 시작하기
__챗GPT에 질문하기
__오픈AI에서 발급하는 API 키 획득하기
__애저에서 챗GPT를 사용하기 위한 준비
우리 기업만의 챗GPT를 위한 학습
__퓨샷, 원샷, 제로샷 러닝
__퓨샷, 원샷 러닝을 사용하기 위한 구성
파인 튜닝
챗GPT API는 어떻게 사용할까?
__GPT-3 API 사용하기
__GPT-3 파인 튜닝
__챗GPT API 사용하기
__위스퍼 사용하기
__애저에서 챗GPT 사용하기

4부. 글쓰기부터 코딩까지, 다양한 챗GPT 활용

6장. 챗GPT 활용하기
챗GPT를 사용하기 위한 유스케이스
업무에 챗GPT 활용하기
__물어볼 곳이 없다? 챗GPT에게 물어보자
__엑셀에서도 챗GPT를 사용할 수 있다고?
코딩, 참 쉽죠?
캐릭터도 인공지능으로 뚝딱!
고립인 듯 고립 아닌 삶
교사는 챗GPT가 싫다
__챗GPT로 과제하기
__챗GPT로 작성한 과제 찾아내기

 

 

전문지식을 함께 전달하기에 일반인이 읽기에 낯선 용어들이 등장하기도 하지만 깔끔한 편집과 그림을 활용한 설명이 많아 어려운 부분은 천천히 읽다 보면 이해를 할 수 있었고 깊이 있는 지식을 익힐 수 있어 좋다.

특히, 4부의 활용부분에서는 엑셀, 코딩 등 직접 활용할 수 있는 실제 활용법을 따라 해볼 수 있도록 자료를 통해 설명하고 있어 큰 도움이 된다.

총 4부로 구성된 이 책은 알아 두면 쓸모 있는 사전 지식, 챗GPT 베일을 벗다, 챗GPT 시작하기, 파인 튜닝과 API, 글쓰기부터 코딩까지 다양한 챗GPT 활용으로 나뉘어 세세하고 깊이 있는 정보를 알차게 전달하고 있다.

자연어 처리를 이해하기 위한 몇 가지 개념을 익히고 자연어 처리와 챗GPT에 대한 설명, 챗GPT의 개념과 동작 원리를 이해하고 GPT-4에 대한 정보, GPT-3, 달리, 코덱스, 위스퍼, GPT의 발전 과정, 챗GPT 등장으로 인한 변화와 챗GPT를 둘러싼 소문의 진위여부, 한계점, 오픈 AI와 마이크로소프트, 챗GPT의 활용, 챗GPT를 만들기 위한 챗GPT API와 파인 튜닝 등 챗GPT와 관련된 모든 정보를 한 권으로 차근히 배울 수 있다.​

 

결론을 말하자면 책을 실습만을 위한 책은 아니고, 처음 입문하기에는 좋은 책으로 보인다. 

이 책을 입문으로 조금 더 학습하는게 나을 것 같다.

 

반응형
반응형

Java 8 Optional

optional 은 java.util 패키지의 Java 8에 추가된 새로운 클래스입니다. 이 도움말에서는 Java Optional 클래스와 해당 개체에 대해 자세히 설명합니다.

 
Optional의 필요성
간단히 말해서, Optional은 Java에서 NullPointerException을 우아하게 다루기 위해 설계되었습니다.
아마도 null 참조에 익숙하실 겁니다. 이로 인해 가장 흔하게 발생하는 NullPointerException을 아래와 같이 보실 수 있습니다.
String str = null;
if(str.equals("codippa")) {
// do something
}
 
 

null 참조에서 메서드를 호출하려고 하기 때문에 java.lang.NullPointerException을 발생시킵니다. 이 문제를 해결하기 위해 Optional 클래스가 추가되었습니다.

 

간단한 null 체크로 NullPointerException을 피할 수 있다고 생각할 수 있습니다. 아래 코드와 같이 말이죠.

 

String str = null;
if(str != null && str.equals("codippa")) {
// 
}

그렇다면 왜 이를 위한 별도의 클래스가 필요한 걸까요?
맞습니다. 하지만 아래 코드를 살펴보세요.

 

String country = student.getStudentDetails().getAddress().getCountry().toLowerCase();
switch(country) {
case "India":
// 뭔가를 수행합니다
case "USA":
// 뭔가를 수행합니다

// 다른 나라들
}
 

위 예제는 student, studentDetails, address 또는 country 객체 중 하나라도 null이라면 NullPointerException의 가능성이 여러 곳에서 발생할 수 있습니다.

이제 여러분은 이전처럼 null 체크를 추가하고 싶을지도 모릅니다. 그러나 그렇게 한다면 위 코드는 다음과 같이 변합니다.

 

String country = null;

if(student != null) {
	StudentDetails studentDetails = student.getStudentDetails();
	if(studentDetails() != null) {
		Address address = studentDetails().getAddress();
		if(address() != null) {
			Country studentCountry = address.getCountry();
			if(studentCountry != null) {
				country = studentCountry.toLowerCase();
			}
		}
	}
}
 

보시는 대로 이 코드는 읽기 어렵고 유지 및 수정하기도 어렵습니다. 이러한 문제를 해결하기 위해 Optional이 만들어졌으며, Optional에 대해 자세히 학습한 후에 다시 살펴보겠습니다.


Optional이란?
Optional은 객체 위에 래퍼 또는 컨테이너입니다. 값(또는 객체)을 포함할 수도 있고 포함하지 않을 수도 있습니다.
Optional은 어떤 객체든 포함할 수 있으므로 Optional<String>, Optional<Cat> 등의 형식으로 선언되며 아래와 같이 생겼습니다.


Optional을 사용하면 값이 존재할 때만 해당 값을 가져오거나, 보유하는 객체가 없거나 null인 경우 기본값을 반환할 수 있습니다.

이를 통해 NullPointerPointerException 문제를 해결하며 코드를 기존의 null 체크보다 더 읽기 쉽게 만듭니다. Optional을 깊게 학습한 후에 위의 예제를 Optional 객체를 사용하여 어떻게 수정할 수 있는지 살펴보겠습니다.

Optional 객체 생성
Optional 객체는 생성자를 통해 생성할 수 없습니다. 이는 생성자가 private이기 때문입니다.
Optional 객체는 정적 메서드를 사용하여만 생성할 수 있으며 아래에 설명된대로 생성됩니다.

 

1. of() 메서드 사용
Optional은 Optional.of() 메서드를 호출하여 해당 Optional이 보유할 객체를 제공하여 생성할 수 있습니다.
예제,

Student student = new Student();
Optional<Student> optional = Optional.of(student);
만약 of에 제공된 객체가 null이면 NullPointerException이 발생합니다. 객체가 null일 가능성이 있는 경우에는 다음에 설명하는 메서드를 사용하세요.

 

2. ofNullable() 메서드 사용
이것은 Optional 객체를 생성하는 두 번째 방법입니다.
ofNullable()도 정적 메서드이며 인수로 객체를 받아 이 객체를 포함하는 Optional을 생성합니다.

만약 객체가 null이라면 빈 Optional 객체를 생성하고 반환합니다. 예제,

Student student = new Student();
Optional<Student> optional = Optional.ofNullable(student);

 

 

 

 

3. 빈 optional 객체 생성
아래와 같이 정적 빈 메소드를 사용하여 빈 값을 가진 Optional 객체를 생성하는 것도 가능합니다.

Optional<Student> optional = Optional.empty(student);

공백으로 반환된 Optional 은 모든 참조 유형에 할당 될 수 있습니다. 

즉 Optional<String>, Optional<Shape>, Optional<Object>


Value of Optional
앞에서 설명한 것처럼 Optional은 객체를 둘러싼 래퍼이지만 기본 객체에 어떻게 액세스합니까? Optional은 래핑하는 객체를 반환하는 get 메소드를 제공합니다. 이 객체의 유형은 Optional 유형과 동일합니다.

 

String color = "red";
Optional<String> optional = Optional.of(color);
String back = optional.get();
System.out.print("Color is : " + back);

결과

 

Color is : red

Check Optional value
Optional 객체에 값이 포함되어 있지 않은 경우, 즉 그것이 empty() 또는 ofNullable() 메서드를 사용하여 생성된 빈 Optional이고 get()을 사용하여 해당 값에 액세스하려고 하면 오류가 발생합니다.

Exception in thread “main” java.util.NoSuchElementException: No value present

이 오류를 방지하려면 isPresent() 또는 isEmpty() 메서드를 사용하여 Optional에 액세스하기 전에 Optional에 값이 포함되어 있는지 확인하는 것이 좋습니다.
isPresent()
이 메서드는 Optional에 값이 포함되어 있으면 true를 반환하고 그렇지 않으면 false를 반환합니다. 

 
Optional<String> optional = Optional.empty();
System.out.print("Optional contains a value? " + optional.isPresent());

결과

Optional contains a value? false

isEmpty()
이 메소드는 isPresent()와 반대로 작동하며 Optional 객체에 값이 없으면 true를 반환하고 그렇지 않으면 false를 반환합니다.

 

// create empty Optional value
Optional<String> optional = Optional.empty();
System.out.print("Optional contains a value? " + optional.isEmpty());

결과

Optional contains a value? true

Action on value present
마지막 섹션에서는 Optional에 값이 포함되어 있는지 확인하는 방법을 살펴보았습니다.
Optional에 값이 포함된 경우 일부 작업을 수행하려면 다음 줄을 생각해 보세요.

Optional<String> o = Optional.empty();
// check if optional contains a value
if(o.isPresent()) {
System.out.print(o.get());
}

그러나 Optional은 if 조건이 필요하지 않은 단축 방법을 제공합니다.

Optional의 isPresent() 메소드를 사용합니다.

 

이 메소드는 기능적 인터페이스인 java.util.function.Consumer 유형의 인수를 허용하므로 해당 구현을 Lambda 표현식으로 직접 제공할 수 있습니다.

 

Optional<String> o = Optional.of("Learning optional");
// print value of optional if non-empty
o.ifPresent((e) -> System.out.println(o.get()));

결과

Learning optional

 

Default optional value
위의 예는 Optional에 값이 있는 경우 취해야 할 조치와 값이 없는 경우 취해야 할 조치를 보여줍니다.
Optional은 비어 있는 경우 일부 작업을 수행하는 방법을 제공합니다.
이러한 방법은
1. orElse()
이 메서드는 값을 인수로 받아들이고 Optional이 비어 있으면 이 값을 반환합니다.
이 인수의 유형은 Optional 유형과 동일해야 합니다.

// simple pizza
Pizza plainPizza = new Pizza();
plainPizza.setDescription("Pizza without any toppings");
// create empty Optional
Optional<Pizza> empty = Optional.empty();
// get pizza from optional
Pizza p = empty.orElse(plainPizza);
System.out.print(p.getDescription())

이 예제에서는 빈 Optional을 생성한 다음 기본 객체를 인수로 사용하여 orElse() 메서드를 호출합니다. 이 코드의 출력은 다음과 같습니다

Pizza without any toppings

이는 orElse()가 반환한 객체가 해당 인수와 동일함을 보여줍니다.
2. orElseGet()
이 메서드는 orElse()와 유사하며 Optional이 비어 있으면 값을 반환합니다.
이는 java.util.function.Supplier 유형의 인수를 허용하므로 공급자가 반환한 값을 반환합니다.

orElseGet()의 예가 앞서 제공됩니다.

// create empty optional
Optional<String> empty = Optional.empty();
String s = empty.orElseGet(() -> "Optional is empty");
System.out.println(s);

결과

Optional is empty

공급자가 기능적 인터페이스이기 때문에 orElseGet() 메서드에 대한 인수는 Lambda 표현식입니다.
위 구문이 혼란스러워 보인다면 orElseGet()에 대한 호출을 별도의 줄로 나누는 아래 코드를 살펴보세요.

 

// define a supplier
Supplier<String> supplier = () -> "Optional is empty";
String s = empty.orElseGet(supplier);
 

 

Difference between orElse() & orElseGet()
1. 두 메소드 사이의 눈에 띄는 차이점은 orElse()는 Optional 객체와 동일한 유형의 인수를 허용하는 반면 orElseGet() 메소드는 java.util.function.Supplier 유형의 인수를 허용한다는 것입니다.

2. 또 다른 차이점은 orElse()가 단순히 제공된 인수를 반환하는 반면 orElseGet()은 결과를 검색하기 위해 공급자 메서드를 호출한다는 것입니다.

3. 하지만 그 이면에는 또 다른 차이점이 있는데, 이 차이점은 아래 예에서 확인할 수 있습니다.

private void getData() {
System.out.println("Fetching data");
}

// create non-empty optional
Optional<String> o = Optional.of("Learning optional");
System.out.println("------------ orElse ------------");

// using orElse
String s = o.orElse(getData());
System.out.println(s);
System.out.println("\n------------orElseGet-------------");

// using orElseGet
s = o.orElseGet(() -> getData());
System.out.println(s);
 

orElse() 및 orElseGet()에 값을 직접 제공하는 대신 값을 반환하는 메서드를 호출합니다.

이 코드를 실행하면 다음과 같은 출력이 생성됩니다.

———— orElse ————
Fetching data
Learning optional

————orElseGet————-
Learning optional

이 출력에서 Optional이 비어 있지 않더라도
orElse()는 여전히 메서드를 실행하는 반면 orElseGet()은 Optional이 비어 있는 경우에만 메서드를 실행합니다.

이는 데이터를 가져오는 데 관련된 네트워크 또는 데이터베이스 호출이 있는 경우 상당히 중요합니다.
3. or()
이 메소드는 Java 9에 추가되었습니다. Optional에 값이 포함되어 있으면 동일한 Optional을 반환하고 그렇지 않으면 다른 기본 Optional 개체를 반환합니다.

or()는 java.util.function.Supplier 유형의 인수를 기대합니다. 반환된 기본 Optional은 이 인수 공급자 함수에 의해 제공됩니다.

String s = "optional value";
// create an optional
Optional<String> o = Optional.ofNullable(s);
// get Optional with or
Optional<String> or = o.or(()-> Optional.of("Default"));
System.out.println("Optional value:: " + or.get());

// create an optional with null value
Optional<String> empty = Optional.ofNullable(null);
// get Optional with or
Optional<String> defaultOptional = empty.or(()-> Optional.of("Default"));
System.out.println("Optional value:: " + defaultOptional.get());

결과

Optional value:: Optional value
Optional value:: Default

Optional에 값이 포함되어 있으면 또는 동일한 Optional을 반환합니다.
그러나 비어 있으면 or의 인수 함수에서 제공하는 Optional이 반환됩니다.

 

Throwing exceptions
지금까지 Optional이 비어 있는 경우 기본값을 반환하는 방법을 살펴보았습니다. 그러나 때로는 비어 있는 Optional을 오류로 간주해야 하는 경우도 있습니다.

이러한 상황을 처리하기 위해 Optional이 비어 있을 때 오류가 발생할 수도 있습니다.
이에 대한 방법은 다음과 같습니다

1. orElseThrow(Supplier)
이 메소드는 공급자 인터페이스 유형의 인수를 승인하고 이 공급자 함수에 의해 반환되는 예외를 발생시킵니다.

orElseThrow()는 Optional이 비어 있는 경우에만 예외를 발생시킵니다. 

// create empty optional
Optional<String> o = Optonal.ofNullable(null);
// throw exception when optional does not have any value
o.orElseThrow(() -> new IllegalArgumentException("Empty Optional"));
 

결과

Exception in thread “main” java.lang.IllegalArgumentException: Empty Optional
at com.codippa.demo.DemoApplication.lambda$0(DemoApplication.java:22)
at java.base/java.util.Optional.orElseThrow(Optional.java:408)
at com.codippa.demo.DemoApplication.main(DemoApplication.java:22)

2. orElseThrow()
이 메소드는 위에서 설명한 orElseThrow()와 유사하지만 어떤 인수도 허용하지 않으며 Optional이 비어 있는 경우 기본적으로 "값이 없습니다"라는 오류 메시지와 함께 java.util.NoSuchElementException을 발생시킵니다.

// create empty optional
Optional<String> o = Optonal.ofNullable(null);
// throw exception when optional does not have any value
o.orElseThrow();
 

결과

Exception in thread “main” java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.orElseThrow(Optional.java:382)
at com.codippa.demo.DemoApplication.main(DemoApplication.java:22)

이 메소드는 Java 10에 추가되었습니다.
Filtering data
값이 특정 기준을 충족하는 경우에만 결과를 반환하려는 조건이 있을 수 있습니다.

Optional은 일치할 조건을 나타내는 Predicate를 허용하고 값이 조건자(또는 조건)와 일치하면 Optional 개체를 반환하고 그렇지 않으면 빈 Optional을 반환하는 필터 메서드를 제공합니다.
Example,

Laptop apple = new Laptop("Apple");
Optional<Laptop> laptop = Optional.of(apple);
// check if
Optional<Laptop> o = laptop.filter((l) -> "Apple".equals(l.getBrand()));
System.out.println(o.orElseThrow());

 

위의 예에서는 노트북 브랜드를 확인하고 브랜드가 Apple이 아닌 경우 빈 Optional을 반환하도록 필터링합니다.

제공된 Predicate가 false를 반환하는 경우, 즉 조건이 일치하지 않는 경우 filter() 메서드는 빈 Optional을 반환합니다.
orElseThrow는 반환된 Optional이 비어 있으면 예외를 발생시킵니다.


Transforming Optional
map 및 flatMap 메소드를 사용하여 일부 유형의 Optional을 다른 유형의 Optional로 변환하는 것이 가능합니다.

 

map()
map()은 인수를 승인하고 값을 반환하는 단일 메소드가 있는 기능적 인터페이스인 java.util.function.Function 유형의 인수를 승인합니다.

map() 인수 함수는 매퍼 함수라고도 합니다.

아래 map() 메소드 예는 Optional<Laptop>을 Optional<String>으로 변환합니다.

 

Laptop apple = new Laptop("Apple");
// create Optional object
Optional<Laptop> laptop = Optional.of(apple);
// map laptop Optional to a string Optional
Optional<String> strOptional = laptop.map(l -> l.getBrand());
// get Optional value
String brand = strOptional.get();
System.out.println(brand); //prints Apple

다음은 위 예의 지도 방법과 관련된 몇 가지 중요한 사항입니다.

map(l -> l.getBrand()) 문에서 map에는 단일 인수가 포함된 Lambda 표현식이 제공되며 이는 값을 반환합니다.
map()은 map()에 인수로 제공된 Lambda 표현식의 반환 유형으로 수정된 유형의 Optional을 반환합니다.
따라서 위의 예에서 map()은 String 유형의 Optional을 반환합니다.

map()은 Optional을 반환하므로 map() 뒤에 다른 Optional 메서드를 연결하는 것이 가능합니다.

 
String brand = laptop.map(l -> l.getBrand()).map(s -> s.toUpperCase()).get();
System.out.println(brand); //prints APPLE

 

두 번째 map() 메소드에 대한 값 유형은 첫 번째 map() 메소드에서 반환된 Optional 유형인 String입니다.
인수 함수가 null을 반환하면 map()은 빈 Optional을 반환합니다.
flatMap()
Optional 객체를 변환하는 또 다른 방법은 flatMap() 메서드를 사용하는 것입니다.

map() 메소드와 flatMap() 메소드에는 두 가지 차이점이 있습니다.
1. flatMap()의 인수는 반환 유형이 Optional 객체인 함수를 기대하는 반면, map() 메소드의 인수는 위 예에서 반환 유형이 문자열과 같은 값인 함수를 기대합니다.

2. map()은 일부 유형의 값을 래핑하는 Optional을 반환하지만 flatMap()은 값을 직접 반환하며 Optional을 반환하지 않습니다.

3. flatMap()은 Optional 인수가 비어 있으면 Optional을 반환하고 Optional 인수가 비어 있지 않으면 값을 반환하며, map()은 두 경우 모두 Optional을 반환합니다.
flatMap()의 예는 다음과 같습니다.

 

Optional<Laptop> laptop = Optional.of(apple);
String result = laptop.flatMap(l -> l.getBrandOptional()).orElseThrow();
System.out.println(result); // prints Apple
이 예에서 getBrandOptional() 메소드는 브랜드 값을 래핑하는 Optional<String>을 반환하므로 flatMap()은 브랜드 값을 직접 반환합니다.

How Optional avoids NullPointerException
이 기사의 시작 부분에서 NullPointerException을 나타내는 다음과 같은 문제가 논의되었습니다.

String country = student.getStudentDetails().getAddress().getCountry().toLowerCase();

이를 방지하려면 여러 개의 Null 검사가 필요했거나 솔루션이 Optional을 사용하고 있었습니다.

이제 Optional에 대해 배운 후에는 Optional이 NullPointerException을 어떻게 방지하는지 생각해야 합니다.

이 예제에 사용된 모든 클래스를 아래와 같이 수정합니다.

 

 

class Student{

StudentDetails studentDetails;

public Optional<StudentDetails> getStudentDetails() {
return Optional.ofNullable(studentDetails);
}

}

class StudentDetails {
Address address;

public Optional<Address> getAddress(){
return Optional.ofNullable(address);
}
}

class Address {
private Country country;

public Optional<Country> getCountry(){
return Optional.ofNullable(country);
}
}

class Country {
private String country;

public Optional<String> getCountry(){
return Optional.ofNullable(country);
}
}

 

 

보시다시피, getter 메소드는 이제 객체 대신 필요한 객체를 직접 래핑하는 Optional을 반환합니다.
국가를 얻으려면 명령문이 다음과 같이 작성됩니다.

Student st = null;
String country = Optional.ofNullable(st).
flatMap(s -> s.getStudentDetails()).
flatMap(sd -> sd.getAddress()).
flatMap(a -> a.getCountry()).
flatMap(c -> c.getCountry()).
orElse("Country not found");

flatMap()에 대한 각 호출은 Optional 객체를 반환하고 마지막으로 getCountry()에서 반환된 Optional이 비어 있으면 오류 메시지가 반환되지만 NullPointerException은 반환되지 않습니다.

 

 

반응형
반응형

워드프레스 에드센스 연결 방법

워드프레스 에드센스 연결하는 방법은 
워드프레스에 site kit 을 설치하면 된다고 한다. 

 

1. 플러그인 설치 - site kit

google analytics 랑 search console 에도 연동이 되나보네요. 

저는 이미 search console 에는 도메인을 미리 추가했어서, 필요는 없었지만 에드센스 넣기 위해 다운 받았습니다,

 

내 계정으로 로그인 하면 바로 연동이 되네요.

 

각 통계 지표의 오른쪽 하단에 search console 인지 analytics 인지 설명이 있네요.

저는 아직 만든지 얼마 안되는 블로그여서 조촐하네요. 열심히 키워보겠습니다. 

 

 

제일 마지막 항목이 에드센스 항목인데, 여기는 들어가서 연결을 하더라도 바로 안되는거 같네요.

에드센스 화면으로 링크가 이동되고 제가 따로 도메인을 추가해줬습니다.

도메인 승인이 되어야지 에드센스 추가가 되는 것 같네요. 

일단 기다려 봐야 겠습니다.

반응형
반응형

Htaccess 파일 에디터 플러그인 - Htaccess File Editor

FTP 클라이언트 사용에 부담을 느끼는 경우 Htaccess File Editor와 같은 플러그인을 사용하여 워드프레스 대시보드에서 .htaccess 파일을 편집할 수 있습니다.

 

설치하고 나면 블로그 관리 내부에 settings > WP Htaccess Editor 에 노출됩니다.

반응형

+ Recent posts