Spring은 Spring Triangle이라고 부르는 핵심 3대 요소를 제공한다.

 

 

핵심 3대 요소에 대해 알아보기 전에 POJO란 무엇인지 먼저 알아보자

 

POJO(Plain Old Java Object 오래된 방식의 간단한 자바 오브젝트) : 특정 기술에 종속되지 않는 순수한 자바 객체를

의미한다. 예를 들어, 특정 기술을 사용하기 위해 특정 프레임워크를 의존하게 되면 그것은 POJO라고 할 수 없다.

특정 기술에 종속되어 있기 때문이다.

 

POJO의 예

public class UserDTO {
	
	private String userName;
	private String userId;
	private String userPassword;
	
	public String getUserName() {
		return userName;
	}
	
	public void setUserName(String userName) {
		this.userName = userName;
	}
	
	public String getUserId() {
		return userId;
	}
	
	public void setUserId(String userId) {
		this.userId = userId;
	}
	
	public String getUserPassword() {
		return userPassword;
	}
	
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
}

위 객체는 기본적인 자바 기능인 getter, setter 기능만 가지고 있다.

특정 기술에 종속되어 있지 않은 순수 자바 객체이기 때문에 위 객체는 POJO라고 할 수 있다.

 

POJO가 아닌 예

public class Sample extends WindowAdapter {

	@Override
	public void windowClosing(WindowEvent e) {
		System.exit(0);
	}
}

Window의 기능을 사용하기 위해 WindowAdapter 클래스를 상속받았기 때문에 POJO라고 할 수 없다.

이렇게 되면 다른 솔루션을 사용하고자 할 때 많은 양의 코드를 리팩토링해야 하는 문제가 있다.

 

이처럼 특정 기술과 환경에 종속되어 의존하게 되면, 코드 가독성 뿐만 아니라 유지보수, 확장성에도 어려움이 생긴다.

이러한 객체지향의 장점을 잃어버린 자바를 되살리기 위해 POJO라는 개념이 등장한 것이다.

 

진정한 POJO란 객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로

설계된 오브젝트이다. - 토비의 스프링 -

 

POJO는
A. 미리 지정된 클래스를 extends 하면 안 된다.
B. 미리 정의된 인터페이스를 implements 하면 안 된다.
C. 미리 정의된 Annotation을 포함하면 안 된다.

 

POJO의 장점
특정 규약에 종속되지 않아 객체지향 설계를 할 수 있다.
특정 환경에 종속되지 않아 테스트하기 좋다.
특정 규약에 종속되지 않아 낮은 레벨 코드와 비즈니스 코드가 분리되어 깔끔한 코드 작성이 가능하다.

 

애플리케이션을 구성하는 객체(Bean)가 생성되고 동작하는 틀을 제공해 줄 뿐만 아니라,

애플리케이션 코드를 어떻게 작성해야 하는지에 대한 기준도 제공한다.

이를 일반적으로 프로그래밍 모델이라고 부르는데, Spring에는 크게 3가지 핵심 프로그래밍 모델을 지원한다.

 

1. AOP(Aspect Oriented Programming 관점 지향 프로그래밍) : 여러 객체에 공통으로 적용할 수 있는 기능을

구분함으로써 재사용을 높여주는 프로그래밍 기법이다. AOP는 핵심 기능과 공통 기능의 구현을 분리함으로써

핵심 기능을 구현한 코드의 수정 없이 공통 기능을 적용할 수 있게 만들어준다.

 

 

2. PSA(Portable Service Abstraction 서비스 추상화) : 환경의 변화와 관계없이 일관된 방식의 기술로의 접근 환경을

제공하는 추상화 구조를 말한다. 이는 POJO 원칙을 철저히 따른 Spring의 기능으로 Spring에서 동작할 수 있는

