반응형

토이 프로젝트로 혼자서 클라우드 서비스를 이용하여 웹 개발부터 배포까지 온 과정을 경험해 보았습니다.

이 과정을 단계별로 나누어서 정리해 보려고 합니다.!

많은 피드백은 감사합니다!

 

목차 

STEP 01) NCP 서버 

STEP 02) AWS RDS, S3

STEP 03) Web Application 개발

STEP 04) Jenkins pipeline 배포

STEP 05) Domain 등록


1. NCP(Naver CLoud Platform)

  - 네이버 클라우드 서비스로 1년간 Free Tier 서비스를 이용할 수 있습니다.

  - 네이버 클라우드 서비스를 사용해 보고 싶어서 서버는 NCP Sorver를 선택

  - 네이버 클라우드 서비스라서 언어가 매우 친숙함.

 

https://www.ncloud.com/

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

 

2. NCP에서는 다양항 클라우드 서비스를 제공합니다.

  - Free Tier에서는 아래 설명과 같이 Micro Server를 1년간 무료로 1대를 제공합니다. 

  - Compute > Server 선택

  - NCP server guide(https://guide.ncloud-docs.com/docs/compute-server-prep)

 

 

3. Server > 서버 생성

 

 

4. 서버 이미지 선택에서 서버 타입 Micro 선택 후 centos-7.8-64 선택  

 

 

5. 서버 설정 탭에서 Free Tier 서버에 맞게 설정 후 다음

  - 본 이미지는 Micro 타입 서버를 이미 1개 생성해서 하나 더 생성할 수 없어서 Compact 타입으로 설정 후 진행하였습니다.

  - SSD 서버는 Micro 타입 서버를 지원하지 않습니다.

 

 

6. 인증키 설정에서 서버에 접속할 관리자 비밀번호를 생성합니다.

  - 항상 인증키는 안전한 곳에 저장!

 

 

7. 네트워크 접근 설정은 생성 할 서버에 대한 방화벽 설정이라고 생각하시면 될 것 같습니다. 

 

 

8. ACG 설정에서 접근 소스는 접속에 허용될 ip 대역을 의미합니다.

  - 웹 서비스를 접근할 8080 포트를 허용합니다.

  - 서버 ssh에 접근되는 22 포트를 허용합니다. (서버 접근은 myip로 하여 보안을 강화하는 게 좋습니다.)

 

 

9. 이제 생성된 서버에 접근해보도록 하겠습니다.

  ssh에 접근에 많이 사용되는 tool인 putty를 이용해 보도록 하겠습니다.

  ncp에 새로 생성된 서버를 클릭해 보시면 포트 포워딩 정보에 서버 접속용 공인 ip와 외부 포트가 있습니다.

  해당 정보를 아래 위치에 작성하고 Open!

  [MacOS putty 참고 블로그]

   - https://velog.io/@wlgus2134/MAC-PUTTY-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0

 

putty

10. 리눅스 관리자 계정은 root이고, password는 위에서 입력한 관리자 비밀번호로 접속이 가능합니다!

 

 

NCP 클라우드 플랫폼을 이용해서 아주 간편하게 Web Server를 구동시킬 수 있는 서버 한 대가 생성되었습니다!

공인 ip를 발급받아야지 저희가 구동시킨 Web Server에 접근할 수 있습니다.

다음 Step에서 Application를 개발하고 진행하도록 하겠습니다.

 

 

728x90
반응형
반응형

로컬에서 정상적으로 작동하는 기능이 리눅스 서버에 배포하니 500 에러가 발생하였다.

에러를 확인하니 아래와 같이 출력되고 있었다..

 

Error resolving template [/index], template might not exist or might not be accessible by any of the configured Template Resolvers

 

Controller에서 return하는 html 파일을 찾을 때 발생하는 문제였다.

"/index"가 문제 발생 원인이다.

 

    @GetMapping("/test")
    public String test( Model model) {
        return "/index"; // 에러 발생
    }

 

/ 를 제거하면 리눅스에서도 정상 작동한다.

 

    @GetMapping("/test")
    public String test( Model model) {
        return "index"; // 정상 작동
    }

 

구글링해서 문제를 해결하였지만, 충분히 에러코드를 읽었으면 쉽게 해결할 문제였던 것 같다.

항상 에러 코드를 상세히 잘 읽어보자..

728x90
반응형
반응형

토이 프로젝트 소스코드를 반영하려고 git push를 하였는데, 빌드가 실패해서 Jenkins에 접속해 보니 아래와 같이 인증 실패 메시지가 출력되고 있었다.

github 계정 password를 수정한 적이 없었는데..

 

 

github에 접속해서 Developer Settings에 들어가 보니 Personal access tokens에서 문제를 확인할 수 있었다..

원인은 토큰 기한이 만료된 것..

 

 

토큰 기한을 연장할 수 있다. Expired on Sat, 클릭 후 추가 연장할 기한을 선택 후 Regenerate token 클릭!

 

 

새로 갱신된 토큰을 저장해서 다시 Jenkins에 등록하면 문제 해결~

Username : github ID

Password : 갱신된 토큰

ID : Jenkins에서 사용될 ID (중복 안됨)

Description : ID 설명

 

728x90
반응형

'Jenkins' 카테고리의 다른 글

[Jenkins] github Webhooks 설정  (0) 2022.11.26
반응형

개발하다 보면 html 파일을 수정할 때마다 서버를 재시작하는 일은 매우 번거롭다.

개발 생산성을 높이기 위해서 Spring Boot에서는 Spring Boot Devtools 모듈을 제공하여 개발 시 유용한 기능들을 제공한다.

Intellij에서 Spring Boot Devtools 의존성을 추가하였지만, 소스코드가 바로 적용이 안되시는 분들을 한 번 따라 해보면 좋을 것 같다.

 

대표적인 기능

  - Automatic Restart : classpath에 있는 파일이 변경될 때마다 감지하여 애플리케이션을 자동으로 재시작해준다.

  - Live Reload : 정적 자원(html, css, js) 수정 시 새로고침 없이 바로 적용할 수 있다.

  - Property Defaults : Thymeleaf는 기본적으로 성능을 향샹시키기 위해서 캐싱 기능을 사용한다. 이 캐싱 기능을 false 값으로 설정하여 수정한 소스가 바로 반영되어지도록 적용할 수 있다.

 

세팅 환경

  - IntelliJ IDEA 2021.3.1 (Ultimate Edition)

  - SpringBoot 2.6.6 

  - gradle

 

Spring Boot Devtools 적용

1. build.gradle에 dependencies 추가

 

developmentOnly 'org.springframework.boot:spring-boot-devtools'

 

2. Preferences > Build, Execution, Deployment > Compiler > Build project automatically 체크

 

 

2. Preferences > Advanced Settings > Compiler > Allow auto-make to start even if developed ... 체크

 

 

3. Edit Configurations...

 

 

4. Modify options

 

 

5. On 'Update' action > Update classes and resources 체크

 

 

6. On frame deactivation > Update classes and resources 체크

 

 

7.  Modify options 확인

 

 

* 설정을 하나씩 추가해 보며 소스코드가 적용이 되는지 확인해 보면 좋을 것 같다. 

  나 같은 경우 브라우저 새로고침을 2번 해야지 html 소스코드가 적용이 되었는데 6번(프레임 비활성 시 클래스 및 리소스 업데이트를 체크)을 적용했더니 새로고침 한 번에 바로 적용이 되었다.

728x90
반응형
반응형

프로토타입 패턴(Prototype Pattern)

  - 프로토타입 패턴은 생성패턴(Creational Pattern) 중 하나이다.
  - 생성 패턴은 인스턴스를 만드는 절차를 추상화하는 패턴이다.
  - 생성 패턴에 속하는 패턴들은 객체를 생성, 합성하는 방법이나 객체의 표현방법을 시스템과 분리해준다.

  - 기존 인스턴스를 복제하여 새로운 인스턴스를 만드는 방법이다.

  - 프로토타입 패턴은 원형이 되는 인스턴스를 사용해 새롭게 생성할 객체의 종류를 명시하여 새로운 객체가 생성될 시점에 인스턴스의 타입이 결정되도록 하는 패턴입니다

  - 생성하고자 하는 객체의 클래스에서 Cloneable의 clone() 메서드를 재정의되어야 한다.

 

장점

  - 구현 클래스에 직접 연결하지 않고 객체를 복사할 수 있습니다.(새 인스턴스를 만드는 것보다 비용적인 면에서 효율적일 수 있다.)

  - 복잡한 객체를 만드는 과정을 숨길 수 있다.

  - 추상적인 타입을 리턴할 수 있다.

단점

  - 복제한 객체를 만드는 과정 자체가 복잡할 수 있다.(특히, 순환 참조가 있는 경우)

코드

 - Mountain.class

package com.bumblebee.designpattern.creational.prototype;

import java.util.ArrayList;
import java.util.List;

public class Mountain implements Cloneable{

    private List<String> mountainList;

    public Mountain() {
        this.mountainList = new ArrayList<>();
    }

    public Mountain(List<String> mountainList) {
        this.mountainList = mountainList;
    }

    public List<String> getMountainList() {
        return mountainList;
    }

    public void mountainListAll() {
        this.mountainList.add("구룡산(306M)");
        this.mountainList.add("북악산(342M)");
        this.mountainList.add("아차산(295M)");
        this.mountainList.add("응봉산(95M)");
        this.mountainList.add("서대문 안산(295M)");
        this.mountainList.add("용마산(348M)");
        this.mountainList.add("인왕산(339M)");
        this.mountainList.add("남산(279M)");
        this.mountainList.add("불암산(509M)");
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
    	//return super.clone(); 얕은 복사(shallow copy)
        return new Mountain(new ArrayList<>(this.mountainList)); //깊은 복사(Deep Copy)
    }
}

 

  - MountainTest.class

  - Cloneable 인터페이스를 구현하여 Mountain 클래스를 생성하였고 clone() 메소드를 통해 깊은 복사 방식으로 인스턴스를 복제 하였습니다. java에서는 기본으로 얕은 복사를 제공한다.

package com.bumblebee.designpattern.creational.prototype;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MountainTest {

    @Test
    void prototypePattern() throws CloneNotSupportedException {

        Mountain mountain = new Mountain();
        mountain.mountainListAll();

        Mountain seoulMountain = (Mountain) mountain.clone();
        Mountain seoulMountain2 = (Mountain) mountain.clone();
        List<String> mountainList = seoulMountain.getMountainList();
        List<String> mountainList2 = seoulMountain2.getMountainList();

        mountainList.add("관악산(632M)");
        mountainList2.remove("북악산(342M)");

        System.out.println(mountain.getMountainList());
        System.out.println(mountainList);
        System.out.println(mountainList2);

    }

}

 

  - 결과

 

정리

 - DB에 접근해서 데이터를 핸들링하는 비용이 크므로 매번 DB에 접근이 필요하지 않는 데이터라면 프로토타입 패턴을 이용해서 객체를 복사해서 사용하는 방법이 유용할 것 같다.

728x90
반응형
반응형

1. h2 Database Engine 다운로드

download에서 본인의 운영체제에 맞게 다운로드

h2 download url

- https://www.h2database.com/html/main.html

 

H2 Database Engine

H2 Database Engine Welcome to H2, the Java SQL database. The main features of H2 are: Very fast, open source, JDBC API Embedded and server modes; in-memory databases Browser based Console application Small footprint: around 2.5 MB jar file size     Supp

www.h2database.com

 

2. SpringBoot 프로젝트 생성 후 yml 파일 작성

spring:
  # DB 연결
  datasource:
    # 설치된 H2 DB와 연결 URL
    url: jdbc:h2:file:./db/H2/data;AUTO_SERVER=true
    # 접속을 위한 드라이버
    driver-class-name: org.h2.Driver
    # springboot 2.4 부터는 username이 꼭 있어야합니다. 없으면 에러가 발생합니다.
    username: sa
    password:
  • jdbc:h2:file : file로 DB를 관리하겠다는 뜻
  • ./db/H2/data : 현재 설정된 경로에 data 라는 이름으로 데이터베이스 파일이 생성된다.  
  • AUTO_SERVER : 다중 접속을 허용하겠다는 의미

 

3. 프로젝트 실행

 

Menu Entity 생성

@Entity
public class Menu {

    @Id
    @GeneratedValue
    private Long id;

    private String menuName;

    private String menuType;



}

 

MenuType Entity 생성

@Entity
public class MenuType {

    @Id
    @GeneratedValue
    private Long id;

    private String typeSeq;

    private String typeName;

}

 

yml 설정에 맞게 생성된 DB file 확인

 

 

4. h2 console 실행

터미널에서 1번에서 다운로드 받은 h2 파일 아래에 bin 파일로 이동 후 ./h2.sh 실행 (mac os 기준)

JDBC URL에 해당 프로젝트 경로에 h2 db 위치를 작성 후 AUTO_SERVE 설정을 넣어준다

ex) jdbc:h2:file:/Users/Desktop/DailySpecial/db/H2/data;AUTO_SERVER=true

 

 

