8주차: 프로젝트 고도화

이재혁·2023년 7월 18일

1️⃣ 스프링 프로젝트, 데이터베이스와 JPA에 대해 학습합니다.

  • 개인 프로젝트 고도화
  • 페이징/페이지네이션
  • 단위 테스트
  • 빌드와 배포
  • CI / CD - AWS
  • 브랜치 전략 - 깃 플로우

개인 프로젝트 고도화

  • 계층형 구조 → 도메인형 구조 변경
  • 회원가입 기능 완료(세션 활용)
  • 로그인 후 세션 활용해서 CRUD
  • 페이징 처리
  • 카카오 로그인/ 로그인(세션 저장)
  • 페이징 고도화(3, 5, 10)
  • 댓글 기능
  • 좋아요 기능

https://github.com/LEEJaeHyeok97/dcInsideClone3

페이징/페이지네이션

  • 사용자가 특정 페이지 번호를 클릭했을 때 그 페이지에 해당하는 데이터만 사용자에게 보여준다

  • 페이징 처리(/board/paging)

    • /board/paging?page=2
      • 이 주소 체계를 더 선호한다.(매일 매일의 페이지 내용이 달라지기 때문에)
    • /board/paging/2
  • 게시글 14개

    • 한 페이지에 5개씩 ⇒ 필요한 페이지 갯수: 3개
    • 한페이지에 3개씩 ⇒ 5개
    • ⇒ 페이징의 난이도가 높은 이유

BoardController.class

// /board/paging?page=1
@GetMapping("/paging")
    public String paging(@PageableDefault(page = 1)Pageable pageable, Model model) {
        //스프링의 Pageable 인터페이스를 사용한다
       // pageable.getPageNumber();
			Page<BoardDTO> boardList = boardService.paging(pageable);
    }
  • @PageableDefault: 사용자에게 기본으로 보여주는 화면(default값)
  • Pageable 인터페이스: 쿼리 스트링으로 받은 페이지 번호를 넘겨줄 수 있게 한다.
  • Page: 스프링에서 제공하는 인터페이스

BoardService.class

public Page<BoardDTO> paging(Pageable pageable) {
        int page = pageable.getPageNumber() - 1;
        int pageLimit = 3; // 한 페이지에 보여줄 글 갯수
        //한 페이지당 3개씩 글을 보여주고 정렬 기준은 id 기준으로 내림차순 정렬한다는 의미
        // page 위치에 있는 값은 0부터 시작
//페이징 처리된 객체를 가져오는것이다.
        Page<BoardEntity> boardEntities =
                boardRepository.findAll(PageRequest.of(page, pageLimit, Sort.by(Sort.Direction.DESC, "id")));
    }
  • Page 인터페이스가 제공하는 메서드
    • getContent(): 요청 페이지에 해당하는 글
    • getTotalElements(): 전체 글갯수
    • getNumber(): DB로 요청한 페이지 번호
    • getSize(): 한 페이지에 보여지는 글 갯수
    • 등등
  • 페이징에서 상세 페이지 조회를 할 때 page=1 과 같이 현재 머물고 있는 페이지를 쿼리스트링으로 넘겨주는 이유?
    • 현재 머물고 있는 위치를 저장하고 있지 않으면 유저가 게시글 목록을 클릭 할때마다 다시 첫 페이지로 돌아가야하는 불편함이 생긴다. 하지만 머물고 있는 페이지를 저장하면 게시글 목록 클릭 시 이전에 머물렀던 페이지로 돌아갈 수 있다. ⇒ 페이징이 없다면 수많은 데이터가 계속 스크롤 되는데 페이지가 저장되지 않으므로 다시 내가 원하던 위치로 돌아가기 힘들다