Library들은 POJO 원칙을 지키도록 PSA 형태의 추상화가 되어있음을 의미한다.
잘 만든 인터페이스 하나가 열 클래스 부럽지 않다. PSA를 '잘 만든 인터페이스'라고도 한다.
PSA가 적용된 코드는 나의 코드가 바뀌지 않고, 다른 기술로 간편하게 바꿀 수 있도록 확장성이 좋고
기술에 특화되어 있지 않는 코드를 의미한다.
Spring은 Spring Web MVC, Spring Transaction, Spring Cache 등 다양한 PSA를 제공한다.

 

Spring Web MVC

             @Component

                     @Controller

                     @Repository

                     @Service

            ● @RequestMapping

            ● ...

● Spring Transaction

            ● JDBC

            ● JPA

● Spring Cache

            ● Cacheable

            ● CacheEvict

...

 

3. IoC / DI

IoC(Inversion of Control 제어의 역전) : 이는 Spring뿐만 아니라 모든 프로그래밍에서 사용될 수 있는 범용적인 개념이다.

쉽게 말해 객체의 제어권이 개발자 본인이 아닌 Spring 컨테이너에게 넘어가는 것이다.

 

다음은 일반적으로 자바에서 객체를 생성하여 객체를 제어하는 코드이다.

class ClassA {
		
}

class ClassB{
	
    private ClassA a;
    
    ClassB() {
    	this.a = new ClassA();
    }
}

보다시피 개발자 본인이 new 연산자를 통해 직접 객체를 생성하고 변수에 할당해 줘야 하는 방식이다.

 

Spring의 경우는 어떨까?

 

다음은 Spring에서의 객체 할당 방식이다.

@Component
class ClassA {
		
}

class ClassB{
	
    @Autowired
    private ClassA a;
 
}

Spring의 경우 Bean(Spring에 의해 관리되는 객체)이라면 @Autowired 어노테이션을 통해 손쉽게 객체를 할당할 수 있다.

이는 개발자 본인이 객체를 관리하는 것이 아닌 Spring 컨테이너에서 객체를 생성하고 해당 객체를 할당 시켜준 것이다.

이처럼 객체의 흐름, 생명주기 관리 등을 외부(제3자)에서 처리하는 방식의 모델을 제어의 역전(IoC)라고 한다.

 

제어의 역전 개념을 이용하면 프레임워크와 라이브러리의 구분 또한 가능하다.

프레임워크가 내가 작성한 코드를 제어하고, 대신 실행하면 그것은 프레임워크가 맞다.(JUnit)

반면에, 내가 작성한 코드가 직접 제어의 흐름을 담당한다면 그것은 프레임워크가 아니라 라이브러리이다.

 

DI(Dependency Injection 의존성 주입) : 객체를 외부로부터 할당받고 이를 통해 객체를 동적으로 할당하는 방식이다.

사용할 객체들을 컨테이너에 등록한 후 애플리케이션 코드에서 해당 객체를 setter 함수의 매개변수로 받아와서

실행 시 동적으로 의존관계를 설정해 준다.

 

의존성 주입 방식에는 3가지가 있다.

A. 생성자를 이용한 의존성 주입

B. setter 메소드를 이용한 의존성 주입

C. 초기화 인터페이스를 이용한 의존성 주입

 

Spring에서는 두 번째 방식인 setter 메소드를 이용한 의존성 주입을 지지한다.

외부에서 제공받은 객체를 저장해뒀다가 내부의 메소드에서 사용하도록 하는 DI 방식에서 활용하기 좋기 때문이다.

 

이 IoC와 DI 덕분에 캡슐화를 통한 높은 응집도와, 객체 간의 낮은 결합도를 이루고 유연한 코드를 작성할 수 있도록

해주며, 개발자들이 개발에 더욱 집중할 수 있도록 해준다.

import java.util.PriorityQueue;

public class Solution {
	
	// 디펜스 게임
	
