소스 코드를 기록하는 남자

SOLID - ISP ( 인터페이스 분리 원칙 ) 에 대하여

OOP

[객체지향 SW 설계의 원칙] ③ 인터페이스 분리의 원칙

 

[객체지향 SW 설계의 원칙] ③ 인터페이스 분리의 원칙

“사람은 다른 사람과 말을 할 때 듣는 사람의 경험에 맞추어 말해야만 한다. 예를 들어 목수와 이야기할 때는 목수가 사용하는 언어를 사용해야 한다.” - 플라톤의 파에톤(P...

zdnet.co.kr

좋은 내용이 있어 읽어보고 정리합니다. 단순한 개인 공부입니다. 잘못된 부분이 있으면 지적해주세요

 

인터페이스 분리 원칙?

ISP의 핵심은 '변화'가 핵심이 된다. 어떻게 변화할 것인지에 대해서 천천히 알아보자

다음과 같은 구조의 프로그램이 있다. 이 프로그램에서 제공하는 기능은 불법 결제 패턴에 해당하는 사용자 결제를 차단하고, 이를 담당자에게 메일로 리포팅하는 동작을 하게 된다.

 

하지만 여기서 추가적으로 SMS 리포팅 기능을 구현해야 하면 어떻게 될까?

 

아마도 CPRule에 메소드를 추가할 것인다. 그럼?

 

전혀 상관없는 클래스에게도 영향을 미치게 될 것이다. 이는 클래스의 재컴파일, 재배포 등과 같은 문제점을 야기한다.

 

이런 부분을 ISP를 통해서 해소할 수 있다. ISP 를 간단하게 정의하면 "클라이언트는 자기가 사용하지 않는 메소드에 의존 관계를 맺으면 안된다" 라는 것이다.

 

아직 한참 모자란 본인은 많은 부분에서 사용하지 않는 메소드가 있음에도 불구하고 의존 관계를 만들어서 사용했던 기억이 있다. 자 그럼 인터페이스를 사용해서 구조를 바꾸면 어떻게 될까?

 

CPRule 이라는 클래스의 응집도는 높히대, 자신이 사용하지 않는 메소드를 분리해서 사용할 수 있게 된다.

 

이러한 부분은 BlockTransaction, EmailReporting 클래스가 직접 CPRule 에 접근하지 않아도 CPRule이 제공하는 서비스를 이용할 수 있게 된 것이다.

 

전형적인 ISP 를 보자

 

A, B, C 세 개의 클라이언트가 Service 인터페이스에 의존 관계를 맺고 있다.

만약에 Service 인터페이스의 어느 하나가 바귄다면, 세 클라이언트 모두를 재 컴파일, 재배포하는 아주 귀찮은 상황이 발생한다. 하지만 이를 ? 아래와 같이 변경한다면

 

기존에 발생했던 변화의 확산이 일어나지 않는다.

 

로버트 C.마틴은 "클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다." 라고 했다.

이 뿐만 아니라 ISP를 이야기할 때 항상 인터페이스를 통한 메서드를 외부에 제공할 때는 최소한의 메서드만 제공하라는 것이다. 명심할 필요가 있다.

SOLID - SRP ( 단일 책임 원칙 ) 에 대하여

OOP

단일 책임 원칙 (SRP)

SRP (Single Responsibility Principle ) 이란..?

직역하면 단일 책임 원칙이다. 사실 직관적인 단어라 어려운 부분이 없다고 생각했다. 하지만 예시를 확인해 봤을때 이게 뭔 말인가? 했다. 그래서 가지고 있던 책 중에 클린 코드를 확인 해보았다.

단일 책임 원칙은 클래스나 모듈을 변경할 이유가 단 하나뿐이어야 한다.

 

아! 나는 기존에 정의된 하나의 클래스에 하나의 책임만을 가져야 된다는 것보다 이게 더 직관적으로 와닿았다.

Dashboard라는 클래스를 예시로 설명해보겠다.

 

public class Dashboard extends JFrame implements MetaData
{
    public Componet getLastFocusComp()
    public void setLastFocus(Component lastFocus)
    public int getMajorVersionNum()
    public int getMinorVersionNum()
    public int getBuildNum()
}

여기서 Dashboard의 역할은 두 개로 가정한다. 소프트웨어 버전 정보를 추적, Dashboard는 스윙 컴포넌트를 관리. 하지만 소프트웨어는 출시될때마다 버전 정보가 변경되며, 스윙 코드를 변경할 때마다 버전 번호가 달라진다. 자, 그럼 여기서 코드를 변경해야 하는 이유가 두 가지나 된다는 것이다.

 

따라서 이 코드에서 냄새를 제거해보자. 변경되는 이유를 찾았으니, 버전 정보를 다루는 메소드를 추출해서 새로운 클래스를 생성해보자. 여기서 버전 정보를 관리하는 메소드는 아래와 같다. 이를 Version 클래스로 만들어보자.

 

public class Version {
    public int getMajorVersionNum()
    public int getMinorVersionNum()
    public int getBuildNum()
}

이렇게 만들어진 Version 클래스는 다른 애플리케이션에서도 충분히 쉽게 사용될 것이다.

 

많은 주니어 개발자들은 깨끗하고 체계적인 소프트웨어보다 돌아가는 소프트웨어에 초점을 맞추는데, 사실 이건 비교하면 잘 정리된 여러 개의 수납장에 물건을 정리해서 사용할 것이냐? 큰 서랍장 하나에 모든 물건을 던져놓고 쓸 것이냐? 이다. 느껴지지 않는가? 냄새나는 코드의 제거는 중요하다.

마음의 정화를 가져오는 SRP, PEACE

SOLID - OCP ( 개방-폐쇄 원칙 ) 에 대하여

OOP

객체 지향에 대해서 본격적인 공부를 시작하면서 보게 된 포스팅이 매우 인상 깊어 글을 작성하게 되었다.

아래는 원본글이니, 객체 지향을 공부하기 시작한 사람이라면 꼭 볼만한 포스팅이라 생각한다.

 

[객체지향 SW 설계의 원칙] ① 개방-폐쇄 원칙

 

[객체지향 SW 설계의 원칙] ① 개방-폐쇄 원칙

소프트웨어 설계의 묘미는 개발자가 작업하는 시스템의 창조자 역할을 할 수 있다는 것이다. 실세계의 경우 좋은 세상을 만들기 위해 적절한 질서, 정책, 의식 등이 전제돼야 하...

zdnet.co.kr

개방-폐쇄 원칙

버틀란트 메이어는 개방-폐쇄 원칙을 다음과 같이 정의한다.

 

소프트웨어 구성 요소 ( 컴포넌트, 클래스, 모듈, 함수 ) 는 확장에 대해서는 개방되어야 하며, 변경에 대해서는 폐쇄되어야 한다. 이는 다시 말해 변경을 위한 비용은 가능한 줄이고 확장을 위한 비용은 가능한 극대화해야 한다는 의미다.

 

이를 달성하기 위해서는 변경되는 부분, 변경되지 않는 부분을 엄격하게 구분해야 한다. 구분을 통해서 변하는 것은 가능한 변하게 쉽게하고, 변하지 않는 것은 변하는 것에 영향을 받지 않도록 하는 것이다. 그리고 인터페이스를 변하는 것과 변하지 않는 것의 중간 지점에서 서로를 보호하는 중재자 역할을 해야된다.

 

따라서, 이를 통해서 얻을 수 있는 것은 객체 간의 관계를 단순화해 복잡도를 줄이고, 확장이나 변경에 의해 발생하는 충격을 줄일수 있다.

 

혹시 복잡한가?

 

그럼 좀 더 쉽게 로버트 C.마틴의 말을 인용해보겠다. "소프트웨어 엔티티는 확장에 대해서는 열려 있어야하고 , 변경에 대해서는 닫혀있어야 된다." 라는 말을 쉽게 풀어보면 "나는 확장될 수 있어야하며, 다른 사람이 변하더라도 나에게 영향을 끼치면 안된다". 좀 더 이해가 됐으면 좋겠다.

 

자, 위 포스팅에서는 중재자의 역할, OCP의 인터페이스 기능으로 하는 예로 24핀 표준 규격의 충전기를 든다. 공통된 규격의 충전기는 사용자가 충전기를 사용함에 있어서 신뢰할 수 있고, 충전기 제공자는 목적에 맞게 확장, 특화하여 차별화나 상품성을 높일 수 있다. 물론 지금은 USB-C type이 표준이라 볼 수 있겠다.

 

하나의 예를 더 들어보자.

 

스프링 입문을 위한 자바 객체 지향의 원리와 이해에 들어있는 예제를 보겠다..

 

위 [그림 1]을 보게 되면 운전자는 기존에 마티즈를 타다가 새로운 자동차 소나타를 구매했다. 차량 종류를 변경하자 기본에 마티즈에서 수동으로 하던 일을 자동으로 변경되었다. 단순히 스틱 차량에서 오토 차량으로 변경되었다고 해서 기존의 운전자의 역할이 변화되어야 되는가? 현실 세계에서 봤을때는 어느 정도 Yes 라는 대답은 하겠지만, 객체 지향에서는 아니다. OCP에 위반되기 때문이다. 그럼 어떻게 해야하는가?

 

 

다소 위 예제가 억지스럽다고 느낄 수 있지만, 그려려니 해주셨으면 한다.

[그림 2]와 같이 기존의 공통된 특성을 추출하여 클래스나, 인터페이스를 생성하면 운전자 클래스는 다양한 자동차가 생긴다 하더라도 운전자 클래스에는 영향을 끼치게 않게 된다. 또한 자동차 입장에서는 확장에는 개방되어 있다.

 

개방 폐쇄 원칙에 대해서 이 글을 보며 조금이라도 이해했다면? 대표적인 개방 폐쇄 원칙을 지킨 가장 큰 예제는 JDBC이다.

JDBC를 사용하는 클라이언트는 데이터베이스가 오라클, MySQL, MariaDB 어떤 데이터베이스를 사용하더라도 Connection을 설정하는 부분을 제외하고는 모두 동일하게 사용 가능하다.

 

자신의 코드는 수정할 필요가 없이 변화에 대해서는 닫혀있으며, 다양한 데이터베이스 연결에 대해서는 확장에 열려있다고

볼 수 있다. 이러한 개방 폐쇄 원칙을 잘 지킴으로써 완충 역할을 하고 있는 것이다.

OCP 주의점

여기서 3가지 주의점에 대해서 언급한다. 아직 주니어 개발자라 격하게 공감하지 못하지만 명언처럼 마음에 담아두게 되었다.

  1. 공통 모듈 설계

    • 공통된 루틴이나 변수를 리팩토링하여 분리를 하게 되었을 때, 공통 모듈이 작을 경우 공통 모듈 재사용을 얻기 위해 너무 잦은 모듈을 접근해야 하고 모듈 구성도를 지저분하게 할 경향이 높다. 설계자의 좋은 자질 중 하나는 OCP에서 확장되는 것과 변경되지 않는 모듈을 분리하는 과정에서 크기 조절을 잘 할 수 있는 결단력이라는 것이다.

  2. 확장을 보장하는 Open 모듈에서 인터페이스의 변경인가, 어댑터 사용인가

    • 확장을 보장하는 open 모듈 영역에서 예측하지 못한 확장 타입을 만났을 때 인터페이스 변경하려는 안과 어댑터를 사용하려는 안 사이에서 갈등하게 된다. 위의 두 예에서처럼 변경의 충격이 적은 후자를 택하는 경우가 대부분이다. 한 번 정해진 인터페이스는 시간이 갈수록 사용하는 모듈이 많아지기 때문에 바꾸는데 엄청난 출혈을 각오해야 한다. 그 대표적인 예가 자바의 deprecated API라 한다.

      인터페이스는 가능하면 변경하면 안 되며, 이를 달성하기 위해서는 여러 경우의 수에 대한 고려와 예측이 필요하다. 과도한 예측은 불필요한 작업을 만들기에, 설계자의 적절한 예측 능력이 필요하다.

  3. 커맨드의 역할

    • 요청자와 처리자 사이의 계약을 커맨드라 지칭하고 있다. 여기서 처리자는 execute()란 인터페이스만 알면 어떠너 처리도 수행할 수 있다. 따라서 서로 의미적 관계가 없는 Command들도 execute()란 메소드로 무엇이든 확장할 수 있다. OCP 구조에서 서버가 확장할 수 있는 운신의 폭이 넓어진 반면 클라이언트는 서버가 어떤 처리를 하는지 무지해진다.

      즉, 인터페이스 설계에서 적당한 추상화 레벨을 선택하는 것이 중요하다. 추상화라는 개념에 '구체적이지 않은' 정도의 의미로 약간 느슨한 개념을 갖고 있다.

      그래디 부치가 말하는 추상화는 '추상화란 다른 모든 종류의 객체로부터 식별될 수 있는 객체의 본질적인 특징' 이라고 한다. 따라서 이 '행위'에 대한 본질적인 정의를 통해 인터페이스를 식별해야 한다.

      포스팅에서 유일하게 이해되지 않는 부분은 '행위' 라는 부분이다. 혹여라도 지나가시던 객체 지향 고수분이 있으시다면 댓글을 큰 해소점이 될 것 같다.

백준12865번 : 평범한 배낭

Algorithm/백준

백준12865번 : 평범한 배낭

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class 백준12865_평범한배낭 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static StringTokenizer st = null;

    public static void main(String[] args) throws IOException{
        int n, k;
        int weight, value;
        int[][] backpack;
        ArrayList<Stuff> stuffs = new ArrayList<>();

        st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());
        backpack = new int[n + 1][k + 1];

        for (int i = 0; i < n; i++)
        {
            st = new StringTokenizer(br.readLine());
            weight = Integer.parseInt(st.nextToken());
            value = Integer.parseInt(st.nextToken());
            stuffs.add(new Stuff(weight, value));
        }
        Collections.sort(stuffs);

        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= k; j++)
            {
                Stuff t = stuffs.get(i - 1);
                if (t.weight > j)
                {
                    backpack[i][j] = backpack[i - 1][j];
                }
                else
                {
                    backpack[i][j] = Math.max(backpack[i - 1][j], t.value + backpack[i - 1][j - t.weight]);
                }
            }
        }
        System.out.println(backpack[n][k]);
    }

    public static class Stuff implements Comparable<Stuff>{
        int weight;
        int value;

        public Stuff(int weight, int value) {
            this.weight = weight;
            this.value = value;
        }

        @Override
        public int compareTo(Stuff o) {
            int cmp = Integer.compare(weight, o.weight);
            if (cmp == 0)
                return (Integer.compare(value, o.value));
            else
                return (cmp);
        }
    }
}