단위 테스트

  • 단위테스트란?

    • 소스 코드의 독립된 특정 모듈을 개별적으로 검증하는 테스트
  • 스프링의 대표적인 단위 테스트 툴은 JUnit4이 있다

  • 테스트하고 싶은 모듈이 있다면 그 파일의 패키지 이름과 똑같이 테스트 폴더에 생성한다

  • @Test: 독립적으로 테스트를 수행할 메소드를 지정한다

  • 작성한 테스트는 JUnit Test로 실행한다

  • 정상 작동하였다면 초록색이, 오류가 발생했다면 빨간색 프로그래스 바가 뜨게 된다.

  • 단위테스트를 위한 인텔리제이 단축키

    1. 단위 테스트 코드를 생성할 클래스명 선택, Alt + Enter

      단위 테스트 코드를 생성할 클래스명에 커서를 두고, Alt + Enter를 입력합니다. 목록이 나타나면, Create Test를 선택합니다.

  • memberDTO 테스트 예시

테스트 성공 시 초록색 체크표시가 나타난다.

빌드와 배포

Spring Boot 기반의 애플리케이션 소스 코드를 빌드하는 방법

  • Intellij IDE를 이용한 빌드
    • 우측 상단의 Gradle 윈도우탭 클릭
    • 프로젝트명/Tasks/build 안에 :bootjar 또는 :build 더블 클릭
    • build/libs 디렉토리에 생긴 Jar 파일로 애플리케이션 실행 가능
💡 :build vs :bootJar - :build 태스크 실행하면 - Gradle에서 빌드와 관련된 모든 task들을 실행시킨다 - 실행 가능한 Jar 파일 이외에 plain Jar 파일 하나를 더 생성한다
  • :bootJar 태스크 실행하면
    • 애플리케이션의 실행 가능한 Jar 파일을 생성하기 위한 task만 실행시킨다
    • 단순히 Executable Jar 파일만 필요하다면 :bootJar 실행
  • Gradle Task를 이용한 빌드

    • Windows 터미널이나 Git Bash로 프로젝트가 위치해 있는 디렉토리 경로로 이동
    • 명령을 입력하여 빌드 진행
    • 빌드가 정상적으로 종료되면 build/libs 디렉토리에 Jar 파일 생성됨
  • 애플리케이션 실행

    • Windows 터미널이나 Git Bash로 생성된 Jar 파일이 있는 디렉토리 경로로 이동(jar 파일이 생성된 디렉토리)
      • Ex. cd desktop/projects/be-template-build/build/libs
    • java -jar Jar 파일명.jar 명령 입력하여 애플리케이션을 서버 환경에서 실행 !
      • Ex. java -jar section3-week3-template-build-0.0.1-SNAPSHOT.jar

애플리케이션 배포

  • 전통적인 배포 방법
    • scp와 같은 표준 유닉스 툴을 이용해서 서버로 간단히 전송하는 것이다. 서버로 전송된 jar 파일은 JVM이 설치된 환경이라면 어디서든 손쉽게 실행할 수 있다.
  • 클라우드 서비스를 위한 배포 방법

    jar 파일은 클라우드 환경에서도 손쉽게 배포할 수 있다.

    • PaaS(Platform as a Service)
      • • 대표적인 PaaS 제공 회사인 Cloud Foundry에서 제공하는 cf command line 툴을 사용하면 jar 파일을 손쉽게 배포할 수 있다.
    • IaaS(Infrastructure as a Service)
      • jar 파일은 AWS Code DeployAWS Elastic BeanstalkAWS Container Registry 같은 서비스를 이용해서 손쉽게 배포가 가능하다.
      • 또한, Microsoft의 클라우드 서비스인 Azure와 Google Cloud 역시 여러가지 Executable Jar 파일 배포 기능을 제공한다.
  • CI / CD 플랫폼을 사용한 배포
    • GithubActions나 Circle CI, Jenkins 같은 플랫폼을 이용해 AWS나 Azure 같은 클라우드 서비스에 Executable Jar 파일을 자동 배포하도록 구성할 수 있다.

CI / CD - AWS

매번 새로운 커밋이 발생할 때마다 서버에 새로운 버전으로 업로드하고, 기존에 실행 중이던 프로세스를 종료한 후, 새로 업로드한 프로젝트를 실행하는 일련의 과정은 상당히 번거로운 작업이다.