	public static int solution(int n, int k, int[] enemy) {
		int answer = enemy.length; // 모든 라운드 클리어 가능할 경우의 리턴 값
		
		PriorityQueue<Integer> pq = new PriorityQueue<>(); // 무적권을 사용해 해치울 적의 수를 남기기 위한 우선순위 큐
		
		// 디펜스 게임 시작
		for(int i = 0; i < enemy.length; i++) { // 4, 2, 4, 5, 3, 3, 1
			pq.offer(enemy[i]); // 4 // 2, 4 // 2, 4, 4 // 2, 4, 4, 5 // 3, 4, 4, 5 // 3, 4, 4, 5
			
			// 무적권은 3개이므로 pq에 4개 이상 라운드가 담기면 그중 가장 적은 적이 나타나는 라운드는 병사를 소모하여 클리어
			if(pq.size() > k) { // false // false // false // true // true // true
				n -= pq.poll(); // 7 // 7 // 7 // 5 // 2 // -1
			}
			
			if(n < 0) { // false // false // false // false // false // true
				return i; // enemy 배열의 6번째 숫자에서 음수가 나오므로 enemy 배열의 5번째 숫자까지는 pass // 5라운드까지 진출 가능
			}
		}
		
		return answer; // 여기까지 내려왔다는 것은 모든 적을 해치우고도 병사가 남았다는 얘기 즉, 모든 라운드 클리어 가능
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n = 7; // 병사 수
		int k = 3; // 무적권 수
		int[] enemy = {4, 2, 4, 5, 3, 3, 1}; // 라운드별 적 수
		
		System.out.println(solution(n, k, enemy)); // 5
	}
}

프로그래머스 디펜스 게임 문제 풀이 Java

public class Solution {

	// 이동하기 - DP 11048번
	
	static int n = 3;
	static int m = 4;
	static int[][] arr = {{1, 2, 3, 4}, {0, 0, 0, 5}, {9, 8, 7, 6}};
	static int[] dy = {1, 1, 0};
	static int[] dx = {0, 1, 1};
	static int[][] dp = new int[n][m];
	
	public static void dfs(int a, int b) {
		
		for(int i = 0; i < 3; i++) {
			int ny = a + dy[i];
			int nx = b + dx[i];
			
			if(ny > n - 1 || nx > m - 1) {
				continue;
			}
			
			// dp 갱신 후 dfs(순서 잘 생각)
			dp[ny][nx] = Math.max(dp[ny][nx], arr[ny][nx] + dp[a][b]);
			dfs(ny, nx);
		}
	}
	
	public static void dynamicProgramming() {
		dp[0][0] = arr[0][0];
		dfs(0,0);
		
		for(int i = 0; i < n; i++) {
			
			for(int j = 0; j < m; j++) {
				System.out.print(dp[i][j] + " ");
			}
            
			System.out.println();
		}
		
		System.out.println("얻을 수 있는 최대 사탕 개수 : " + dp[n - 1][m - 1]);
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// (1,1) 좌상단에서 (N,M) 우하단까지 사탕 최대로 얻기
		dynamicProgramming();
	}
}

백준 DP 11048번 이동하기

'Java > 백준' 카테고리의 다른 글

[Java] 백준 [2178] 미로 탐색  (0) 2022.12.24
[Java] 백준 [1541] 잃어버린 괄호  (0) 2022.12.18
[Java] 백준 [7570] 줄 세우기  (0) 2022.12.17
[Java] 백준 [2631] 줄 세우기  (0) 2022.12.17
[Java] 백준 [9095] 1, 2, 3 더하기  (0) 2022.12.16

<MySQL>

SELECT A.AUTHOR_ID
     , B.AUTHOR_NAME
     , A.CATEGORY
     , SUM(A.PRICE * C.SALES) AS TOTAL_SALES
  FROM BOOK A
     , AUTHOR B
     , BOOK_SALES C
 WHERE A.AUTHOR_ID = B.AUTHOR_ID
   AND A.BOOK_ID = C.BOOK_ID
   AND DATE_FORMAT(C.SALES_DATE, '%Y-%m') = '2022-01'
 GROUP BY A.AUTHOR_ID, A.CATEGORY, B.AUTHOR_NAME
 ORDER BY A.AUTHOR_ID, A.CATEGORY DESC