가장 기초 dp 문제며, knapsack problem 이라고 치면 많은 해설을 찾을 수 있다.

포인트는 다음과 같다.

물건 번호 물건 무게 물건 가치
1 3 6
2 4 8
3 5 12
4 6 13

주어진 물건들의 무게와 가치는 다음과 같다고 가정한다.

만약 가방의 무게가 7이라는 값으로 주어지게 되면 초기 값은 다음과 같다.

물건 번호 \ 가방 무게 0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 0
2 0
3 0
4 0

반복문으로 보게 된다면 1번행, 1번열부터 채우기 시작한다고 보면 된다.

점화식은 다음과 같다.

아래 점화식에서 사용할 stuff는 물건을 지칭하고, dp는 위 표를 가르킨다.

여기서 i는 행 ( 물건의 인덱스이자 표에서 행 )

여기서 j는 열 ( 가방의 무게이자, 표에서 열 )

i = 1, j = 1 부터 시작한다.

if stuff[i].무게 > j
  dp[i][j] = dp[i - 1][j];
else
  dp[i][j] = Math.max (dp[i - 1][j], stuff[i].가치 + dp[i - 1][j - stuff[i].무게])

설명보다 표의 값의 변화를 보는것이 이해가 빠를듯하다.

물건 번호 \ 가방 무게 0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 ( 무게 3 , 가치 6 ) 0 0 0 6 6 6 6 6
2 ( 무게 4, 가치 8 ) 0
3 ( 무게 5, 가치 12 ) 0
4 ( 무게 6, 가치 13 ) 0

