> su
Password:
su: Sorry

 

su: Sorry 라고 나오며, 루트 사용자(su)로 실행되지 않는다.

이는 비밀번호 초기 설정이 안되어있어 나오는 것이다.

 

> sudo -s

 

입력하여 (경고는 엔터키를 눌러 무시해도 된다.), bash 쉘에 접속하고 > passwd root 명령어를 통해 root 비밀번호를 설정해준다.

앞으로 su 명령어를 실행할 때, 설정한 비밀번호을 사용한다.

 


참고 사이트

pragp.tistory

NodeJS + MongoDB 데이터 다루기

# npm 설치
npm install mongoose

 

const mongoose = require("mongoose");

mongoose.connect("mongodb://127.0.0.1:27017/databaseName"); // database name: project

// 아래 db 코드는 확인할 때 사용한다. 코드 생략 가능
const db = mongoose.connection;
db.on("open", function () {
  console.log("Connected");
});
db.on("error", function () {
  console.log("Connection Failed!");
});

/**
 * 최초 데이터 1건을 조회한다. (가장 오래된 데이터)
 * @param {mongoose.Schema} schema
 * @param {object} filter
 * @returns
 */
const FindFirst = async (schema, filter) => {
  return await schema
    .findOne(filter)
    .then((response) => response)
    .catch((error) => error);
};

/**
 * 데이터를 저장한다.
 * @param {mongoose.Schema} schema
 * @param {object[]} data
 */
const Save = (schema, data) => {
  for (value in data) {
    new schema(data[value])
      .save()
      .then((response) => response)
      .catch((error) => error);
  }
};
/**
 * 데이터를 조회하고, 최신순으로 조회한다.
 * @param {mongoose.Schema} schema
 * @param {object} filter
 * @param {number} limit
 * @returns
 */
const Find = async (schema, filter = undefined, limit = undefined) => {
  return await schema
    .find(filter)
    .sort({ _id: -1 })
    .limit(limit)
    .then((response) => response)
    .catch((error) => error);
};

/**
 * 데이터를 삭제한다.
 * @param {mongoose.Schema} schema
 * @param {object[]} data
 * @returns { acknowledged: boolean, deletedCount: number }
 */
const Delete = async (schema, filter = undefined) => {
  return await schema.deleteMany(filter)
    .then((response) => response)
    .catch((error) => error);
};

// mongoose 조회 함수 호출하기
( async () => {
  const returnDelete = await Delete(Ticker);
  console.log(returnDelete.deletedCount);
}) ();

 

Schema.js

const mongoose = require("mongoose");
const { Schema } = mongoose;

const ticker = new Schema({
  name: string
});

const Ticker = mongoose.model("tickers", ticker);

module.exports = {
  Ticker,
};

 


Reference Site

mongoose guide

 

Mongoose v6.6.0: Schemas

If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. If you are migrating from 5.x to 6.x please take a moment to read the migration guide. Everything in Mongoose starts with a Schema. Each schema ma

mongoosejs.com

 

토이 프로젝트 진행하면서 OpenAPI를 사용하는데, 요청 수 제한이 있어, 클라이언트에서 많은 요청들을 계속하여 호출하는데 무리가 있었다. (429 Too Many Requests)

백엔드 서버에서 스케줄링을 통해 데이터베이스에 API 정보를 저장한다면, 문제를 해결할 수 있을 것 같았다.

OpenAPI를 사용하다보니 RDBMS로는 데이터 정보 구조를 정의하고 관리하기에는 무리가 있을 것 같아, 비정형화 데이터를 저장할 수 있는 NoSQL을 사용하기로 했다.

오래전에 Firebase(Only 클라우드 서비스, 비용 발생 가능성)를 통해 NoSQL을 접해본 적은 있지만, 가장 많이 사용하는 NoSQL인MongoDB를 접해보고 싶었고, 환경을 직접 구축(On-premise)해보는 경험을 해보기로 했다.


NoSQL 이란?

  • non SQL, non relational SQL, not only SQL 와 같은 의미로 해석된다. SQL을 사용하지 않는다는 의미보다 SQL만을 사용하지 않는 데이터베이스 관리 시스템(DBMS)이다.
  • NoSQL에 대한 구체적인 정의는 없지만, 공통적인 성향이 있다.
    • 대부분 클러스터(하나의 클러스터에서 여러개의 서버를 이용하도록 설계)에서 실행할 목적으로 만들어졌기 때문에 관계형 모델을 사용하지 않는다
      • 분산 환경에서 노드(서버)들이 잘 작동할 때, 하나의 노드 시스템에 장애가 났을 때, 문제를 해결하기 좋다.
    • Schema-less, 스키마(구조에 대한 정의) 없이 동작한다. 따라서 데이터 구조를 미리 정의할 필요가 없으며, 시간이 지나더라도 언제든지 바꿀 수 있기 때문에 비형식적인 데이터를 저장하는 데 용이하다.
    • 비일관성(Inconsistency), 게임의 로그 같은 데이터들은 매 초마다 엄청난 양이 생성되지만 한번 저장되고 난 뒤에는 수정될 일이 거의 없다. 이런 데이터의 일관성을 보장하기 위해 ACID 트랜잭션을 지원할 필요는 없다.
      • 다수가 동시에 읽고 쓰는 (Read and Write) 상황에 좋다.
  • 데이터와 트래픽이 증가함에 따라 RDBMS에서는 원활한 데이터 처리가 어려워졌다. 이를 해결하기 위해 장비의 성능을 키우는 수직적 확장(Scale-up)은 비용적인 문제가 발생한다. NoSQL에서는 수평적 확장(Scale-out)을 통해 성능을 올리기 쉽다.

 MongoDB 란?

  • NoSQL DBMS의 한 종류이고, Document 모델을 사용한다.
  • mongo는 humongous를 줄인 표현이다. '겁나 큰 DB' 라는 뜻.

