✍️
dodeon
  • 개발왕, 도던
  • 스프링 시큐리티 인 액션
    • 오늘날의 보안
    • 안녕! 스프링 시큐리티
    • 사용자 관리
    • 암호 처리
    • 인증 구현
    • 실전: 작고 안전한 웹 애플리케이션
    • 권한 부여 구성: 액세스 제한
    • 권한 부여 구성: 제한 적용
    • 필터 구현
    • CSRF 보호와 CORS 적용
    • 실전: 책임의 분리
    • OAuth 2가 동작하는 방법
    • OAuth 2: 권한 부여 서버 구현
  • 스프링 고급편
    • 스레드 로컬
    • 템플릿 메서드 패턴과 콜백 패턴
    • 프록시 패턴과 데코레이터 패턴
  • 스프링 입문
    • 프로젝트 환경설정
    • 스프링 웹 개발 기초
    • 회원 관리 예제 - 백엔드
    • 스프링 빈과 의존 관계
    • 회원 관리 예제 - MVC
    • 스프링 DB 접근 기술
      • JDBC
      • JPA
    • AOP
  • 스프링 핵심 원리
    • 객체 지향 설계와 스프링
      • 스프링의 탄생
      • 객체 지향 프로그래밍
      • 좋은 객체 지향 설계의 원칙
      • 객체 지향 설계와 스프링
    • 스프링 핵심 원리 이해
      • 회원 도메인 개발
      • 주문 도메인 개발
    • 객체 지향 원리 적용
      • 관심사의 분리
      • 새로운 구조와 정책 적용
      • 정리
      • IoC, DI, 컨테이너
      • 스프링으로 전환하기
    • 스프링 컨테이너와 스프링 빈
      • 스프링 빈 기본 조회
      • 동일 타입이 둘 이상일 때 조회
      • 상속일 때 조회
      • BeanFactory와 ApplicationContext
      • 다양한 설정 형식
      • 스프링 빈 설정 메타 데이터
    • 싱글턴 컨테이너
      • @Configuration과 싱글턴
    • 컴포넌트 스캔
      • 탐색 위치와 기본 탐색 대상
      • 필터와 중복 등록
    • 의존 관계 자동 주입
      • 롬복과 최신 트렌드
      • 조회 빈이 2개 이상일 때
      • 애너테이션 직접 만들기
      • 조회한 빈이 모두 필요할 때
      • 올바른 실무 운영 기준
    • 빈 생명 주기 콜백
      • 인터페이스 방식
      • 메서드 지정 방식
      • 애너테이션 방식
    • 빈 스코프
      • 프로토타입 스코프
      • Provider
      • 웹 스코프
  • 스프링 MVC
    • 웹 애플리케이션 이해
      • 서버
      • 서블릿
      • 멀티 스레드
      • HTML, HTTP API, CSR, SSR
      • 자바 백엔드 웹 기술 역사
    • 서블릿
      • HttpServletRequest
      • HTTP 요청 데이터
      • HttpServletResponse
      • HTTP 응답 데이터
    • 서블릿, JSP, MVC 패턴
      • 서블릿으로 만들기
      • JSP로 만들기
      • MVC 패턴
    • MVC 프레임워크 만들기
      • 프론트 컨트롤러 패턴
      • View 분리
      • Model 추가
      • 단순하고 실용적인 컨트롤러
      • 유연한 컨트롤러
      • 정리
    • 스프링 MVC의 구조 이해
      • 스프링 MVC 전체 구조
      • 핸들러 매핑과 핸들러 어댑터
      • 뷰 리졸버
      • 스프링 MVC 시작하기
      • 스프링 MVC 컨트롤러 통합
      • 스프링 MVC 실용적인 방식
    • 스프링 MVC 기본 기능
      • 프로젝트 생성
      • 로깅
      • 요청 매핑
      • HTTP 요청의 기본 및 헤더 조회
      • HTTP 요청 파라미터
      • HTTP 요청 메시지
      • HTTP 응답
      • HTTP 메시지 컨버터
      • 요청 매핑 핸들러 어댑터
    • 스프링 MVC 웹 페이지 만들기
    • 메시지, 국제화
      • 스프링 메시지 소스
    • Validation
      • BindingResult
      • FieldError, ObjectError
      • 오류 코드와 메시지 처리
      • Validator 분리
    • Bean Validation
      • Form 전송 객체 분리
      • HTTP 메시지 컨버터
    • 로그인
      • 쿠키
      • 세션
      • 서블릿 HTTP 세션
      • 서블릿 필터
      • 스프링 인터셉터
      • ArgumentResolver 활용
    • 예외 처리와 오류 페이지
      • 오류 화면 제공
      • 필터
      • 인터셉터
      • 스프링 부트 오류 페이지
    • API 예외 처리
      • 스프링 부트 기본 오류 처리
      • HandlerExceptionResolver
      • ExceptionResolver
      • ControllerAdvice
    • 스프링 타입 컨버터
      • Converter
      • ConversionService
      • 뷰 템플릿에 적용하기
      • Formatter
    • 파일 업로드
      • 서블릿과 파일 업로드
      • 스프링과 파일 업로드
      • 파일 업로드 및 다운로드 예제
  • 자바 ORM 표준 JPA 프로그래밍
    • JPA 소개
    • JPA 시작하기
    • 영속성 관리
      • 영속성 컨텍스트
      • 플러시
      • 준영속 상태
    • Entity 매핑
      • 객체와 테이블 매핑
      • 데이터베이스 스키마 자동 생성
      • 필드와 칼럼 매핑
      • 기본 키 매핑
      • 실전 예제
    • 연관 관계 매핑
      • 단방향 연관 관계
      • 양방향 연관 관계
      • 실전 예제
    • 다양한 연관 관계 매핑
      • 다대일
      • 일대다
      • 일대일
      • 다대다
      • 실전 예제
    • 고급 매핑
      • 상속 관계 매핑
      • 매핑 정보 상속
      • 실전 예제
    • 프록시와 연관관계 관리
      • 프록시
      • 즉시 로딩과 지연 로딩
      • 영속성 전이와 고아 객체
      • 실전 예제
    • 값 타입
      • 기본값 타입
      • 임베디드 타입
      • 값 타입과 불변 객체
      • 값 타입의 비교
      • 값 타입 컬렉션
      • 실전 예제
    • 객체 지향 쿼리 언어 - 기본
      • 기본 문법과 쿼리 API
      • 프로젝션
      • 페이징
      • 조인
      • 서브 쿼리
      • JPQL 타입 표현과 기타 식
      • 조건식
      • JPQL 함수
    • 객체 지향 쿼리 언어 - 중급
      • 경로 표현식
      • fetch join
      • 다형성 쿼리
      • Entity 직접 사용
      • Named 쿼리
      • 벌크 연산
  • 스프링 부트와 JPA 활용 - 웹 애플리케이션 개발
    • 프로젝트 환경설정
    • 도메인 분석 설계
      • 도메인 분석 설계
      • Entity 클래스 개발
      • Entity 설계 시 주의점
    • 애플리케이션 아키텍처
    • 회원 도메인 개발
    • 상품 도메인 개발
    • 주문 도메인 개발
      • Entity, 리포지토리, 서비스 개발
      • 주문 기능 테스트
      • 주문 검색 기능 개발
    • 웹 계층 개발
      • 변경 감지와 병합
  • 스프링 부트와 JPA 활용 - API 개발과 성능 최적화
    • API 개발 기본
      • 회원 등록 API
      • 회원 수정 API
      • 회원 조회 API
    • 지연 로딩과 조회 성능 최적화
      • Entity 직접 노출
      • Entity를 DTO로 변환
      • JPA에서 DTO 직접 조회
    • 컬렉션 조회 최적화
      • Entity 직접 노출
      • Entity를 DTO로 변환: 페치 조인
      • Entity를 DTO로 변환: 페이징과 한계 돌파
      • DTO 직접 조회
      • DTO 직접 조회: 컬렉션 조회 최적화
      • DTO 직접 조회: 플랫 데이터 최적화
      • 정리
    • OSIV와 성능 최적화
  • 스프링 데이터 JPA
    • 예제 도메인 모델
    • 공통 인터페이스 기능
      • 순수 JPA 기반 리포지토리
      • 공통 인터페이스 설정
    • 쿼리 메서드 기능
      • JPA Named Query
      • @Query
      • 파라미터 바인딩
      • 반환 타입
      • 페이징과 정렬
      • 벌크성 수정 쿼리
      • @EntityGraph
      • JPA Hint & Lock
    • 확장 기능
      • 사용자 정의 리포지토리
      • Auditing
      • Web 확장
    • 스프링 데이터 JPA 분석
    • 나머지 기능
      • Specifications
      • Query By Example
      • Projections
      • Native Query
  • Querydsl
    • 프로젝트 환경 설정
    • 예제 도메인 모델
    • 기본 문법
      • JPQL vs Querydsl
      • Q-Type 활용
      • 검색 조건
      • 결과 조회
      • 정렬
      • 페이징
      • 집합 함수
      • 조인
      • 서브 쿼리
      • Case 문
      • 상수, 문자 더하기
    • 중급 문법
      • 프로젝션과 결과 반환
      • 동적 쿼리
      • 수정, 삭제 벌크 연산
      • SQL Function 호출
    • 순수 JPA와 Querydsl
      • 순수 JPA 리포지토리와 Querydsl
      • 동적 쿼리와 성능 최적화 조회
      • 조회 API 컨트롤러 개발
    • 스프링 데이터 JPA와 Querydsl
      • 스프링 데이터 페이징 활용
      • 스프링 데이터 JPA가 제공하는 Querydsl 기능
  • 데이터 접근 핵심 원리
    • JDBC 이해
      • JDBC와 최신 데이터 접근 기술
      • 데이터베이스 연결
      • JDBC 개발
  • 백엔드 시스템 실무
    • CPU bound 애플리케이션
      • CPU를 극단적으로 사용하는 애플리케이션
      • 스트레스 테스트 툴로 성능 측정
      • Dockerized 애플리케이션 GCP 배포
      • Jenkins를 이용한 배포
    • CPU bound 애플리케이션 무중단 배포
      • nginx를 통한 로드밸런싱 구성
      • 서버를 늘려서 성능 측정
    • 배포 자동화와 협업을 위한 Git
      • GitHub Webhook과 jenkins로 배포 자동화
      • 머지할 때 발생하는 충돌 해결하기
      • 실무에서 유용한 Git 꿀팁
    • I/O bound 애플리케이션
    • Message Queue를 도입하여 데이터 유실 방지
      • 스트레스 테스트
    • 검색과 분석을 위한 저장소 ElasticSearch
    • Kubernetes
  • 모든 개발자를 위한 HTTP 웹 기본 지식
    • 인터넷 네트워크
      • IP
      • TCP, UDP
      • PORT
      • DNS
    • URI와 웹 브라우저 요청 흐름
    • HTTP 기본
      • 클라이언트-서버 구조
      • stateful, stateless
      • 비 연결성
      • HTTP 메시지
    • HTTP 메서드
    • HTTP 메서드 활용
    • HTTP 상태 코드
    • HTTP 헤더 - 일반
      • 표현
      • 콘텐츠 협상
      • 전송 방식
      • 정보
      • Authorization
      • 쿠키
    • HTTP 헤더 - 캐시
      • 검증 헤더와 조건부 요청
      • 조건부 요청 헤더
      • 프록시 캐시
      • 캐시 무효화
  • 김영한의 실전 자바
    • 제네릭
  • 예제로 배우는 스프링 입문
    • 예제로 배우는 스프링 입문(개정판)
      • PetClinic 예제
      • 스프링 IoC
      • 스프링 AOP
      • 스프링 PSA
  • 스프링 프레임워크 핵심 기술
    • 스프링 프레임워크 핵심 기술
      • IoC 컨테이너와 빈
        • 스프링 IoC 컨테이너와 빈
        • ApplicationContext와 빈 설정
        • @Autowired
        • @Component와 컴포넌트 스캔
        • 빈의 스코프
        • Environment
        • MessageSource
        • ApplicationEventPublisher
        • ResourceLoader
      • Resource/Validation
        • Resource 추상화
        • validation 추상화
      • 데이터 바인딩 추상화
      • SpEL
      • 스프링 AOP
      • Null-Safety
  • 스프링 부트 개념과 활용
    • 스프링 부트 원리
      • 자동 설정
      • 내장 서버
        • 컨테이너와 서버 포트
        • HTTPS와 HTTP2
      • 독립적으로 실행 가능한 JAR
    • 스프링 부트 활용
      • Spring Application
      • 외부 설정
      • 프로파일
      • 로깅
      • 테스트
      • Spring Boot Devtools
    • 스프링 웹 MVC
      • 소개
      • HttpMessageConverters
      • ViewResolver
      • 정적 리소스
      • 웹 JAR
      • index 페이지와 파비콘
      • ExceptionHandler
      • Spring HATEOAS
      • CORS
  • THE JAVA
    • JVM 이해하기
      • 자바, JVM, JDK, JRE
      • JVM 구조
      • 클래스 로더
      • Heap
      • Garbage Collector
    • 리플렉션
      • 클래스 정보 조회
  • The Java - Test
    • JUnit 5
      • JUnit 시작하기
      • JUnit 시작하기
    • Mockito
