> su
Password:
su: Sorry
su: Sorry
라고 나오며, 루트 사용자(su)로 실행되지 않는다.
이는 비밀번호 초기 설정이 안되어있어 나오는 것이다.
> sudo -s
입력하여 (경고는 엔터키를 눌러 무시해도 된다.), bash 쉘에 접속하고 > passwd root
명령어를 통해 root 비밀번호를 설정해준다.
앞으로 su
명령어를 실행할 때, 설정한 비밀번호을 사용한다.
> su
Password:
su: Sorry
su: Sorry
라고 나오며, 루트 사용자(su)로 실행되지 않는다.
이는 비밀번호 초기 설정이 안되어있어 나오는 것이다.
> sudo -s
입력하여 (경고는 엔터키를 눌러 무시해도 된다.), bash 쉘에 접속하고 > passwd root
명령어를 통해 root 비밀번호를 설정해준다.
앞으로 su
명령어를 실행할 때, 설정한 비밀번호을 사용한다.
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,
};
[CentOS7] MongoDB 환경 구성 (네트워크, 보안 설정) (1) | 2024.04.19 |
---|---|
[NoSQL] MongoDB 설치 - Mac (0) | 2022.09.10 |
토이 프로젝트 진행하면서 OpenAPI를 사용하는데, 요청 수 제한이 있어, 클라이언트에서 많은 요청들을 계속하여 호출하는데 무리가 있었다. (429 Too Many Requests)
백엔드 서버에서 스케줄링을 통해 데이터베이스에 API 정보를 저장한다면, 문제를 해결할 수 있을 것 같았다.
OpenAPI를 사용하다보니 RDBMS로는 데이터 정보 구조를 정의하고 관리하기에는 무리가 있을 것 같아, 비정형화 데이터를 저장할 수 있는 NoSQL을 사용하기로 했다.
오래전에 Firebase(Only 클라우드 서비스, 비용 발생 가능성)를 통해 NoSQL을 접해본 적은 있지만, 가장 많이 사용하는 NoSQL인MongoDB를 접해보고 싶었고, 환경을 직접 구축(On-premise)해보는 경험을 해보기로 했다.
단점
brew tap mongodb/brew
brew install mongodb-community
# 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
이후 mongo shell 접속하기 위해, mongo 명령어를 통해 접속하려 했지만 실패하였다.
MongoDB 문서를 참고하여, mongosh 명령어로 접속할 수 있었음
mongosh
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}...])
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()
[CentOS7] MongoDB 환경 구성 (네트워크, 보안 설정) (1) | 2024.04.19 |
---|---|
[NoSQL] NodeJS + MongoDB(mongoose) (0) | 2022.09.12 |
동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 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();
}
}
[프로그래머스] 뒤에 있는 큰 수 찾기 (0) | 2023.02.12 |
---|---|
[프로그래머스] 억억단을 외우자 (0) | 2022.11.26 |
백준 10021 : Watering the Fields (JAVA, MST) (0) | 2022.08.10 |
[JAVA] 단체사진 찍기 (2017 카카오코드 본선) (0) | 2022.06.18 |
SCC - Tarjan (타잔 알고리즘) (0) | 2019.07.11 |
https://github.com/oven-sh/bun
// http.ts
export default {
port: 3000,
fetch(request: Request) {
return new Response("Hello World");
},
};
// bun ./http.ts
bun 문서에서 제공하는 기본 예제 코드입니다.
bun create react ./app
cd app
bun dev
https://www.youtube.com/watch?v=t9924eteb-4
[Bun] 2. Windows WSL 통해 Bun 환경 구축하기 (feat. VSCode) (0) | 2022.08.14 |
---|---|
[Bun] 1. Windows WSL 통해 Bun 환경 구축하기 (0) | 2022.08.14 |
https://code.visualstudio.com/
현재 사용하시는 윈도우에 VSCode가 설치되어 있어야 합니다.
환경 구축 과정에서 생략된 부분이 있을 수 있습니다. 댓글 남겨주시면 답글 남기도록 하겠습니다!
[Bun] 3. Bun 명령어를 통해 React 서버 실행하기 (0) | 2022.08.14 |
---|---|
[Bun] 1. Windows WSL 통해 Bun 환경 구축하기 (0) | 2022.08.14 |
WSL (Windows SubSystem for Linux) 설치 방법은 아래 블로그에 잘 설명되어 있습니다
https://ingu627.github.io/tips/install_ubuntu/
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를 생략하고 패키지 설치가 가능합니다
/home/<사용자 디렉토리> 로 이동하여 curl 명령어를 실행하였습니다. (다른 폴더에서 해도 됩니다)
그리고 해당 경로(.)에 대한 폴더 권한을 사용자(tpwls8122)에게 부여하였습니다.
폴더 권한을 부여하는 이유는 VScode Extension (Remote - WSL)을 이용해 프로그래밍을 할 때, (폴더, 파일 생성 시) Permission denied 문제를 해결하기 위함입니다.
~ 경로는 현재 접속한 계정의 홈 디렉터리입니다. ( /home/tpwls8122 )
~/.bun/bin/bun에 성공적으로 설치되었다고 하고, 아래 ~/.bashrc 파일에 아래 명령어를 추가해주면 됩니다.
다음 장에서 VSCode 를 통해 서버를 실행 시켜보도록 하겠습니다
https://github.com/oven-sh/bun#unzip-is-required
https://www.youtube.com/watch?v=t9924eteb-4
[Bun] 3. Bun 명령어를 통해 React 서버 실행하기 (0) | 2022.08.14 |
---|---|
[Bun] 2. Windows WSL 통해 Bun 환경 구축하기 (feat. VSCode) (0) | 2022.08.14 |
최소 신장 트리 (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;
}
}
[프로그래머스] 억억단을 외우자 (0) | 2022.11.26 |
---|---|
[알고리즘] Union-Find (유니온 파인드) (0) | 2022.08.21 |
[JAVA] 단체사진 찍기 (2017 카카오코드 본선) (0) | 2022.06.18 |
SCC - Tarjan (타잔 알고리즘) (0) | 2019.07.11 |
[알고스팟] WILDCARD - JAVA (0) | 2019.06.06 |
- Net과 Work의 합성어로 컴퓨터와 같은 노드들이 통신 기술을 통해 그물망처럼 연결되어 통신을 하는 형태를 뜻함
- 데이터 및 리소스를 송신, 교환 또는 공유하기 위한 목적으로 케이블(유선) 또는 WiFi(무선)로 연결된 2개 이상의 컴퓨터로 구성
- 인터넷에서 다른 컴퓨터와 통신할 때 사용하는 프로토콜
- 컴퓨터의 논리적인 주소를 구분
- 현재 IP는 32비트 체계(IPv4 주소 체계)를 사용하므로 약 40억 개의 주소를 표현 가능 (1비트는 0과 1로 표현이 가능)
└ 2^32 = 42,9496,7296
- 192.168.0.1 과 같은 형태의 주소 ( 11000000.10101000.00000000.00000001 )
* 우리는 도메인 네임을 통해 웹사이트에 접속하지만 사실 IP 주소를 통해 통신을 한다.
- 흔히 사용하는 IP 주소 체계, 일반적인 의미의 IP
- IPv4의 가장 큰 단점은 오직 32비트만을 사용한다는 점 → 공인 IP 주소 40억 개로는 전 세계의 모든 컴퓨터를 처리할 수 없음
- 따라서 이를 해결하기 위해 128 비트를 사용하는 IPv6 주소 체계가 등장 (922,3372,0368,5477,5807 개의 주소. 922경)
- 공인 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의 특성때문이라고 한다
- 하나의 공인 IP 주소를 여러 대의 호스트에서 사용할 수 있도록 내부 사설 IP로 나누는 기술
- 내부 네트워크에서 사용하는 IP 주소와 외부에 드러나는 주소를 다르게 유지할 수 있기 때문에, 내부 네트워크에 대한 어느 정도의 보안 기능을 한다. 방화벽과 비슷한 기능이다.
- 우리는 공유기를 설치하여 여러 대의 PC, 스마트폰에서 인터넷을 사용할 수 있는데, 이것이 가능한 이유는 인터넷 공유기에 NAT 기능이 탑재되어 있기 때문
- IP 패킷의 TCP/UDP 포트 숫자와 소스 및 목적지의 IP 주소 등을 재기록하면서 라우터를 통해 네트워크 트래픽을 주고 받는 기술이다. 패킷에 변화가 생기기 때문에 IP나 TCP/UDP의 체크섬(checksum)도 다시 계산되어 재기록해야 한다. 그렇기 때문에 네트워크 성능에 영향을 줄 수 밖에 없다
- NAT을 사용할 때 단점은 여러명이 동시에 인터넷에 접속하게 되므로, 실제로 접속하는 호스트 숫자에 따라서 접속 속도가 느려질 수 있다.
◆ 10진수 표기법 (Dotted Decimal Notation)
└ 실제 네트워크 장비는 IP주소를 2진수로 사용
└ 10진수 표기는 사람이 IP 주소를 보기 위한 방법
└ 1 Byte (1옥텟, 1 octet)을 10진수로 변화해 점을 찍어 구분
◆ IP 주소의 범위 : 0.0.0.0 ~ 255.255.255.255
◆ IP 주소 = 네트워크(Network) ID + 호스트(Host) 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 (서브넷 마스크)
◆ Subnet Mask - Prefix (프리픽스)
- 서브넷 마스크를 표기하는 다른 방법
- 네트워크 ID의 개수를 표기
◆ 네트워크 주소와 브로드 캐스트 주소
호스트 ID가 모두 0인 네트워크 주소와 호스트 ID가 모두 1인 브로드 캐스트 주소는 IP 주소로 사용할 수 없다.
위 사진의 네번째 옥텟를 봤을 때, 호스트 ID의 범위는 0 ~ 255이지만 실제로 IP 주소 할당을 할 수 있는 호스트 ID는 1 ~ 254 를 사용할 수 있다
- 공인 IP 주소를 가진다면 추적이 쉽다
- 사설 IP라고 하더라도 수사권이 있는 경찰은 ISP 업체를 통해 추적할 수 있다
https://findip.opendocs.co.kr/
아마존 AWS (Amazon Web Services), MS Azure, Google GCP, 네이버 클라우드, NHN 클라우드, Cafe24, 가비아 등이 있다
- 외부에서는 사설 IP로 접속이 불가능하지만, 포트 포워딩(특정한 포트로 들어오는 데이터 패킷을 다른 포트로 바꿔서 다시 전송해주는 작업)을 통해 해결할 수 있다
- 우리 집의 공인 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 웹 서버로 포워딩하여 충돌을 피할 수 있다
- 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
1. 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());
}
}
[JAVA] Slack API 활용하여 서버 CPU 사용률 모니터링 구축해보기 (0) | 2022.06.26 |
---|---|
[윈도우] JAVA 1.8 설치 (0) | 2020.11.14 |
[JAVA] 문자열 수식 계산하기 (0) | 2019.05.13 |