장점

  • Schema-less 구조로 다양한 형태의 데이터 저장이 가능하고, 데이터 모델의 유연한 변화가 가능하다.
  • Read/Write 성능이 뛰어나다.
  • 수평적 확장(Scale-out) 구조로 많은 데이터 저장이 가능하고 장비 확장이 간단하다.
  • JSON 구조로 데이터를 직관적으로 이해 가능하다.

단점

  • 데이터 업데이트 중 장애 발생 시, 데이터 손실이 가능하다.
  • 많은 인덱스 사용 시, 충분한 메모리가 필요하다.
  • 데이터 공간 소모가 RDBMS에 비해 많다. (중복 key, 데이터 발생 가능)
  • ACID 트랜잭션 지원이 RDBMS 대비 미약하다.

1. 몽고디비 설치 명령어

brew tap mongodb/brew
brew install mongodb-community

설치 위치: /usr/local/var/mongodb

 

2. 서비스 명령어

# start
brew services start mongodb/brew/mongodb-community
mongod # deamon 프로세스로 실행. 백그라운드에서 실행

# stop
brew services stop mongodb/brew/mongodb-community

# 위 명령어로 실행하면서 오류가 계속 발생하였음
sudo su # 관리자 모드로 접속하여 아래 명령어를 통해 실행함
brew services # 서비스 확인
brew services start mongodb-community
brew services stop mongodb-community

brew services start mongodb/brew/mongodb-community
Default MongoDB Port: 27017

 

Install MongoDB Community Edition on macOS — MongoDB Manual

Docs Home → MongoDB Manual MongoDB AtlasMongoDB Atlas is a hosted MongoDB service option in the cloud which requires no installation overhead and offers a free tier to get started.Use this tutorial to install MongoDB 6.0 Community Edition on macOS using

www.mongodb.com

이후 mongo shell 접속하기 위해, mongo 명령어를 통해 접속하려 했지만 실패하였다.

MongoDB 문서를 참고하여, mongosh 명령어로 접속할 수 있었음

mongosh

 

3. MongoDB-Compass 설치

brew install cask
brew install mongodb-compass

 

4. Mongo Shell 명령어

db # 현재 사용중인 DB 확인

show dbs # DB 리스트 확인.  처음 db 명령어를 통해 확인한 DB를 확인할 수 없는데, 최소 1개의 Document 를 추가해야함

use <database name> # DB 접속

db.foo.insertOne({name:"foo"}) # 데이터 추가하기. collection은 foo로 추가, 명령어 맨 앞의 db의 현재 DB를 뜻함

db.foo.find() # 데이터 확인

show collections # collection 확인