Powered by GitBook
On this page
  • 인스턴스 생성
  • 젠킨스 설정
  • 플러그인 설치
  • 젠킨스로 배포
  • 대칭키와 비대칭키
  • 젠킨스 인스턴스에서 개인 키와 공개 키 생성
  • 공개 키 등록
  • 워커 내부 폴더 권한 변경
  • 젠킨스만 워커에 접속할 수 있게 설정
  • Publish over SSH
  • SSH Servers
  • 배포 스크립트 작성
  • SSH로 접속해 docker run 명령어 실행
  • 확인
  • 정리

Was this helpful?

  1. 백엔드 시스템 실무
  2. CPU bound 애플리케이션

Jenkins를 이용한 배포

  • 젠킨스의 기능

    • build & deploy

    • batch

      • 실시간이 아니라 모아서 또는 주기적으로 처리하는 것

  • 이전에 손수 빌드, 배포했던 작업을 젠킨스로 자동화 한다.

인스턴스 생성

  • 젠킨스 인스턴스 or 젠킨스

    • 젠킨스가 실행되고 있는 인스턴스

    • 하나만 생성할 예정

  • 워커 인스턴스 or 워커

    • 배포 대상이 되는 인스턴스

    • 개발한 애플리케이션을 실행시키는 인스턴스