<Oracle>

SELECT A.AUTHOR_ID
     , B.AUTHOR_NAME
     , A.CATEGORY
     , SUM(A.PRICE * C.SALES) AS TOTAL_SALES
  FROM BOOK A
     , AUTHOR B
     , BOOK_SALES C
 WHERE A.AUTHOR_ID = B.AUTHOR_ID
   AND A.BOOK_ID = C.BOOK_ID
   AND TO_CHAR(C.SALES_DATE, 'YYYY-MM') = '2022-01'
 GROUP BY A.AUTHOR_ID, A.CATEGORY, B.AUTHOR_NAME
 ORDER BY A.AUTHOR_ID, A.CATEGORY DESC

프로그래머스 저자 별 카테고리 별 매출액 집계하기 SQL

import java.util.LinkedList;
import java.util.Queue;

public class Solution {

	// 미로 탐색 - BFS 2178번
	// 최단 거리 탐색 BFS
	
	static int r = 4;
	static int c = 6;
	static int[][] arr = {{1, 0, 1, 1, 1, 1}, {1, 0, 1, 0, 1, 0}, {1, 0, 1, 0, 1, 1}, {1, 1, 1, 0, 1, 1}};
	static boolean[][] visit = {};
	static int[] dx = {0, 0, -1, 1};
	static int[] dy = {-1, 1, 0, 0};
	
	public static void bfs(int n, int m) {
		
		Queue<int[]> q = new LinkedList<>();
		
		q.offer(new int[] {n,m});
		
		visit[n][m] = true;
		
		while(!q.isEmpty()) {
			
			int[] tempArr = q.poll();
			int row = tempArr[0];
			int col = tempArr[1];
			
			for(int i = 0; i < 4; i++) {
				int nextX = col + dx[i];
				int nextY = row + dy[i];
				
				if(nextX < 0 || nextY < 0 || nextX >= c || nextY >= r) {
					continue;
				}
				
				if(visit[nextY][nextX] || arr[nextY][nextX] == 0) {
					continue;
				}
				
				q.offer(new int[] {nextY,nextX});
				arr[nextY][nextX] = arr[row][col] + 1;
				visit[nextY][nextX] = true;
			}
		}
		
		System.out.println(arr[r-1][c-1]);
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		visit = new boolean[r][c];
		
		bfs(0, 0);
	}
}

백준 BFS 2178번 미로 탐색

'Java > 백준' 카테고리의 다른 글

[Java] 백준 [11048] 이동하기  (0) 2022.12.26
[Java] 백준 [1541] 잃어버린 괄호  (0) 2022.12.18
[Java] 백준 [7570] 줄 세우기  (0) 2022.12.17
[Java] 백준 [2631] 줄 세우기  (0) 2022.12.17
[Java] 백준 [9095] 1, 2, 3 더하기  (0) 2022.12.16

core > BlockChainStarter

package core;

import java.util.ArrayList;

public class BlockChainStarter {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Block block1 = new Block(1, null, 0, new ArrayList<Transaction>());
		block1.mine();
		block1.getInformation();
		
		Block block2 = new Block(2, block1.getBlockHash(), 0, new ArrayList<Transaction>());
		block2.addTransaction(new Transaction("이승엽", "홍길동", 1.5));
		block2.addTransaction(new Transaction("이근혁", "홍길동", 0.7));
		block2.mine();
		block2.getInformation();
		
		Block block3 = new Block(3, block2.getBlockHash(), 0, new ArrayList<Transaction>());
		block3.addTransaction(new Transaction("리로이", "다니엘", 8.2));
		block3.addTransaction(new Transaction("홍길동", "이승엽", 0.4));
		block3.mine();
		block3.getInformation();
		