# 1개의 데이터 추가
db.collection.insertOne({document}

# 여러 데이터 추가
db.collection.insertMany([{document1},{document2}...])

데이터 추가하기
데이터 확인
find 조건 검색

4. 데이터베이스, 계정 생성

# root 권한 계정 생성
use admin # admin DB 접속
db.createUser({ user:"sejin", pwd:"******", roles: ["root"] })

# root 계정으로 shell 진입
mongosh admin -u sejin -p ******

use project # 데이터베이스 생성(create), 전환(switched)
db.createUser({user:"user", pwd:"******", roles:["dbOwner"]}) # 일반 계정 생성

# 생성한 일반 계정 확인
db.getUsers()

 

 


 

NoSQL - 나무위키

“Not Only SQL” : 데이터를 저장하는 데에는 SQL 외에 다른 방법들도 있다. NoSQL이라고 하는 말은 대한민국이 아닌 모든 나라를 외국이라고 부르는 것과 비슷하다. 세상에는 한국 말고도 각자의 문

namu.wiki

 

[MongoDB] MongoDB 장점/단점

MongoDB 장점 Schema-less 구조 - 다양한 형태의 데이터 저장 가능 - 데이터 모델의 유연한 변화 가능(데이터 모델 변경, 필드 확장 용이) Read/Write 성능이 뛰어남 Scale Out 구조 - 많은 데이터 저장이

tychejin.tistory.com

 

Union-Find (유니온 파인드)란?

  • 그래프 알고리즘으로 합집합 알고리즘이다
  • 상호 배타적 집합(Disjoint-set)이라고도 한다.
    ※ Disjoint set: 서로 중복되지 않는 부분 집합들로 나눠진 원소들에대한 정보를 저장하고 조작하는 자료구조

Union-Find (유니온 파인드) 특징

  • 집합을 구현하는 데는 배열, 리스트 등을 이용할 수 있으나 그 중 가장 효율적인 트리 구조를 이용하여 구현
  • 두 노드가 서로 같은 그래프에 속하는지 판별하는 알고리즘

알고리즘 문제

백준 1976 여행가자

동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 N개 있고 임의의 두 도시 사이에 길이 있을 수도, 없을 수도 있다. 동혁이의 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인지 알아보자. 물론 중간에 다른 도시를 경유해서 여행을 할 수도 있다. 예를 들어 도시가 5개 있고, A-B, B-C, A-D, B-D, E-A의 길이 있고, 동혁이의 여행 계획이 E C B C D 라면 E-A-B-C-B-C-B-D라는 여행경로를 통해 목적을 달성할 수 있다.

도시들의 개수와 도시들 간의 연결 여부가 주어져 있고, 동혁이의 여행 계획에 속한 도시들이 순서대로 주어졌을 때 가능한지 여부를 판별하는 프로그램을 작성하시오. 같은 도시를 여러 번 방문하는 것도 가능하다.

문제 분석

각 도시들 간의 연결 여부와 여행 계획이 주어지고, 출발지에서 목적지까지 여행 가능 여부를 판별한다.
여행 계획에 포함된 도시들이 같은 그래프에 속해있는지 구한다.

 

    for (int i = 0; i < N; i++)
        parent[i] = i;

각 그래프의 root 노드를 저장하는 parent 배열을 선언하고, 초기 값은 자기 자신을 저장한다.

    static void union(int x, int y) {
        x = find(x);
        y = find(y);
        if (x > y)
            parent[x] = y;
        else
            parent[y] = x;
    }

연결되어 있는 두 노드를 union하여 같은 root를 공유하도록 최신화한다.
두 노드의 root 값 중 작은 값을 root로 저장한다.

    static int find(int x) {
        if (parent[x] == x)
            return x;
        return parent[x] = find(parent[x]);
    }

재귀 함수를 통해 그래프의 root 노드를 찾아 parent 값을 최신화하고, argument와 parent 값이 같을 경우, 루트 노드에 도달하였기 때문에 재귀를 중단한다.

풀이 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class Main {

    static int N, M;
    static int[][] map;
    static int[] parent;
    static String[] input;

    static int find(int x) {
        if (parent[x] == x)
            return x;
        return parent[x] = find(parent[x]);
    }

    static void union(int x, int y) {
        x = find(x);
        y = find(y);
        if (x > y)
            parent[x] = y;
        else
            parent[y] = x;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        M = Integer.parseInt(br.readLine());
        map = new int[N][N];
        parent = new int[N];

        for (int i = 0; i < N; i++)
            parent[i] = i;

        for (int i = 0; i < N; i++) {
            input = br.readLine().split(" ");
            for (int j = 0; j < N; j++) {
                map[i][j] = Integer.parseInt(input[j]);
                if (map[i][j] == 1) {
                    union(i, j);
                }
            }
        }

        boolean isCycle = true;
        input = br.readLine().split(" ");
        for (int i = 0; i < M - 1; i++) {
            int a = Integer.parseInt(input[i]) - 1;
            int b = Integer.parseInt(input[i + 1]) - 1;

            if (parent[a] != parent[b]) {
                isCycle = false;
                break;
            }
        }

        System.out.println(isCycle ? "YES" : "NO");
        br.close();
    }

}

간단한 서버 실행하기

https://github.com/oven-sh/bun

 

GitHub - oven-sh/bun: Incredibly fast JavaScript runtime, bundler, transpiler and package manager – all in one.

Incredibly fast JavaScript runtime, bundler, transpiler and package manager – all in one. - GitHub - oven-sh/bun: Incredibly fast JavaScript runtime, bundler, transpiler and package manager – all i...

github.com

// http.ts
export default {
  port: 3000,
  fetch(request: Request) {
    return new Response("Hello World");
  },
};

// bun ./http.ts

bun 문서에서 제공하는 기본 예제 코드입니다.

서버를 실행하기 전에 ifconfig 명령어를 통해 wsl의 네트워크 IP 주소를 확인하세요
윈도우 브라우저에서 WSL 서버로 접속 확인

 

리액트 서버 실행하기

bun create react ./app
cd app
bun dev

React 프로젝트를 생성하고, 프로젝트 폴더로 이동하여 bun 명령어를 통해 서버를 실행
Welcome to React!

 


https://bun.sh/

 

Bun is a fast all-in-one JavaScript runtime

Bundle, transpile, install and run JavaScript & TypeScript projects – all in Bun. Bun is a new JavaScript runtime with a native bundler, transpiler, task runner and npm client built-in.

bun.sh

 

https://www.youtube.com/watch?v=t9924eteb-4 

 

https://code.visualstudio.com/

현재 사용하시는 윈도우에 VSCode가 설치되어 있어야 합니다.

Extensions (Ctrl + Shift + X)에서 Remote - WSL 를 설치합니다
상단 File - Open Folder 를 누르시고, bun 패키지를 설치했던 사용자의 홈 디렉토리로 이동합니다
터미널에서 mkdir 명령어로 폴더/파일 생성 가능하지만, 버튼을 통해서 생성할 경우 Permission denied 문제가 발생했습니다
chown -R <사용자 계정> <경로> 를 통해 권한을 부여하여 해결했습니다
처음 권한 문제로 찾다가 검색했던 내용인데, 위 명령어로도 불가능하다면 이 설정 참고해주세요. Settings ( Ctrl + , )에서 wsl 검색 -> Polling 체크

 

 

환경 구축 과정에서 생략된 부분이 있을 수 있습니다. 댓글 남겨주시면 답글 남기도록 하겠습니다!

Bun은 Windows OS 환경을 지원하지 않지만, WSL(Windows Subsystem for Linux) 설치하여 사용이 가능

 

WSL (Windows SubSystem for Linux) 설치 방법은 아래 블로그에 잘 설명되어 있습니다

https://ingu627.github.io/tips/install_ubuntu/

 

윈도우10에서 리눅스(Linux) 설치하기 (Ubuntu on WSL2)

AWS에서 가상의 환경을 작업하던 중, 내 PC에서 구동해 보았으면 싶어서 설치를 진행해 보았습니다. 윈도우10 환경에서 wsl2를 설치해봅니다.

ingu627.github.io

WSL 설치 후, 계정 생성까지 완료가 되었다면 환경 구축에 필요한 패키지를 설치합니다

sudo apt install net-tools
sudo apt install unzip
sudo apt-get install wget ca-certificates

net-tools:  WSL 서버 주소를 확인하기 위해 (ifconfig)

unzip: bun 설치 시, 압축된 파일을 풀기 위해

ca-certificates:  https 사이트에 curl 명령어를 사용할 때, 오류가 나지 않기 위해

 

sudo su 명령어를 통해 관리자 권한을 획득하시면, sudo를 생략하고 패키지 설치가 가능합니다


Bun 설치하기

/home/<사용자 디렉토리> 로 이동하여 curl 명령어를 실행하였습니다. (다른 폴더에서 해도 됩니다)

그리고 해당 경로(.)에 대한 폴더 권한을 사용자(tpwls8122)에게 부여하였습니다.

폴더 권한을 부여하는 이유는 VScode Extension (Remote - WSL)을 이용해 프로그래밍을 할 때, (폴더, 파일 생성 시) Permission denied 문제를 해결하기 위함입니다. 

 

~ 경로는 현재 접속한 계정의 홈 디렉터리입니다. ( /home/tpwls8122 )

~/.bun/bin/bun에 성공적으로 설치되었다고 하고, 아래 ~/.bashrc 파일에 아래 명령어를 추가해주면 됩니다.

ls -al 명령어를 입력하면 숨겨진 파일들을 확인할 수 있습니다. vi .bashrc 명령어를 통해 파일을 수정합니다
vi 편집기를 사용하시는 분들은 방향키를 통해 커서를 이동하고 i 를 누른 뒤 입력해주세요. 두 줄의 export 명령어를 복사하셨다면 마우스 우클릭을 통해 붙여넣기가 가능합니다. esc 버튼을 누르고 :wq 입력하여 파일을 저장하고 편집기를 종료합니다
bun 명령어를 실행할 수 없습니다. 터미널 새로 열어줍니다
vscode 터미널을 설치하신 분이라면 + 버튼을 통해 새로운 터미널을 실행시켜주시고, 그렇지않다면 우분투 종료 후 재실행 해주시면 될 것 같습니다.

 

 

VSCode - Extension - Remote - WSL 설치

 

다음 장에서  VSCode 를 통해 서버를 실행 시켜보도록 하겠습니다


https://bun.sh/

 

Bun is a fast all-in-one JavaScript runtime

Bundle, transpile, install and run JavaScript & TypeScript projects – all in Bun. Bun is a new JavaScript runtime with a native bundler, transpiler, task runner and npm client built-in.

bun.sh

https://github.com/oven-sh/bun#unzip-is-required

 

GitHub - oven-sh/bun: Incredibly fast JavaScript runtime, bundler, transpiler and package manager – all in one.

Incredibly fast JavaScript runtime, bundler, transpiler and package manager – all in one. - GitHub - oven-sh/bun: Incredibly fast JavaScript runtime, bundler, transpiler and package manager – all i...

github.com

https://www.youtube.com/watch?v=t9924eteb-4 

 

최소 신장 트리 (MST, Minimum Spanning Tree)

 

Spanning Tree

 - 그래프 내의 모든 정점을 포함하는 트리

 - 그래프의 최소 연결 부분 그래프

 - 모든 정점들이 연결되어 있어야 하고, 사이클을 포함해서는 안됨

 - 그래프에 있는 n개의 정점을  n-1 개의 간선으로 연결

 

MST의 특징

 - 간선의 가중치의 합이 최소

 - n개의 정점을 가지고 그래프에 대해 n-1 개의 간선만을 사용

 - 사이클을 포함해서는 안됨

 


문제

https://www.acmicpc.net/problem/10021

 

풀이

처음에는  DFS + 백트래킹으로 풀었다가 시간 초과

이 문제는 MST 알고리즘으로 풀어야한다

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;

class Main {

	static String[] input;
	static StringBuilder sb = new StringBuilder();
	static int N, C;
	static int[] parent;

	// 유니온 파인드
	// 부모(root) 노드를 찾는 과정
	static int find(int n) {
		if (n == parent[n])
			return n;
		return parent[n] = find(parent[n]);
	}

	// 연결된 두 노드의 부모 노드를 찾고, 하나의 부모 노드로 동기화 시켜준다
	static void union(int x, int y) {
		x = find(x);
		y = find(y);

		// 다른 부모 노드 값이 나온다면, 인덱스 값이 더 작은 노드를 부모 노드로 정한다
		if (x < y)
			parent[y] = x;
		else
			parent[x] = y;
	}

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		input = br.readLine().split(" ");
		N = Integer.parseInt(input[0]);
		C = Integer.parseInt(input[1]);

		Node[] node = new Node[N];
		for (int i = 0; i < N; i++) {
			input = br.readLine().split(" ");

			// Node( x좌표, y좌표, 0) 으로 생각
			node[i] = new Node(Integer.parseInt(input[0]), Integer.parseInt(input[1]), 0);
		}

		// 비용(cost)가 적은
		PriorityQueue<Node> pq = new PriorityQueue<>((n1, n2) -> n1.cost - n2.cost);

		for (int i = 0; i < N; i++) {
			for (int j = i + 1; j < N; j++) {
				int cost = (int) Math.pow(node[i].x - node[j].x, 2) + (int) Math.pow(node[i].y - node[j].y, 2);
				// 노드간 비용이 최소 비용을 넘어야만 (관계를 사용할 수 있기 때문에) 우선순위 큐에 넣는다.
				if (C <= cost) {
					// Node ( i번호 노드, j번호 노드, 비용)
					pq.add(new Node(i, j, cost));
				}
			}
		}

		// 노드들의 부모 노드를 자기 자신으로 초기화
		parent = new int[N];
		for (int i = 0; i < N; i++)
			parent[i] = i;

		int result = 0;
		int count = 0; // 모든 정점을 방문했는지 확인하기 위한 변수

		// 우선순위 큐는 가장 최소 비용을 가진 노드 관계를 우선적으로 뽑는다
		while (!pq.isEmpty()) {
			Node n = pq.poll(); // x번 노드, y번 노드, 비용
			if (find(n.x) == find(n.y)) // 노드 관계가 확인된 것이라면 continue
				continue;

			union(n.x, n.y); // union 합친다
			count += 1; // 1개의 노드 관계를 카운트
			result += n.cost;
		}

		// 노드 개수가 N개라면 관계는 N-1개이다. 위에서 중복되지않고 모든 노드를 차례로 관계를 확인했다면 count == N-1
		System.out.println(count < N - 1 ? -1 : result);
		br.close();
	}

}