i = 1, j = 1 일때, 위의 조건으로 비교해보면 1번 물건의 무게는 3 , 현재 가방 허용 무게는 j 즉 1이기때문에 if 문에서 true , 표의 (1, 1)은 (0, 1)의 값인 0

..... 쭉 가다가 j 가 3인 시점에 되면?

i = 1, j = 3 일때, 조건식 3 > 3 이 false가 되고 Math.max ( 0, 6 + 0 ) 이므로 6이 된다.

i = 2일때 보자.

물건 번호 \ 가방 무게 0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 ( 무게 3 , 가치 6 ) 0 0 0 6 6 6 6 6
2 ( 무게 4, 가치 8 ) 0 0 0 6 8 8 8 14
3 ( 무게 5, 가치 12 ) 0
4 ( 무게 6, 가치 13 ) 0

표에서 ( 2, 4 )를 봤을때 값이 8로 변한다. 단순하게 생각해서 가방 무게 제한까지 하나씩 증가시키면서 가장 높은 가치가 있는 물건을 넣는 행위를 끝까지 반복하는 것임.

AWS 데이터베이스 환경 세팅 ( AWS RDS )

AWS

웹 서비스의 백앤드 개발에서 애플리케이션 코드 개발만큼 중요한 것이 데이터베이스 핸들링입니다.

 