		Block block4 = new Block(4, block3.getBlockHash(), 0, new ArrayList<Transaction>());
		block4.addTransaction(new Transaction("다니엘", "리로이", 0.1));
		block4.mine();
		block4.getInformation();
	}
}

core > Block

package core;

import java.util.ArrayList;
import util.Util;

public class Block {

	private int blockID; // 블록 아이디
	private String previousBlockHash; // 이전 블록의 해시 값
	private int nonce; // 채굴을 위한 정답
	private ArrayList<Transaction> transactionList; // 블록에 들어가는 데이터(해당 블록이 생성되기 전까지 발생한 신규 트랜잭션들의 정보)
	
	public Block(int blockID, String previousBlockHash, int nonce, ArrayList<Transaction> transactionList) {
		this.blockID = blockID;
		this.previousBlockHash = previousBlockHash;
		this.nonce = nonce;
		this.transactionList = transactionList;
	}
	
	public int getBlockID() {
		return blockID;
	}
	
	public void setBlockID(int blockID) {
		this.blockID = blockID;
	}
	
	public String getPreviousBlockHash() {
		return previousBlockHash;
	}

	public void setPreviousBlockHash(String previousBlockHash) {
		this.previousBlockHash = previousBlockHash;
	}
	
	public int getNonce() {
		return nonce;
	}
	
	public void setNonce(int nonce) {
		this.nonce = nonce;
	}
	
	public void addTransaction(Transaction transaction) {
		transactionList.add(transaction);
	}
	
	public String getBlockHash() { // 해당 블록의 해시 값
		String transactionInformations = "";
		
		for(int i = 0; i < transactionList.size(); i++) {
			transactionInformations += transactionList.get(i).getInformation();
		}
		
		return Util.getHash(nonce + transactionInformations + previousBlockHash);
	}
	
	public void getInformation() { // 특정한 한 개의 블록이 있을 때 이 블록에 대한 정보를 출력
		System.out.println("----------------------------------");
		System.out.println("블록 아이디 : " + getBlockID());
		System.out.println("이전 블록의 해시 값: " + getPreviousBlockHash());
		System.out.println("채굴 정답 : " + getNonce());
		System.out.println("트랜잭션 개수 : " + transactionList.size() + "개");
		
		for(int i = 0; i < transactionList.size(); i++) {
			System.out.println(transactionList.get(i).getInformation());
		}
		
		System.out.println("블록의 해시 값 : " + getBlockHash());
		System.out.println("----------------------------------");
	}
	
	public void mine() {
		while(true) {
			if(getBlockHash().substring(0, 4).equals("0000")) { // nonce + transactionInformations + previousBlockHash의 해시 값이 "0000"으로 시작할 때 채굴에 성공 // 채굴 난이도 고정
				System.out.println(blockID + "번째 블록의 채굴에 성공했습니다.");
				break;
			}
			nonce++;
		}
	}
}

core > Transaction

package core;

public class Transaction {
	
	String sender;
	String receiver;
	double amount;
	
	public Transaction(String sender, String receiver, double amount) {
		this.sender = sender;
		this.receiver = receiver;
		this.amount = amount;
	}
	
	public String getSender() {
		return sender;
	}
	
	public void setSender(String sender) {
		this.sender = sender;
	}
	
	public String getReceiver() {
		return receiver;
	}
	
	public void setReceiver(String receiver) {
		this.receiver = receiver;
	}
	
	public double getAmount() {
		return amount;
	}
	
	public void setAmount(double amount) {
		this.amount = amount;
	}
	
	public String getInformation() {
		return sender + "이(가) " + receiver + "에게 " + amount + "개의 코인을 보냈습니다.";
	}
}

util > Util

package util;

import java.security.MessageDigest;

public class Util {
	