class Node {
	int x, y, cost;

	Node(int x, int y, int cost) {
		this.x = x;
		this.y = y;
		this.cost = cost;
	}
}

 

 


참고 사이트

 

[알고리즘] 최소 신장 트리(MST, Minimum Spanning Tree)란 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

네트워크(Network)

- Net과 Work의 합성어로 컴퓨터와 같은 노드들이 통신 기술을 통해 그물망처럼 연결되어 통신을 하는 형태를 뜻함

- 데이터 및 리소스를 송신, 교환 또는 공유하기 위한 목적으로 케이블(유선) 또는 WiFi(무선)로 연결된 2개 이상의 컴퓨터로 구성

 


 

IP (Internet Protocol)

- 인터넷에서 다른 컴퓨터와 통신할 때 사용하는 프로토콜

- 컴퓨터의 논리적인 주소를 구분

- 현재 IP는 32비트 체계(IPv4 주소 체계)를 사용하므로 약 40억 개의 주소를 표현 가능 (1비트는 0과 1로 표현이 가능)

  └ 2^32 = 42,9496,7296

- 192.168.0.1 과 같은 형태의 주소 ( 11000000.10101000.00000000.00000001 )

 

* 우리는 도메인 네임을 통해 웹사이트에 접속하지만 사실 IP 주소를 통해 통신을 한다.