규모가 있는 회사에는 전문 DBA 라는 직군이 있기에 상대적으로 데이터베이스를 다룰 일이 적다하지만 

 

백앤드 개발자 또한 데이터베이스를 잘 이해하고 있어야 합니다.

 

따라서 어느정도의 데이터베이스 구축, 쿼리 튜닝에 대한 기본적인 지식이 필요합니다. 

 

직접 데이터베이스를 설치해서 다루게 되면 모니터링 , 알람, 백업, HA 구성 등을 모두 직접 해야하며,

 

처음 구축에 며칠이 걸릴 수도 있습니다.

 

따라서 AWS 앞에서 언급한 작업을 모두 지원하는 관리형 서비스인 RDS를 제공합니다.

 

많은 부분을 자동화하였기 때문에, 개발자가 개발에 집중할 수 있게 하며, 저량 용량 부족에 대한 부분을 단순 비용 지불로

 

해소할 수 있습니다.

 

RDS 생성

1. 서비스 찾기에서 RDS 검색합니다.

 

 

 

 

 

2. 데이터베이스 생성 클릭

 

 

 

 

 

 

 

3. MariaDB를 사용합니다. 옵션은 아래와 같이 선택해주세요

 

 

4. 설정 

임의의 DB 인스턴스 식별자와 마스터 사용자 이름 암호를 지정해주세요