	public static String getHash(String input) { // 단순 문자열 input
		StringBuffer result = new StringBuffer();
		
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-256"); // Secure Hash Algorithm // 256비트로 구성 // 64자리 문자열 반환
			md.update(input.getBytes());
			byte bytes[] = md.digest();
			
			for(int i = 0; i < bytes.length; i++) {
				result.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		return result.toString(); // SHA-256 해시를 적용한 결과 리턴
	}
}

 

 

'Block Chain' 카테고리의 다른 글

[Block Chain] Java 실습-2  (0) 2022.12.21
[Block Chain] Java 실습-1  (0) 2022.12.19
[Block Chain] 암호화폐  (0) 2022.12.01
[Block Chain] 해시  (0) 2022.12.01
[Block Chain] 쉽게 이해하기  (0) 2022.11.30

core > BlockChainStarter

package core;

public class BlockChainStarter {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Block block1 = new Block(1, null, 0, "데이터"); // 블록 아이디, 이전 블록의 해시 값, 채굴을 위한 정답, 블록에 들어가는 데이터
		block1.mine();
		block1.getInformation();
		
		Block block2 = new Block(2, block1.getBlockHash(), 0, "데이터");
		block2.mine();
		block2.getInformation();
		
		Block block3 = new Block(3, block2.getBlockHash(), 0, "데이터");
		block3.mine();
		block3.getInformation();
		
		Block block4 = new Block(4, block3.getBlockHash(), 0, "데이터");
		block4.mine();
		block4.getInformation();
	}
}

core > Block

package core;

import util.Util;

public class Block {

	private int blockID; // 블록 아이디
	private String previousBlockHash; // 이전 블록의 해시 값
	private int nonce; // 채굴을 위한 정답
	private String data; // 블록에 들어가는 데이터
	
	public Block(int blockID, String previousBlockHash, int nonce, String data) {
		this.blockID = blockID;
		this.previousBlockHash = previousBlockHash;
		this.nonce = nonce;
		this.data = data;
	}
	
	public int getBlockID() {
		return blockID;
	}
	
	public void setBlockID(int blockID) {
		this.blockID = blockID;
	}
	
	public String getPreviousBlockHash() {
		return previousBlockHash;
	}

	public void setPreviousBlockHash(String previousBlockHash) {
		this.previousBlockHash = previousBlockHash;
	}
	
	public int getNonce() {
		return nonce;
	}
	
	public void setNonce(int nonce) {
		this.nonce = nonce;
	}
	
	public String getData() {
		return data;
	}
	
	public void setData(String data) {
		this.data = data;
	}
	
	public String getBlockHash() { // 해당 블록의 해시 값
		return Util.getHash(nonce + data + previousBlockHash);
	}
	
	public void getInformation() { // 특정한 한 개의 블록이 있을 때 이 블록에 대한 정보를 출력
		System.out.println("----------------------------------");
		System.out.println("블록 아이디 : " + getBlockID());
		System.out.println("이전 블록의 해시 값: " + getPreviousBlockHash());
		System.out.println("채굴 정답 : " + getNonce());
		System.out.println("블록 데이터 : " + getData());
		System.out.println("블록의 해시 값 : " + getBlockHash());
		System.out.println("----------------------------------");
	}
	
	public void mine() {
		while(true) {
			if(getBlockHash().substring(0, 4).equals("0000")) { // nonce + data + previousBlockHash의 해시 값이 "0000"으로 시작할 때 채굴에 성공 // 채굴 난이도 고정
				System.out.println(blockID + "번째 블록의 채굴에 성공했습니다.");
				break;
			}
			nonce++;
		}
	}
}

util > Util

package util;

import java.security.MessageDigest;

public class Util {
	