5. 생성된 테이블  확인

 

 

** db file 경로 지정시 h2 console 같은 경우 사용자 디렉터리에서 부터 찾아야 한다.

사용자 디렉터리 경로 파일 접근 같은 경우

h2 console

ex) jdbc:h2:~/testdb

 

yml

ex)

url: jdbc:h2:tcp://localhost/~/testdb

 

728x90
반응형
반응형

코드를 점진적으로 개선하기

 

목차

1. 책의 예제

2. 점진적으로 개선하기

3. IDE를 활용해 점진적으로 개선하기


1. 책의 예제

명령형 인수 구문 분석기

코드 초안

  - 모든 로직이 하나의 클래스에 들어가있다.

  - 처음부터 지저분한 코드를 짜려는 생각은 없었고, 코드를 어느정도 손봤지만 새로운 인수 유형이 들어오면서 재양이 시작됐다.

  - 이제는 개선해야 할 때라는 걸 깨닫고, 변경 전후 시스템이 동일하게 돌아간다는 사실을 확인하기 위해 테스트들을 작성해뒀다.

  - 자잘하게 점진적으로 개선해나갔다.

 

코드 완성본

  - Args 클래스에서 코드 중복을 최소화하고, ArgsException 클래스를 분리했다. ArgumentMarshaler 클래스를 통해 여러 인수에 대한 추후 확장성을 만들어냈다.

  - 코드만 분리해도 설계가 좋아진다. 관심사를 분리하면 코드를 이해하고 보수하기 훨씬 더 쉬워진다.

 