5. 스토리지

실습 용도로 사용하기에 할당 스토리지 크기는 20으로 지정합니다. 그리고 스토리지 자동 조정은 비활성화합니다.

6. 연결

퍼블릭 액세스 가능을 예로 변경합니다. 추후 보안 그룹에서 지정된 IP 만 접근 가능하도록 막겠습니다.

7. 추가 구성

추가 구성에서 초기 데이터베이스 이름만 지정하고 파라미터 옵션은 기본값으로 설정한 후 생성합니다.

 

8. 생성 이후 파라미터 설정

 

 

 

데이터베이스 생성 이후 왼편의 카테고리에서 파라미터 그룹으로 이동합니다.

 

이동한 다음에 우측 상단에 있는 파라미터 그룹 생성 버튼을 클릭합니다.

 

 

 

 

 

 

 

 

 

 

9. 파라미터 생성

파라미터 그룹 세부 정보에서 파라미터 그룹 패밀리라는 항목이 있는데 이 항목은 생성할 때 선택한 DB 버전 정보와 일치시켜 줘야 합니다.

 

저는 maria 10.4.8 버전을 선택했기 때문에 10.4 를 선택해주겠습니다.

 

혹여 등록할 때 선택한 버전이 기억나지 않는다면 

데이터베이스 -> 구성 -> 엔진 버전 으로 가시면 선택한 DB 버전을 확인할 수 있습니다.

 

 

 

 

 

10. 파라미터 편집

생성된 파라미터를 클릭하고 우측 상단을 보면 파라미터 편집이 있습니다.

 

클릭해줍니다.

 

우선 time_zone을 수정하겠습니다.  Asia/Seoul 로 변경해주세요.

 

다음으로 Character Set 을 변경하겠습니다.

 

아래 항목에서

character_set_client

character_set_connection

character_set_database

character_set_filesystem

character_set_results

character_set_server

collation_connection

collation_server

 

character 그룹은 모두 utf8mb4로 변경합니다.

collation 그룹은 모두 utf8mb4_general_ci로 변경합니다.

 

utf8과 utf8mb4의 차이는 이모지 저장 가능 여부입니다.

 

다음은 max_connections 수정입니다.

 

프리티어 사양으로는 60개의 커넥션만 가능합니다. 좀 더 넉넉하게 150으로 변경합니다.

 

혹여나 추후에 RDS 사양을 높이게 되면, 기본값으로 변경해주시면 됩니다.

 

값을 수정하고 변경 사항을 저장해줍니다.

 