kns.kornet.net 은&nbsp; kt의 DNS 서버, domain name을 통해 네이버 접속이 가능하지만 Addresses 2개의 IP 주소를 통해서도 접속이 가능

 

IPv4

- 흔히 사용하는 IP 주소 체계, 일반적인 의미의 IP

- IPv4의 가장 큰 단점은 오직 32비트만을 사용한다는 점 → 공인 IP 주소 40억 개로는 전 세계의 모든 컴퓨터를 처리할 수 없음

- 따라서 이를 해결하기 위해  128 비트를 사용하는 IPv6 주소 체계가 등장 (922,3372,0368,5477,5807 개의 주소. 922경)

 

 

IP의 분류

- 공인 IP : 세계에서 단 하나만 존재하는 IP 주소

A 클래스 IP 대역 0.0.0.0 ~ 127.255.255.255  
B 클래스 IP 대역 128.0.0.0 ~ 191.255.255.255  
C 클래스 IP 대역 192.0.0.0 ~ 233.255.255.255  
D 클래스 IP 대역 224.0.0.0 ~ 239.255.255.255 멀티캐스트 주소 지정을 위함
E 클래스 IP 대역 240.0.0.0 ~ 255.255.255.255 연구용 IP로 예약된 주소

  └ 조직 내부망(인트라넷)에서만 사용하는 내부 서버가 아니라, 외부 서비스(ex. 네이버)라면 반드시 공인 IP가 필요하다

  └ 그렇다면 유동 IP인 경우에는 서버 구축이 불가능할까? -> DDNS (Dynamic DNS)를 통해 구축이 가능하다 (네이버 서버의 IP가 변경되더라도 DDNS 서버에 접촉하여 현재 상태를 동기화 시켜준다)

 