2. 점진적으로 개선하기

1. 코드가 나빠지고 있음을 느꼈을 때 기능을 추가하지 않고 개선을 시작한다.

2. 변경을 가한 후에도 시스템이 변경 전과 똑같이 돌아가야 한다. 테스트 코드가 없다면 작성하고, 코드를 수정하기 전 상태에서 모든 테스트가 통과해야 한다.

3. 책임에 따라 클래스를 나누고, 코드를 옮긴다. 테스트가 깨지지 않도록 확인하며 자잘한 변경을 조금씩 진행한다.

"프로그램을 망치는 가장 좋은 방법 중 하나는 개선이라는 이름 아래 구조를 크게 뒤집는 행위다"

 

3. IDE를 활용해 점진적으로 개선하기

Intellij 

mac 기준(Window는 command = Ctrl, option = Alt)

 

메서드 추출 기능 :                                     command + option + m

메서드 파라미터를 추가하거나 변경 기능 :  command + f6

메서드나 변수 이름 변경 :                          Shift + f6

변수 추출 기능 :                                        command + option + v

특정 값을 멤버 변수로 설정하는 기능 :       command + option + f

특정 값을 상수로 추출 기능 :                     command + option + c

 

하위 클래스의 메서드를 상위로 올리거나, 상위 클래스의 메서드를 하위로 내릴수 있는 기능 : 