11. 생성한 파라미터 그룹을 데이터베이스에 연결

 

데이터베이스 카테고리에 들어가서 인스턴스 체크 이후 수정을 클릭합니다. 

로딩창에서 수정 목록이 뜰때까지 기다려줍니다.

 

이후 추가 구성 목록에서 DB 파라미터 그룹을 생성한 파라미터로 변경해줍니다.

 

 

수정 이후 적용을 해줍니다. 한번씩 파라미터 값이 제대로 적용되지 않을수 있으니 수정 완료 이후에 데이터베이스 카테고리에서 우측 상단 탭의 작업 -> 재부팅을 진행해줍니다.

 

그럼 RDS 인스턴스 생성을 마치겠습니다.

'AWS' 카테고리의 다른 글

아마존 리눅스 서버 생성 시 꼭 해야 될 설정  (0) 2020.11.23

아마존 리눅스 서버 생성 시 꼭 해야 될 설정

AWS

자바 기반의 웹 애플리케이션으로 작동해야 하는 서버들은 필수적으로 해야될 설정이 있습니다.

 

  • Java 사용할 버전 설치
  • 타임존 변경
  • 호스트네임 변경

저는 실습과정에서 aws linux ami1를 선택해서 진행해야 했었는데 aws에서 더 지원하지 않는지, 목록에 존재하지 않았습니다.

따라서 aws linux ami2 를 선택하여 진행했고, 접속하여 확인해보니 Java 가 설치되지 않았습니다. 

 

기본적으로 서버의 시간은 미국 시간대입니다. 따라서 한국의 시간대로 변경해야 합니다.

 

호스트네임은 실무에 간다면, 수십대의 서버가 동작하기에 IP주소로 구분하는 것은 어렵습니다. 따라서 호스트네임을 필수로 등록해야 합니다.

 

Java Install

sudo yum install -y java-1.8.0-openjdk-devel.x86_64

 

위 명령어를 입력하면 Java 8 version 이 설치가 됩니다.

 

혹시 이전에 설치된 버전이 있다면 아래 명령어를 입력한 다음 사용할 버전을 선택해주시면 됩니다.

 

sudo /usr/sbin/alternatives --config java

 

서버에 사용하지 않는 버전이 존재한다면 아래 명령어를 입력하여 제거해주세요

 

sudo yum remove java-version-openjdk

 

version은 제거할 버전이 1.7.0 인 경우에 version 대신 1.7.0을 입력해주시면 됩니다.

 

타임존 변경

EC2 서버의 기본 타임존은 UTC이며, 한국과 9시간 차이가 발생합니다.

현재 서버의 타임존은 date 명령어로 확인할 수 있습니다. AWS의 EC2의 기본 로컬타임은 UTC로 설정이 됩니다.

 

따라서 Seoul 시간대로 변경해보겠습니다.

 

sudo rm /etc/localtime

sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

두 명령어를 입력하고 date 명령어로 확인했을 때 시간대가 일치하면 정상적으로 변경된 것입니다.

 

Hostname 변경

명령어를 실행하여 정규화된 이름을 입력해야 합니다.

 

sudo hostnamectl set-hostname webserver.mydomain.com

 

빨간 부분을 원하는 이름으로 변경하고 명령어를 입력합니다.

 

이렇게 다 해주시고 난 뒤에 재부팅 후 호스트 네임을 확인해보십시요.

위와 같이 변경했다면 webserver 까지만 보입니다.

 

sudo reboot

 

리루팅하시면 일정 시간 이후에 재부팅이 됩니다. 따라서 기다리셨다가 접속해보세요

 

/etc/hosts 에 변경된 hostname 등록

호스트 주소를 찾을 때 가장 먼저 검색해 보는 /etc/hosts 에 변경한 hostname 을 등록해야 합니다.

추후에 hostname을 등록하지 않음으로 발생하는 장애가 존재할 수 있기에 사전에 해소합시다.

 

sudo vim /etc/hosts

hostname에 이전에 변경한 이름을 등록해주고 저장합니다.

 

등록하고 나서

 

curl 등록한 호스트 이름

 

으로 조회했을 때 잘 못 등록했다면 Could not resolve host 에러가 발생하고

 

올바르게 등록된 경우는 Failed to connect to 에러가 발생합니다. 이는 아직 80 port 접근이 안된다는 것임으로 호스트 네임 등록이 잘 되었다는 의미입니다.