- 사설 IP : 공유기를 이용해 만들 수 있는 가상의 IP 주소

  └ IPv4의 주소 부족 현상을 지연시킬 목적으로 생성

  └ 외부에서는 대표 공인 IP만 검색되며,  사설(내부) IP는 검색이 불가하므로 보안성이 증가

  └ 인터넷 공유기에 연결된  PC, TV, 스마트폰 등이 대표적인 예시

A 클래스 사설 IP 대역 10.0.0.0 ~ 10.255.255.255
B 클래스 사설 IP 대역 172.16.0.0 ~ 172.31.255.255
C 클래스 사설 IP 대역 192.168.0.0 ~ 192.168.255.255

  └ 공인 IP 주소를  사설 IP로 할당할 수 있다. 하지만 공인 IP (구글, 네이버, 다음 등)를 사설 IP로 등록해서 사용할 경우에는 게이트웨이를 타고 나가서 인터넷 상에서 접속해야할 외부 사이트들이 내부 네트워크에 있는 컴퓨터로 계산되어, 내부 네트워크에서 외부 서비스를 사용하지 못하는 문제를 겪을 수 있다

 

- 고정 IP : 해당 컴퓨터의 IP 주소를 고정적으로 사용

 

- 유동 IP : 수시로 변화하는 IP 주소

  └ 말 그대로 IP가 유동적으로 바뀐다는 의미지만 연결 때마다 반드시 변경되지는 않는다. 같은 랜선이라도 PC / 공유기에 연결했을때 다른 IP 받을 수 있는데, 이는 MAC 주소를 토대로 IP를 할당하는 유동 IP의 특성때문이라고 한다

 


 

NAT (Network Address Translation, 네트워크 주소 변환)

- 하나의 공인 IP 주소를 여러 대의 호스트에서 사용할 수 있도록 내부 사설 IP로 나누는 기술

- 내부 네트워크에서 사용하는 IP 주소와 외부에 드러나는 주소를 다르게 유지할 수 있기 때문에, 내부 네트워크에 대한 어느 정도의 보안 기능을 한다. 방화벽과 비슷한 기능이다.

- 우리는 공유기를 설치하여 여러 대의 PC, 스마트폰에서 인터넷을 사용할 수 있는데, 이것이 가능한 이유는 인터넷 공유기에 NAT 기능이 탑재되어 있기 때문

- IP 패킷의 TCP/UDP 포트 숫자와 소스 및 목적지의 IP 주소 등을 재기록하면서 라우터를 통해 네트워크 트래픽을 주고 받는 기술이다.  패킷에 변화가 생기기 때문에 IP나 TCP/UDP의 체크섬(checksum)도 다시 계산되어 재기록해야 한다. 그렇기 때문에 네트워크 성능에 영향을 줄 수 밖에 없다

- NAT을 사용할 때 단점은 여러명이 동시에 인터넷에 접속하게 되므로, 실제로 접속하는 호스트 숫자에 따라서 접속 속도가 느려질 수 있다.

 


 

IP 주소의 여러가지 개념 

◆ 10진수 표기법 (Dotted Decimal Notation)

  └ 실제 네트워크 장비는 IP주소를 2진수로 사용

  └ 10진수 표기는 사람이 IP 주소를 보기 위한 방법

  └ 1 Byte (1옥텟, 1 octet)을 10진수로 변화해 점을 찍어 구분