해당 메서드에서 마우스 오른쪽 클릭 후 

 

 

728x90
반응형

'Book > Clean Code' 카테고리의 다른 글

[Clean Code] Chapter 13  (0) 2022.03.31
[Clean Code] Chapter 12  (0) 2022.03.28
[Clean Code] Chapter 11  (0) 2022.03.27
[Clean Code] Chapter 10  (0) 2022.03.26
[Clean Code] Chapter 09  (0) 2022.03.21
반응형

동시성을 구현할 때 명실할 것들

 

목차

1. 동시성 프로그래밍이란

2. 동시성 프로그래밍이 필요한 이유

3. 안전한 동시성 프로그래밍 규칙

4. 동시성 테스트 방법


1. 동시성 프로그래밍이란

어플리케이션을 효율적으로 실행하기 위해 멀티코어를 온전히 활용하도록 구현하는 방식

 

클라이언트가 아닌 어플리케이션 관점에서 봐야한다.

  - 내 어플리케이션의 효율성을 높여야 한다.

  - 어플리케이션이 동작하는 머신의 환경이 효율적으로 돌아가도록 어플리케이션에 메모리 누수나 자원이 낭비되지 않도록 신경쓴다

 

 

2. 동시성 프로그래밍이 필요한 이유

동시성 프로그래밍의 미신과 오해

 

동시성은 항상 성능을 높여준다.(x)

동시성은 때로 성능을 높여준다.(o)

 

동시성을 구현해도 설계는 변하지 않는다.(x)

동시성을 구현하면 설계를 바꿔야 한다.(o)

 

Web나 EJB와 같은 컨테이너를 사용하면 동시성을 이해할 필요가 없다.(x)

컨테이너를 사용해도 동시성을 이해해야 한다.(o)

 

 

3. 안전한 동시성 프로그래밍 규칙

단일 책임 원칙(SRP) 설계

 * 동시성 관련 코드는 다른 코드와 분리하라

  - 동시성 코드는 독자적인 개발, 변경, 조율 주기가 있다.

  - 동시성 코드에는 독자적인 난관이 있다. 다른 코드에서 겪는 난관과 다르며 훨씬 어렵다.

  - 잘못 구현한 동시성 코드는 별의별 방식으로 실패한다.

  - 주변에 있는 다른 코드가 발목을 잡지 않더라도 동시성 하나만으로도 충분히 어렵다.

 