# jenkins 인스턴스에서 실행하는 명령어 (한 줄씩 실행하면서 정상적으로 실행이 되고 있는지 꼭 확인해보세요)
sudo yum install wget
sudo yum install maven
sudo yum install git
sudo yum install docker

sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
sudo yum install jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
# 여기까지 실행하면 설치는 완료
  • 웹 브라우저로 젠킨스에 접속할 것이다.

  • 근데 젠킨스는 8080 포트로 떠있다.

  • 우리가 만든 인스턴스는 80 포트를 사용하는데 젠킨스를 80 포트로 바꾸는 건 까다롭다.

  • 방화벽 규칙 설정에서 8080 포트를 허용하는 규칙을 추가한다.

    • 0.0.0.0/0

      • 모든 ip 요청을 허용한다.

    • tcp:8080

      • 8080 포트를 허용한다.

젠킨스 설정

http://00.00.000.00:8080/
  • 인스턴스 ip + 8080 포트로 접속하면 젠킨스 설정 화면이 뜬다.

sudo cat /var/lib/jenkins/secrets/initialAdminPassword
  1. 해당 명령어로 파일을 읽어 비밀번호를 알아낸다.

  2. 추천 플러그인 버튼을 클릭한다.

  3. 어드민 계정으로 사용할 정보를 입력한다.