192.168.10.100

◆ IP 주소의 범위 :  0.0.0.0 ~ 255.255.255.255

◆ IP 주소 = 네트워크(Network) ID  +  호스트(Host) ID

  • Network ID : 네트워크를 나타내는 ID
  • Host ID : 네트워크에 포함된 호스트를 나타내는 ID

 

◆ Class : IP 주소를 효율적으로 나누어 놓은 범위

A Class 대규모 네트워크 범위 - 처음 1비트는 항상 0
- 첫 옥텟(1 byte = 8 bit)을 네트워크 ID로 사용
- 첫 옥텟의 범위는 00000000 (0) ~ 01111111 (127)이지만 0과 127로 시작하는 주소는 예약되어 있어, 실범위는 1 ~ 126
- 나머지 3 옥텟 (3 byte = 24 bit)는 호스트 ID로 사용되며 2^24 = 약 1670만 개의 호스트 수를 가질 수 있다
B Class 중규모 네트워크 범위 - 처음 2개의 비트는 항상 10
- 두 옥텟을 네트워크 ID로 사용
- 첫 옥텟은 10000000 (128) ~ 10111111 (191) 범위를 가진다
- 호스트 ID는 2 옥텟 (2 byte = 16 bit)를 가지므로 2^16 = 65536의 호스트 수를 가진다
C Class 소규모 네트워크 범위 - 처음 3개의 비트는 항상 110
- 세 옥텟(3 byte = 24 bit)을 네트워크 ID로 사용
- 첫 옥텟은 11000000 (192) ~ 11011111 (223)의 범위를 가짐
- 호스트 ID는 1 옥텟 (1 byte = 8 bit)를 가지므로 2^8 = 256개의 호스트 수를 가진다. 
D Class 멀티캐스트용 주소 범위  
E Class 연구용 주소 범위  

 

Subnet Mask (서브넷 마스크)

  • IP주소에서 네트워크 ID와 호스트 ID를 구분하기 위해 사용
  • 32bit로 구성되어 있으며, IP주소와 동일한 표기법을 사용
  • 네트워크 ID는 1로, 호스트 ID는 0으로 표기

 

Subnet Mask - Prefix (프리픽스)

- 서브넷 마스크를 표기하는 다른 방법

- 네트워크 ID의 개수를 표기

 

네트워크 주소와 브로드 캐스트 주소

호스트 ID가 모두 0인 네트워크 주소와  호스트 ID가 모두 1인 브로드 캐스트 주소는 IP 주소로 사용할 수 없다.

위 사진의 네번째 옥텟를 봤을 때, 호스트 ID의 범위는 0 ~ 255이지만 실제로 IP 주소 할당을 할 수 있는 호스트 ID는 1 ~ 254 를 사용할 수 있다

 


 

IP 주소 실습 (내 컴퓨터)

윈도우 CMD - ipconfig

  • C 클래스 사설 IP 대역에 속함
  • 서브넷 마스크  프리픽스(Prefix) 표기 :  192.168.0.11 / 24
  • IPv4 주소 2진법으로 표기 : 11000000.10101000.00000000.00001011
  • 서브넷 마스크 2진법 표기 : 11111111.11111111.11111111.00000000
  • IPv4 주소와 서브넷 마스크.  비트 AND 연산하여 네트워크 ID를 구한다.  
    • 네트워크 ID : 11000000.10101000.00000000.00000000 (192.168.0.0)
    • 호스트 ID는 192.168.0.0 (네트워크 주소) ~ 192.168.0.255 (브로드캐스트 주소)를 가지며 개수는 2^8 = 256개
    • IP 주소로 사용할 수 있는 범위는 192.168.0.1 ~ 192.168.0.254이며, 나의 IP 주소는 범위안에 있는 192.168.0.11
  • 기본 게이트웨이는 ipTime 공유기 주소를 뜻하며, 일반적으로 1로 지정한다고 한다. 그렇다면 내 공유기에 연결될 수 있는 장치는 2 ~ 254 범위, 253개의 장치를 연결할 수 있다는 뜻이다

 


 

IP 추적 (Tracking)

- 공인 IP 주소를 가진다면 추적이 쉽다

- 사설 IP라고 하더라도 수사권이 있는 경찰은 ISP 업체를 통해 추적할 수 있다

 

나의 공인 IP로 조회해본 결과, 특정한 위치까지 나오지 않는다.

https://www.ip-tracker.org/

https://findip.opendocs.co.kr/

 


 

ISP (Internet Service Provider, 인터넷 서비스 제공자)

KT(KORNET), SK텔레콤(SK_TELECOM-NET), SK브로드밴드(broadNnet)은 인터넷망이 통합되어 있다. LG U+는 여러 인터넷 망을 사용하기 때문에 혼파망이라고 부르고, 이 때문에 같은 지역에서 같은 LG U+ 인터넷을 쓰더라도 어느 ISP에 연결되어있는지에 따라 인터넷의 품질이 극과 극으로 나누어 진다.

 


 