자료 범위를 제한하라

 * 공유 자료를 최대한 줄여라

  - 동시 수정 문제를 피하기 위해 객체를 사용하는 코드 내 임계영역을 synchronized 키워드로 보호하라

  - 보호할 임계영역을 빼먹거나, 모든 임계영역을 보호했는지 확인하느라 수고가 드므로 임계 영역의 수를 최소화 해야 한다.

 

자료 사본을 사용하라

 * 공유 자료를 줄이려면, 최대한 공유하지 않는 방법이 제일 좋다.

  - 객체를 복사해 읽기 전용으로 사용한다.

  - 각 스레드가 객체를 복사해 사용한 후 한 스레드가 해당 사본으로 결과를 가져온다.

  - 사본을 사용하는 방식으로 내부 잠금을 없애 수행 시간을 절약하는 것이 사본 생성과 가비지 컬렉션에 드는 부하를 상쇄할 가능성이 크다.

 

Thread는 가능한 독립적으로 구현하라

 * 다른 스레드와 자료를 공유하지 않는다.

  - 서블릿처럼 각 Thread는 클라이언트 요청 하나를 처리한다.

  - 모든 정보는 비공유 출처(client의 request)에서 가져오며 로컬 변수에 저장한다.

  - 각 서블릿은 마치 자신이 독자적인 시스템에서 동작하는 양 요청을 처리한다.

 

라이브러리를 이해하라

 * java.util.concurrent 패키지를 익혀라

  - Thread Safe한 컬렉션을 사용한다. (ConcurrentHashMap, AtomicLong)

  - 서로 무관한 작업을 수행할 때는 executor 프레임워크르르 사용한다.

  - 가능하다면 Thread가 Blocking되지 않는 방법을 사용한다.

 

동기화 하는 메서드 사이에 존재하는 의존성을 이해하라

 * 공유 객체 하나에는 메서드 하나만 사용하라

  - 클라이언트에서 잠금 - 클라이언트에서 첫 번째 메서드를 호출하기 전에 서버를 잠근다.

    마지막 메서드를 호출할 때까지 잠금을 유지한다.

  - 서버에서 잠금 - 서버에다 "서버를 잠그고 모든 메서드를 호출한 후 잠금을 해제하는" 메서드를 구현한다.

     클라이언트는 이 메서드를 호출하기만 하면 된다.

  - 연결(Adapter)서버 - 잠금을 수행하는 중간 단계를 생성한다.

     '서버에서 잠금'방식과 유사하지만 원래 서버는 변경하지 않는다.

 

4. 동시성 테스트 방법

동시성 코드를 테스트 해야 한다.

 * 테스트를 했다고 동시성 코드가 100% 올바르다고 증명하기는 불가능하다. 하지만 충분한 테스트는 위험을 낮춘다.

  - 문제를 노출하는 테스트 케이스를 작성하라

  - 프로그램의 설정과 시스템 설정과 부하를 바꿔가며 자주 돌려라

  - 테스트가 실패하면 원인을 추적하라

  - 다시 돌렸더니 통과한다는이유로 그냥 넘어가면 절대로 안된다.

 

코드에 보조 코드를 넣어 돌려라

 * 드물게 발생하는 오류를 자주 발생시키도록 보조 코드를 추가한다.

  - 코드에 wait(), sleep(), yield(), priority() 함수를 추가해 직접 구현한다.

  - 보조코드를 넣어주는 조구를 사용해 테스트한다.

     다양한 위치에 ThreadJigglePoint.jiggle()를 추가해 무작위로 sleep(), yield()가 호출되도록 한다.

  - 테스트 환경에서 보조 코드를 돌려본다.

 

동시성 코드를 실제 환경이나 테스트 환경에서 돌려본다

 * 다양한 요청과 상황에 동시성 코드가 정상적으로 동작하는지 확인한다.

  - 배포하기 전에 테스트 환경에서 충분히 오랜시간 검증한다.

  - 동시성 코드를 배포한 후에 모니터링을 통해 문제가 발생하는지 지켜본다.

728x90
반응형

'Book > Clean Code' 카테고리의 다른 글

[Clean Code] Chapter 14  (0) 2022.04.02
[Clean Code] Chapter 12  (0) 2022.03.28
[Clean Code] Chapter 11  (0) 2022.03.27
[Clean Code] Chapter 10  (0) 2022.03.26
[Clean Code] Chapter 09  (0) 2022.03.21

+ Recent posts