CI/CD는 지속적 통합(Continuous Integration)과 지속적 배포(Continuous Deployment)의 약자로서, 소프트웨어 개발 프로세스를 혁신적으로 개선하는데 중요한 역할을 수행합니다. CI/CD를 통해 코드 변경 사항을 자동으로 빌드, 테스트 및 배포함으로써 개발 속도를 높이고 안정성을 확보할 수 있습니다. 이러한 자동화 방법론은 개발자가 수동으로 빌드와 배포 과정을 반복하지 않아도 되게 하여 많은 시간을 절약할 수 있습니다.

목표는 main 브랜치에 push가 발생하는 경우 자동으로 서버에 배포되도록 하는 파이프라인을 구축하는 것이다.

  • main 브랜치에 커밋이 발생하면 자동으로 테스트 및 빌드가 이루어진다.
  • 빌드된 jar 파일이 배포 서버에 복사된다.
  • 배포 서버에서는 기존에 실행되고 있는 서버를 중단한다.
  • 새로 빌드된 jar 파일로 서버를 실행한다.

프로젝트 생성

  • 개인 프로젝트 활용

Github 저장소에 push

git add .
git commit -m "Commit message"

커밋 후에는 새로운 저장소를 생성 해준다.

생성이 완료되면 push 해준다.

#git remote add origin 저장소주소
git remote add origin git@github.com:ShanePark/ci-cd-example.git
git branch -M main
git push -u origin main
  • 나는 여기서 origin이 이미 등록되어 있기 때문에 다음 명령어로 수정해서 두번째 remote를 등록했다
    git remote add cicd https://github.com/LEEJaeHyeok97/ci-cd-example.git
    git branch -M main
    git push -u cicd main

푸쉬가 완료 되면 Github 저장소에서 코드 확인이 가능하다.

파이프라인 생성

  • 빌드
    • main 브랜치에 push가 일어날 경우 자동으로 빌드를 시도하는 스크립트를 작성한다
    • Actions 메뉴를 확인해보면 Java with Gradle이 보인다.
    • Configure를 클릭해서 확인한다

확인해보면, 따로 수정할 필요 없이 바로 사용 가능한 스크립트가 작성되어 있다.

바로 우측의 Commit changes.. 를 클릭해 저장.

main에 커밋

커밋과 동시에 CI 작업이 이루어진다. Actions에 들어가서 확인 해 보면 Status가 In Progress로 변경되어 있다.

나는 실패로 나와 있었다

다음과 같이 수정하니 In progress가 잘 떴다

Untitled

그래도 오류가 나서

[에러노트] Execution failed for task ':test'. > There were failing tests.

build.gradle을 수정했더니

그래도 오류가 나서 검색을 해보니, mysql을 위한 세팅을 따로 더 해줘야 하는데

세팅이 더 필요하므로 잠시 중단하기로 한다.

결과적으로는 정상진행이 되면

커밋 할 때 마다 파이프라인이 자동으로 진행된다.

1~2초 간 서비스가 잠시 다운되는데 이를 피하기 위해서는 무중단 배포를 적용해주어야 한다.

브랜치 전략 - 깃 플로우

  • 브랜치 전략이란? 브랜치란 독립적으로 어떤 작업을 진행하기 위한 개념입니다. 필요에 의해 만들어지는 각각의 브랜치는 다른 브랜치의 영향을 받지 않기 때문에, 여러 작업을 동시에 진행할 수 있고 이후 병합이 가능합니다.

  • main 브랜치를 큰 줄기로 필요한 기능을 새로 만들 때 마다
  • 브랜치를 추가했다(pagination, kakaologin..)
  • git에서 병합 시 intellij에서 git pull 해서 코드 통일성을 맞춰줘야 한다.
profile
서비스기업 가고 싶은 대학생

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

좋은 글 잘 읽었습니다, 감사합니다.

답글 달기