플러그인 설치

  • 플러그인 관리에서 Publish Over SSH를 재시작 없이 설치한다.

젠킨스로 배포

  • 배포에는 여러 방법이 있지만 SSH를 통해 배포하는 것이 보편적이다.

  • 젠킨스가 워커로 접속해 도커 이미지를 풀 받고 런 시키는 것이다.

  • 이때, 젠킨스의 워커만 SSH로 접속할 수 있게 만들어야 한다.

    • 해커 등 원하지 않는 접속이 있을 위험이 있기 때문이다.

  • 워커가 젠킨스 인스턴스라고 증명할 수 있는 SSH 연결만 허용하도록 만든다.

대칭키와 비대칭키

  • 대칭 키

    • 암호화와 복호화에 같은 키 사용

  • 비대칭 키

    • 암호화와 복호화에 다른 키 사용

    • 둘 사이에 관계는 있지만 키가 같지는 않다는 뜻이다.

  • 공개 키로 암호화한 것은 개인 키로 복호화 할 수 있다.

  • 개인 키로 암호화한 것은 공개 키로 복호화 할 수 있다.

    • 서명이라는 개념

    • A의 공개 키로 서명할 수 있는 건 A 뿐이다.

    • A의 공개 키로 복호화할 수 있는 메시지를 만드는 건 A 뿐이다.

젠킨스 인스턴스에서 개인 키와 공개 키 생성