서버 구축을 쉽게 하는 방법은 호스팅 업체를 이용

아마존 AWS (Amazon Web Services), MS Azure, Google GCP, 네이버 클라우드, NHN 클라우드, Cafe24, 가비아 등이 있다

 

사설 IP로 서버 운영하는 방법

- 외부에서는 사설 IP로 접속이 불가능하지만, 포트 포워딩(특정한 포트로 들어오는 데이터 패킷을 다른 포트로 바꿔서 다시 전송해주는 작업)을 통해 해결할 수 있다

ipTIME 공유기를 사용한다면 192.168.0.1에 접속하여, 포트포워딩 설정을 할 수 있다

- 우리 집의 공인 IP를 219.214.33.125 라고 가정, 공유기를 사용하는 PC 2대는 192.168.0.2 (A 컴퓨터, 웹 서버(PORT : 3000), 192.168.0.3 (B 컴퓨터) IP를 할당받아 사용하고 있다

- 포트 포워딩을 설정하여, 3000번 포트로 들어오는 패킷은 192.168.0.2 (A 컴퓨터)로 접속할 수 있도록 설정해준다

- http://219.214.33.125:3000 로 접속 시, A 컴퓨터 서버로 접속이 가능하다

- 만약 B 컴퓨터에도 3000번 포트를 사용하는 웹 서버를 구축했다고 가정해보자. 이 경우 B 컴퓨터에 대한 포트 포워딩 규칙을 외부 포트:3001, 내부 포트:3000으로 추가하여, 공인IP:3000 은 A 웹 서버,  공인IP:3001 은 B 웹 서버로 포워딩하여 충돌을 피할 수 있다

 


 

포트 (PORT)

- IP는 컴퓨터를 찾는 주소라고 한다면, PORT는 컴퓨터의 응용 프로그램을 찾는 주소이다. 

- A 대학교의 주소를 IP 주소라고 비유한다면,  컴퓨터공학과는 포트(PORT)이다. 또는 서울 B아파트 102동이 IP 주소라고 한다면,  301호는 포트(PORT)라고 생각하면 될 것 같다

잘 알려진 포트 (well-known port) 0번 ~ 1023번 - IANA의 권고안일 뿐이다. 가끔 각 포트 번호를 그대로 사용하지 않고 다른 용도로 사용하기도 한다
- SSH(22), HTTP(80), HTTPS(443), FTP(20, 21), TELNET(23), RDP(3389, 원격 데스크톱) 
- well-known port는 정보보안 컨설팅 시 지적사항에 해당하기 때문에, 잘 알려진 포트에 대해서는 변경이 필요하다고 한다
등록된 포트 (registered port) 1024번 ~ 49151번 - 사용자가 직접 등록할 수 있는 포트를 의미하며 등록해서 사용할 수 있다
동적 포트 (dynamic port) 49152번 ~ 65535번 - 수시로 변경되는 포트를 의미하며 인터넷이나 시스템에서 사용할 때 동적으로 할당하는 포트를 의미한다 (동적포트)
- 운영체제가 부여하는 동적 포트 또는 개인적인 목적으로 사용할 수 있는 포트

 

 

더 공부 : DMZ


참고 사이트

https://www.youtube.com/watch?v=pRWD7oTeuFw 

https://rcsecurity.tistory.com/4

https://itinformation.tistory.com/59

https://www.youtube.com/watch?v=b7Wk-6w5vgg 

https://namu.wiki/w/NAT

 

1. pom.xml  -  dependency 추가

https://mvnrepository.com/

 

Maven Repository: Search/Browse/Explore

Simple API to run JMeter performance tests in an VCS and programmers friendly way. Last Release on Oct 28, 2021

mvnrepository.com

httpmime 검색해서 원하는 버전 선택해서 pom.xml에 dependency를 추가
추가된 것을 확인

2. 라이브러리를 이용하여 post (multipart/form-data) 요청

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class Main {
	public static void main(String[] args) throws IOException {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpPost uploadFile = new HttpPost("URL");
		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
		builder.addTextBody("name", "sejin");
		builder.addTextBody("key", "value");

		File file = new File("C:\\Users\\tpwls\\Downloads\\test.png");

		builder.addBinaryBody("image", new FileInputStream(file), ContentType.APPLICATION_OCTET_STREAM, file.getName());

		HttpEntity multipart = builder.build();
		uploadFile.setEntity(multipart);
		CloseableHttpResponse response = httpClient.execute(uploadFile);
		HttpEntity responseEntity = response.getEntity();

		InputStream is = responseEntity.getContent();
		BufferedReader r = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));

		String line = null;
		StringBuilder sb = new StringBuilder();

		while ((line = r.readLine()) != null) {
			sb.append(line);
		}

		System.out.println(sb.toString());
	}
}

 

+ Recent posts