'AWS' 카테고리의 다른 글

AWS 데이터베이스 환경 세팅 ( AWS RDS )  (0) 2020.11.23

[OS] Scheduler 알고리즘

Computer Science/OS

긴 포스팅은 머릿속에 들어오지 않습니다. 짧고 굵게 갑니다.

 

스케줄링 알고리즘은 크게 2 분류가 있습니다.

 

비선점, 선점

 

비선점

비선점 (Non-preemptive)

      :   프로세스가 CPU에 할당되면 그 프로세스가 종료되거나 대기 중 상태로 전환될 때까지 CPU를 점유

 

대표적인 알고리즘 : FCFS, SJF

장점 단점
1. 모든 프로세스에 대해 공정한 처리가 가능하다.
2. 프로세스 간의 오버헤드가 적다
3. 응답시간의 예측이 편하며, 일괄 처리 방식에 적합하다.
1. 긴 작업이 짧은 작업을 오래동안 기다리게 만드는 경우가 생긴다.
2. 중요 작업을 먼저 처리할 수 없다.

 

선점

선점 (Preemptive)

     : 어떤 조건이 만족되면 현재 실행 중인 프로세스의 의사와 상관없이 그것의 실행을 중단하고 다른 프로세스를 CPU에 할당

 

대표적인 알고리즘 : SRTF, RR, Priority Scheduling, Multi-level Scheduling

장점 단점
1. 높은 우선 순위를 가지는 프로세스들을 빠르게 처리할 수 있다.
2. 빠른 응답 시간을 요구하는 시스템에 용이하다.
1. 프로세스 간의 Context Switch가 자주 발생한다.
2. 우선순위가 낮은 프로세스는 starvation 현상을 겪게 된다.

Nagle Algorithm 이란 무엇인가?

Computer Science/Network

시작하기에 앞서서 제가 공부하면서 이해한 내용을 정리하는 부분이라 정확하지 않을 수도 있다는 점 인지해주셨으면 감사하겠습니다.

 

 

Nagle's algorithm is a means of improving the efficiency of TCP/IP networks by reducing the number of packets that need to be sent over the network. It was defined by John Nagle while working for Ford Aerospace. It was published in 1984 as a Request for Comments (RFC) with title Congestion Control in IP/TCP Internetworks

위키피디아의 정의를 보면 다음과 같이 정의되어 있다.

네이글's 알고리즘은 네트워크로 전송해야할 패킷을 수를 줄임으로 TCP/IP 네트워크의 효율성을 증가시킨다.

Ford Aerospace에서 근무하던 John Nagle이 정의하였으며, 1984년 RFC (IP/TCP internetwork에서 혼잡 제어)로 발표되었다.

 

 

 

Nagle 알고리즘으로 사용할 이점은 ?

  1. 패킷을 전송할 때는 전송하고자 하는 패킷의 크기와 상관없이 항상 고정적인 비용이 필요하다 (TCP에서는 40byte header). 따라서 한 번의 전송에 많은 데이터를 보내는 것은 전송 비용을 줄 일 수 있다.
  2. 여러 번에 보내던 패킷을 한 번에 보내면 얻는 이점이 있다. 적은 양을 여러 차례 보내면서 생기는 대역폭의 낭비를 줄일 수 있다는 것
  3. 대역폭 낭비를 줄임으로써 잠재적으로 발생할 수 있는 congestion collapse를 방지할 수 있다는 점.
MSS ( Maximum segment size )

if 전송할 데이터가 있으면 then
	if 윈도우 사이즈 >= MSS and 가능한 데이터 크기 >= MSS then
    	완전한 MSS segment 전송
    else
    	if 파이프에 미확인된 data가 여전히 존재 then
        	ack 가 수신될때까지 buffer에 data enqueue
        else
        	즉시 data 전송
        end if
    end if
end if

 

이 알고리즘을 사용함에 있어 문제점이 존재

  1. 다량의 write에 부정적인 영향을 준다.
  2. 실시간 시스템과의 상호 작용이 좋지 않음

larger write에서 부정적인 영향을 주는 이유는, 어떤 request-response 어플리케이션 프로토콜에서 request data는 하나의 패킷보다 클 수 있는데, 이는 임의적으로 few hundred milliseconds의 지연을 발생시킬 수 있음