ssh-keygen -t rsa -f ~/.ssh/id_rsa
  • 젠킨스에서 젠킨스의 개인키와 공개키 쌍을 만든다.

    • Enter passphrase는 계속 엔티를 누른다.

cd .ssh
ls
id_rsa  id_rsa.pub
  • 개인 키와 공개 키 쌍이 생성된 걸 확인한다.

    • pub가 공개키를 나타낸다.

공개 키 등록

vi id_rsa.pub
  • 공개 키 내용을 복사한다.

  • GCP - 메타데이터 - SSH 키에 등록한다.

    • 공개 키가 워커에게 등록된다.

워커 내부 폴더 권한 변경

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
  • 권한을 변경해준다.

젠킨스만 워커에 접속할 수 있게 설정

  • 젠킨스 관리 - 시스템 설정

Publish over SSH

vi ~/.ssh/id_rsa
  • key

    • 젠킨스의 개인 키를 입력한다.

SSH Servers

  • Name

    • 서버를 다양하게 연결 할 수 있기 때문에 구분할 수 있는 이름으로 짓는다.

  • HostName

    • 젠킨스와 워커는 같은 네트워크 상에 있기 때문에 내부 IP를 입력한다.

  • UserName

    • 젠킨스 계정 userName를 넣는다.

    • 젠킨스 인스턴스에 설치된 계정과 맞지 않으면 연결 실패한다.

  • remote directory

    • 이번 프로젝트에서는 홈 디렉토리를 사용한다.

    • pwd 커맨드의 결과를 넣는다.

배포 스크립트 작성

  1. 새로운 Item을 만든다.

    • item name

      • cpu-worker-instance-1 deploy

    • Freestyle project

  2. 빌드 후 조치

  3. Send build artifacts over SSH

  4. SSH Server에 워커 인스턴스를 연결한다.

  5. 고급 - Verbose output in console을 체크한다.

    • 로그를 자세히 출력해준다.

sudo docker run -p 80:80 user-name/spring-boot-cpu-bound
  1. Transfers - Exec command

    • 도커 run 명령어를 입력한다.

SSH로 접속해 docker run 명령어 실행

앞서 했던 설정으로 build를 해보면 실패한다. sudo를 사용할 수 없다고 나올 것이다.

docker run -p 8080:80 user-name/spring-boot-cpu-bound
  • 이전에 sudo를 붙였던 이유는 80번 포트를 사용하기 위해서였다.

    • 8080으로 포트를 변경하면 sudo가 필요없다.

  • 어차피 나중에 nginx가 앞에서 요청을 받게 되는데, nginx만 80번 포트이면 되므로 문제가 없다.

다시 해보면 이번엔 docker: command not found 에러가 뜬다.

sudo yum install docker
sudo systemctl start docker
  • 워크 인스턴스에 docker를 설치하고 docker 데몬을 실행한다.

/usr/bin/docker-current: Got permission denied while trying to connect to the Docker daemon socket 
at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.26/containers/create: 
dial unix /var/run/docker.sock: connect: permission denied.
sudo chmod 666 /var/run/docker.sock
  • 권한 에러가 뜨면 docker.sock의 권한을 변경한다.

이제 애플리케이션이 잘 뜬다. 문제는 로딩 중인 로그 때문에 젠킨스가 배포가 끝나지 않았다고 인식해 빨간색이 된다.

nohup docker run -p 8080:80 redthink90/spring-boot-cpu-bound > /dev/null 2>&1 &
  • 구성 - SSH Server - Transfers - Exec command의 명령어를 수정한다.

nohup ... &
  • 명령을 백그라운드로 실행시키겠다.

> /dev/null 2>&1
  • 표준 에러를 표준 출력으로 리다이렉션 하겠다.

확인

http://{워커의 외부 ip}:8080/hash/123
  • 워커의 외부 IP로 접속해서 응답이 나오는지 본다.

정리

  1. 젠킨스와 워커의 인스턴스를 생성한다.

  2. 젠킨스의 개인 키, 공개 키 쌍을 만든다.

  3. 공개 키를 워커에 등록한다.

  4. 젠킨스에서 워커 인스턴스로 배포하도록 설정한다.

  5. 워커 인스턴스에서 도커 이미지를 pull 받고 run 하게 한다.

    • 이 과정에서 로그를 보며 삽질한다.

PreviousDockerized 애플리케이션 GCP 배포NextCPU bound 애플리케이션 무중단 배포

Last updated 3 years ago

Was this helpful?