	public static String getHash(String input) { // 단순 문자열 input
		StringBuffer result = new StringBuffer();
		
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-256"); // Secure Hash Algorithm // 256비트로 구성 // 64자리 문자열 반환
			md.update(input.getBytes());
			byte bytes[] = md.digest();
			
			for(int i = 0; i < bytes.length; i++) {
				result.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		return result.toString(); // SHA-256 해시를 적용한 결과 리턴
	}
}

 

<정상적인 경우>

<특정 블록의 데이터 변조>

 

<블록체인 해킹이 불가능한 이유>

1. 특정 블록의 데이터가 변조된다면 이후 모든 블록의 해시 값이 달라진다.

즉, 특정 블록의 데이터 변조를 위해서는 이후 모든 블록에 대한 채굴을 다시 수행해야 한다는 것

2. 이후 모든 블록에 대한 채굴을 다시 수행하여 이전에 발생했던 트랜잭션 정보를

변조하는데 성공했다고 하더라도 전체 네트워크에서 50% 이상의 컴퓨팅 파워를 갖고 있지 않은 이상

올바른 블록체인으로 인정받을 수 없다.

해커의 블록체인 vs 그 외 모든 사람들(과반수)의 블록체인 => 해커의 블록체인은 무시됨

'Block Chain' 카테고리의 다른 글

[Block Chain] Java 실습-3  (0) 2022.12.21
[Block Chain] Java 실습-1  (0) 2022.12.19
[Block Chain] 암호화폐  (0) 2022.12.01
[Block Chain] 해시  (0) 2022.12.01
[Block Chain] 쉽게 이해하기  (0) 2022.11.30

core > BlockChainStarter

package core;

import util.Util;

public class BlockChainStarter {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		// STEP 1. 해시 알고리즘은 입력 값이 조금만 바뀌어도 결과는 완전히 다른 값이 나온다. 채굴의 원리는 이러한 눈사태 효과에서 출발한다.
		System.out.println(Util.getHash("이승엽")); // 0c2bc0396e93dcc356680303162ced49c0fe2fed31ed1da7753113e413a2c06a
		System.out.println(Util.getHash("이승엽1")); // 55868675c69c4009a2dc5baa44b5326f93429b587b10828a622de61bca097bd7
		
		// STEP 2. 작업 증명(Proof of Work) : 비트코인에서 사용되고 있는 채굴 방식
		int nonce = 0;
		
		while(true) { // 채굴
			
			// 16진수 6자리 => 16 x 16 x 16 x 16 x 16 x 16 => 2의 24승(난이도)
			if(Util.getHash(nonce + "").substring(0, 6).equals("000000")) { // 어떠한 숫자 nonce를 문자열 형태로 바꾼 후 이것의 해시 값이 "000000"으로 시작할 때 채굴에 성공
				System.out.println("정답 : " + nonce); // 665782
				System.out.println("해시 값 : " + Util.getHash(nonce + "")); // 0000000399c6aea5ad0c709a9bc331a3ed6494702bd1d129d8c817a0257a1462
				break;
			}
			
			nonce++; // nonce 1씩 증가
		}
		// 작업 증명이라는 합의 알고리즘을 사용하는 블록체인 시스템은 이처럼 무작위의 입력값을 대입하여 정답(nonce)을 구하는 방식으로 채굴이 가능하도록 설계가 되어있다.
	}
}

util > Util

package util;

import java.security.MessageDigest;

public class Util {
	
	public static String getHash(String input) { // 단순 문자열 input
		StringBuffer result = new StringBuffer();
		
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-256"); // Secure Hash Algorithm // 256비트로 구성 // 64자리 문자열 반환
			md.update(input.getBytes());
			byte bytes[] = md.digest();
			
			for(int i = 0; i < bytes.length; i++) {
				result.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		return result.toString(); // SHA-256 해시를 적용한 결과 리턴
	}
}

 

 

'Block Chain' 카테고리의 다른 글

[Block Chain] Java 실습-3  (0) 2022.12.21
[Block Chain] Java 실습-2  (0) 2022.12.21
[Block Chain] 암호화폐  (0) 2022.12.01
[Block Chain] 해시  (0) 2022.12.01
[Block Chain] 쉽게 이해하기  (0) 2022.11.30

+ Recent posts