[11.25] 내일배움캠프[Spring] TIL-19

박상훈·2022년 11월 25일
0

내일배움캠프[TIL]

목록 보기
19/72

[11.25] 내일배움캠프[Spring] TIL-19

1. CS특강

  • Http, Https

1) IP
👉 인터넷에 연결되어 있는 모든 장치들(컴퓨터, 스마트폰...)을 식별할 수 있도록 각각 장비에 부여되는 고유주소
👉 인터넷에 연결되어 있는 모든 장비는 IP주소를 갖는다.
🚨 개인생각: 같은 인터넷을 사용하는 기기는 같은 IP주소를 갖게 되는데 발제 내용에는 각 장비에 부여되는 고유주소라고 서술했다. 사실 각 장비의 고유 주소는 MAC이라는 물리 주소가 아닌가..?

Ipv4Ipv6
주소길이32bit128bit
표시 방법4개 부분에서 8bit씩 10진수로표시(202.30.64.22)8개 부분에 16bit씩 16진수로 표시(2001:0203:abcd:ffff:0000:0000
주소 개수256x256x256x256 = 약 43억개약 43억 x 43억 x 43억 x 43억개

2) DNS( Domain Name System )
👉 IP주소를 사람들이 알기 쉽게 문자료 표현한 것

  • DNS의 IP정보 전송 방식

3) 포트(Port)
👉 운영체제통신에서 종단점을 뜻한다.
👉 IP Address를 통해 목적지 호스트까지 도달한 후에는 어떤 프로세스에서 데이터를 받을 것인지를 알아야하는데,
이 때 쓰이는 것이 포트번호이다.

구분포트 범위설명
잘 알려진 포트1 ~ 1023공식적으로 지정 되어있는거 있고 아닌거 있음( 80:http / 443:https )
등록된 포트1024 ~ 49151사용자가 직접 등록해서 사용할 수 있는 포트
동적 포트49152 ~ 65535매번 접속시 포트번호 변경, 인터넷이나 시스템 사용할 때 동적으로 할당하는 포트

4) 회선 통신
👉 옛날에 사용하던 회선교환 방식
👉 데이터 전송하는 시점의 트래픽, 혼잡도 등의 요인에 따라 효율이 달라지기 때문에 비효율적

5) 패킷 통신
👉 미리 이동경로를 정하지 않고, 데이터를 패킷이라는 작은 단위로 나누어 전송하는 방식
👉 전송될 데이터는 네트워크를 통해 전송되기 전에 패킷으로 쪼개지고, 각 패킷에는 고유 번호가 지정되어 있다.
👉 네트워크를 걸쳐 최종 수신지에 도착했을 때 번호 순서대로 결합되어 원래 데이터가 된다.
👉 회선 통신과는 다르게 각 패키은 전송 당시 가장 효율적인 경로를 설정하여 최종 목적지까지 이동하게 된다.
🚨 굳이 왜 패킷으로 나누지? 효율적인 경로만 파악해서 쏴주면 되는 것 아닌가?
🚨 데이터가 네트워크의 대역폭을 너무 많이 차지하기 때문! 다른 데이터의 흐름을 막을 위험이 있다!!

5) TCP / IP
👉 패킷을 안전하게 전달해주는 전송 프로토콜
👉 IP위에서 동작하고 데이터의 전달을 보장하고 순서도 보장한다.
👉 흐름제어 : 송신측과 수신측의 처리 속도 차이를 해결하기 위한 기법
👉 혼잡제어 : 송신측의 데이터 전달과 네트워크의 데이터 처리 속도 차이를 해결하기 위한 기법
👉 TCP 3 way - handshake : 두 종단간의 정확한 데이터 전송을 보장하기 위해 연결을 설정하는 과정
👉 TCP 4 way - handshake : 두 종단 간 데이터 전송을 끝낸 후 설정을 해제하는 과정

6) Http ( HyperText Transfer Protocol )
👉 클라이언트와 서버 간의 자원을 교환하기 위한 TCP/IP 기반 통신 프로토콜 (약속,규정)
👉 단방향성 : 서버가 먼저 응답을 보낼 수 없고 클라이언트가 요청을 보내야만 응답할 수 있다.
👉 비연결성 : 클라이언트의 요청으로 서버와 연결된 후, 요청에 대한 응답의 데이터를 전송하면 연결을 종료한다 -> 실시간 통신을 할 수 없음 -> 카카오톡과 같은 채팅 서비스 안됨
👉 문제점 : 도청이 가능함, 통신 상대가 검증된 상대인지 확인하지 않아서 위장이 가능, 변조가 가능
🚨 이러한 문제점 때문에 Https가 두두둥장!!

  • Http Method
    👉 클라이언트가 웹 서버에게 요청의 목적이나 종류를 알리는 수단
    👉 GET : 보통 리소스 조회시 사용, 서버에 전달하고 싶은 데이터는 Query를 통해서 전달
    👉 POST : 주로 리소스를 새롭게 생성할 때 사용, 서버에 전달하고 싶은 데이터 메세지 바디를 통해 전달
    👉 PUT : 리소스가 있으면 대체, 리소스가 없으면 생성, 데이터를 덮어쓴다.
    👉 PATCH : PUT과 마찬가지러 리소스를 수정할 때 사용하지만 , PATCH는 리소스를 일부만 변경할 때 사용
    👉 DELETE : 리소스를 제거할 때 사용
  • Http 상태코드
    👉 1xx : 요청시 수신되어 처리중
    👉 2xx : 요청 정상 처리
    👉 3xx : 요청을 완료하려면 추가 행동이 필요( 보통 리다이렉트 처리 )
    👉 4xx : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
    👉 5xx : 서버 오류
  • Http 통신 흐름
    1 ) 웹 브라우저에 URL입력
    2) 사용자가 입력한 URL주소 중 도메인 네임 부분을 DNS서버에 검색하고 DNS서버에서 해당 도메인 네임에
    해당하는 IP주소를 찾아온다.
    3) HTTP프로토콜을 사용하여 페이지 URL 정보와 찾아온 IP주소를 포함하는 HTTP요청 메세지를 생성하고,
    생성된 HTTP요청 메세지는 TCP프로토콜을 사용하여 인터넷 망을 통해 해당 IP주소의 컴퓨터로 전송된다.
    4) HTTP 요청 메세지를 받은 컴퓨터(서버)는 웹 페이지 URL 정보 중 PATH와 HTTP Method에 맞는 액션을 취한다.
    5) 생성된 응답 데이터는 또 다시 HTTP프로토콜을 사용하여 HTTP응답 메세지로 만들어지고 TCP프로토콜을 사용하여 인터넷 망을 통해 요청했던 컴퓨터(클라이언트)로 전송된다.
    6) 도착한 HTTP응답 메세지는 웹 브라우저에 의해 브라우저 렌더링 과정을 거쳐 화면에 출력되어 사용자가 볼 수 있게 된다.
  • Https
    👉 Http + Secure -> Http의 보안
    👉 SSL / TLS 프로토콜을 사용해 HTTP를 암호화하여 주고 받을 때 쓰는 통신 프로토콜
  • SSL / TLS HandShake

1) 서비스를 서빙하는 서버가 CA로부터 CA인증서를 발급받는다.

2) 브라우저에서 도메인을 쳐서 요청을 보내 클라이언트(브라우저)와 서버가 TCP연결을 맺는다.
3) 서버는 브라우저가 보내준 Cipher Suite중 하나를 고르고, 자신의 SSL/TLS 프로토콜 버전을 브라우저에게 알리면서, 서버 자신의 도메인에 대한 CA인증서를 보낸다.

4) 브라우저는 앞으로 서버와 통신하는데 있어 암호화를 위해 사용할 대칭키를 만들고, 그 대칭키를 사이트 공개 키로 암호화하여 서버로 보낸다.

5) 서버는 자신의 개인 키를 사용하여 암호화된 것을 복호화하여 사용자 대칭 키를 얻어낸다.

6) 이렇게 얻은 대칭 키를 활용하여 서버와 클라이언트가 서로 데이터를 안전하게 암/복호화 하면서 통신할 수 있게 된다.

2. 순수 java를 이용한 미니프로젝트 -2

  • 은행 관리 콘솔 프로그램을 구현하자
    👉 깃 허브 사용 ( 각자의 브렌치 따서 작업하고 합치기를 반복 )
    👉 현재까지 계좌 추가, 이름 or 계좌번호로 계좌를 검색하고 수정,삭제가 가능하다.
    👉 팀원 성재님과, 동규님이 입출금 관리를 담당하고 계신다.
  • 깃허브


    👉 아직 능숙하지는 않지만 나름 잘 진행되고 있다.
    👉 현재까지 이해한 깃허브의 개념은 이렇다.
    1) 공통 리파지토리를 만든다.
    2) 공통 리파지토리를 Clone해온다.
    3) 현재 branch는 main or master일 것인데, 맡은 파트가 있을테니 각자의 branch를 만들어 작업한다.
    4) local( 내 컴퓨터 )에 있는 new branch를 add -> commit -> push 한다.
    5) 공통 리파지토리에 origin/new branch가 생기며, main branch와 다른점이 있을 경우 merge할 거냐는 창이 뜬다.
    6) 여기서 merge를 진행하게 된다면 나의 수정사항이 공통 리파지토리에 올라간다.
    7) 다음 작업시에는 나의 local main branch에서 origin main branch를 pull 하고, new branch로 checkout해서 Merge 'main' into 'new branch'를 해주면 끝!
    8) 이렇게 해야 Conflict가 안나더라...
    9) 혹시 new branch에서 작업하다가 main branch를 pull 해와야하는 상황이 생긴다면, new branch는 꼭 commit해놓고 checkout할 것!!
  • App.java( main )
import service.Bank;
import vo.User;
import java.util.Scanner;
import java.util.regex.Pattern;

public class App {
//    private static final scan = new Scanner();
    Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            // main 화면, 각 클래스와 관련된 내용으로 연결되고 이후 접속 시 관련 메뉴를 한 번 더 볼 수 있도록 설정
            System.out.println("=== BankSystem에 오신 것을 환영합니다 ===");
            System.out.println("원하시는 메뉴에 해당하는 번호를 입력하세요.");
            System.out.println("1. 은행 관리 2. 거래내역 관리 3. 종료");
            int select = sc.nextInt();

            if (select == 3) {
                System.out.println("안녕히 가십시오");
                break;
            }

            switch (select) {
                case 1:
                    bankManager();
                    break;

                case 2:
                   moneyList();
                 break;

                default:
                    System.out.println("다시 입력해 주세요.");
                    break;

            }
        }
    }

    public static void bankManager() {
        Bank bank = Bank.getInstance();
        Scanner sc = new Scanner(System.in);
        while (true) {
            // 은행 관리자 화면
            System.out.println("=== 은행 관리 ===");
            System.out.println("원하시는 메뉴에 해당하는 번호를 입력하세요.");
            System.out.println("1. 계좌 등록 2. 출금/입금 3. 등록계좌 수정/삭제 4. 계좌 조회(소유자/계좌번호/전체) 5. 이전");
            int select = sc.nextInt();

            if (select == 5) {
                break;
            }
            switch (select) {
                case 1:
                    System.out.println("=== 계좌 등록 ===");
                    System.out.print("소유주 : ");
                    String name = sc.next();
                    String pattern = "[0-9,\\-]{3,6}\\-[0-9,\\-]{2,6}\\-[0-9,\\-]";
                    System.out.print("계좌번호( ex) xxx-xxxxxx-x ) : ");
                    String accountNum = sc.next();
                    if(!Pattern.matches(pattern,accountNum)){
                        System.out.println("계좌번호 형식이 틀렸습니다!");
                        return;
                    }
                    if(!bank.checkToUsableBankNum(accountNum)){
                        return;
                    }
                    System.out.print("계좌 비밀번호 설정 :");
                    String pwd = sc.next();
                    System.out.print("은행명 :");
                    String bankName = sc.next();

                    User user = new User(name,0,accountNum,bankName,pwd);

                    bank.addUser(user);
                    break;

                case 2:
                    System.out.println("=== 입출금 ===");
                    System.out.println("1. 입금 2. 출금");
                    int num = sc.nextInt();

                    if (num == 1) {
                        // 입금 메서드 호출
                    } else {
                        // 출금 메서드 호출
                    }

                    break;

                case 3:

                    System.out.println("=== 등록계좌 수정 및 삭제 ===");
                    System.out.println("1. 수정 2. 삭제");
                    int num2 = sc.nextInt();

                    if (num2 == 1) {
                        // 수정 메서드 호출
                        System.out.print("수정할 계좌번호를 입력하세요 :");
                        String updateAccountNum = sc.next();
                        // 입력한 계좌번호가 DB에 있는지 확인
                        if(!bank.confrimAccountNum(updateAccountNum)){
                            return;
                        }
                        System.out.print("계좌 비밀번호를 입력하세요 :");
                        String updatePwd = sc.next();
                        // 입력한 계좌의 비밀번호가 맞는지 확인
                        if(!bank.confrimAccountPwd(updateAccountNum,updatePwd)){
                            return;
                        }
                        System.out.println("수정할 정보를 선택하세요!");
                        System.out.println("1.소유주명, 2.은행");
                        int updateContentNum = sc.nextInt();

                        if(updateContentNum == 1){
                            // 소유주명 바꾸기
                            System.out.print("변경할 소유주명 :");
                            String updateUserName = sc.next();
                            bank.updateUserName(updateUserName,updateAccountNum);

                        }else if(updateContentNum == 2){
                            // 은행명 바꾸기
                            System.out.print("변경할 은행이름 :");
                            String updateBankName = sc.next();
                            bank.updateBankName(updateBankName,updateAccountNum);

                        }else{
                            System.out.println("잘못된 번호입니다!");
                        }


                    } else {
                        // 삭제 메서드 호출
                        System.out.print("삭제할 계좌번호를 입력하세요 :");
                        String deleteAccountNum = sc.next();
                        // 입력한 계좌번호가 DB에 있는지 확인
                        if(!bank.confrimAccountNum(deleteAccountNum)){
                            return;
                        }
                        System.out.print("계좌 비밀번호를 입력하세요 :");
                        String deletePwd = sc.next();
                        // 입력한 계좌의 비밀번호가 맞는지 확인
                        if(!bank.confrimAccountPwd(deleteAccountNum,deletePwd)){
                            return;
                        }
                        //삭제 메서드 호출
                        bank.deleteAccount(deleteAccountNum);
                    }
                    break;

                case 4:
                    System.out.println("=== 등록계좌 조회 ===");
                    System.out.println("1. 이름으로 조회 2. 계좌번호로 조회 3. 전체 조회");
                    int num3 = sc.nextInt();

                    if (num3 == 1) {
                        // 이름 조회 메서드 호출
                        System.out.print("조회하실 성함을 입력하세요 :");
                        String searchName = sc.next();

                        if(!bank.searchByUserName(searchName)){
                            return;
                        }

                    } else if (num3 == 2) {
                        // 계좌번호 조희 메서드 호출
                        System.out.print("조회하실 계좌번호를 입력하세요 :");
                        String serchAccountNum = sc.next();
                        if(!bank.confrimAccountNum(serchAccountNum)){
                            return;
                        }
                        if(!bank.searchByAccountNum(serchAccountNum)){
                            return;
                        }
                    } else if(num3 == 3) {
                        // 전체 조회 메서드 호출
                        bank.showAll();
                    }else{
                        System.out.println("잘못된 번호입니다!");
                    }
                    break;


                default:
                    System.out.println("다시 입력해 주세요.");
                    break;

            }
        }
    }
    public static void moneyList () {
        Scanner sc = new Scanner(System.in);
//        String accNum = 계좌번호 호출
        while (true) {
            // 입출금내역 관련 화면
            System.out.println("=== 거래내역 관리 ===");
            System.out.println("원하시는 메뉴에 해당하는 번호를 입력하세요.");
            System.out.println("1. 잔고 확인 2. 거래 내역 조회 3. 이전");
            int select = sc.nextInt();

            if (select == 3) {
                break;
            }

            switch (select) {
                case 1:
                    System.out.println("이름을 입력하세요");
                    String name = sc.nextLine();
//                    if ( name == 계좌 클래스의 이름) {
//                          return 이름;
//                          System.out.println(이름);
//                          System.out.println("당신의 계좌번호는 : " + accNum);
//                          break;
//                    }
                    System.out.println("비밀번호를 입력하세요.");
//                    System.out.println("현재 잔액은 " + 잔액 + " 원 입니다.");
//                    비밀번호를 틀릴 경우
                    break;

                case 2:
                    System.out.println("이름을 입력하세요");
                    String name2 = sc.nextLine();
//                    if ( name2 == 계좌 클래스의 이름) { // 계좌번호를 키로 한 거래내역 클래스에 접근
//                          return 이름;
//                          System.out.println(이름);
//                          System.out.println("당신의 계좌번호는 : " + accNum);
//                          break;
//                    }
//                    거래내역 조회 메서드
                    break;

                default:
                    System.out.println("다시 입력해 주세요.");
                    break;

            }
        }
    }

    public static void userInfo () {
        // 유저정보 관련화면
        System.out.println("=== USER 정보 ===");
    }
}
  • Bank.java( DB CRUD )
package service;


import org.w3c.dom.ls.LSOutput;
import vo.User;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Bank {

    private final static Bank bank = new Bank();
    private List<User> userList = new ArrayList<>();
    //private List<Account> account = new ArrayList<>();

    //Bank하나의 객체를 유지하기 위한 메서드
    public static Bank getInstance(){

        if(bank == null){
            return new Bank();
        }
        return bank;
    }
    //유저의 정보를 저장하는 부분
    public void addUser(User user){
        System.out.println("은행 정보가 정상적으로 저장되었습니다.");
        userList.add(user);
    }

    public void showAll(){
        for(int i=0;i<userList.size();i++){
            System.out.println("------------");
            System.out.print(userList.get(i).getName()+"님 ");
            System.out.println(userList.get(i).getAccountNum()+" ");
            System.out.println(userList.get(i).getStock()+"원 ");
            System.out.println(userList.get(i).getBankName()+" 은행");
        }
    }

    public boolean checkToUsableBankNum(String bankNum){

        if(userList.stream().anyMatch(s->s.getAccountNum().equals(bankNum))){
            System.out.println("이미 등록된 계좌번호입니다!");
            return false;
        }
        return true;
    }

    public boolean confrimAccountNum(String inputAccountNum){

        if(userList.stream().anyMatch(s -> s.getAccountNum().equals(inputAccountNum))){
            return true;
        }
        System.out.println("존재하지 않는 계좌번호입니다!");
        return false;
    }

    public boolean confrimAccountPwd(String inputAccountNum, String pwd){

        Stream<User> userInfo = userList.stream().filter(s -> s.getAccountNum().equals(inputAccountNum));


        if(userInfo.anyMatch(s -> s.getPwd().equals(pwd))){
            return true;
        }
        System.out.println("계좌의 비밀번호가 틀립니다!");
        return false;

    }

    public void updateUserName(String updateUserName,String inputAccountNum){

        for(int i=0 ; i<userList.size();i++){
            if(userList.get(i).getAccountNum().equals(inputAccountNum)){
                String previousUserName = userList.get(i).getName();
                userList.get(i).setName(updateUserName);
                String presentUserName = userList.get(i).getName();
                System.out.println(previousUserName+"님에서 "+presentUserName+"님으로 변경되었습니다!");
                break;
            }
        }
    }

    public void updateBankName(String updateBankName,String inputAccountNum){

        for(int i=0 ; i<userList.size();i++){
            if(userList.get(i).getAccountNum().equals(inputAccountNum)){
                String previousBankName = userList.get(i).getBankName();
                userList.get(i).setBankName(updateBankName);
                String presentBankName = userList.get(i).getBankName();
                System.out.println(previousBankName+"은행에서  "+presentBankName+"은행으로 변경되었습니다!");
                break;
            }
        }
    }

    public void deleteAccount(String inputAccountNum){
        for(int i=0 ; i<userList.size();i++){
            if(userList.get(i).getAccountNum().equals(inputAccountNum)){
                String presentBankName = userList.get(i).getName();
                userList.remove(i);
                System.out.println(presentBankName+"님의  "+inputAccountNum+" 계좌가 삭제되었습니다!!");
                break;
            }
        }
    }

    public boolean searchByUserName(String searchUserName){
        Stream<User> searchUser = userList.stream().filter(s -> s.getName().equals(searchUserName));
        //위에 선언한 스트림으로 공백일 때 계좌 없다고 하고 싶은데 필터로 찾지 못해도 무슨 값이 담기는지 봐도 모르겠음..!!
        if(!userList.stream().anyMatch(s -> s.getName().equals(searchUserName))){
            System.out.println(searchUserName+"님으로 등록된 계좌가 없습니다!");
            return false;
        }
        searchUser.forEach(u -> System.out.println("--------\n"+u.getName()+" "+u.getAccountNum()+ " \n"+u.getStock()+"원 \n"+u.getBankName()+" 은행"));
        return true;
    }

    public boolean searchByAccountNum(String searchAccountNum){
        Stream<User> searchUser = userList.stream().filter(s -> s.getAccountNum().equals(searchAccountNum));
        //위에 선언한 스트림으로 공백일 때 계좌 없다고 하고 싶은데 필터로 찾지 못해도 무슨 값이 담기는지 봐도 모르겠음..!!
        if(!userList.stream().anyMatch(s -> s.getAccountNum().equals(searchAccountNum))){
            System.out.println(searchAccountNum+"번호로 등록된 계좌가 없습니다!");
            return false;
        }
        searchUser.forEach(u -> System.out.println("--------\n"+u.getName()+" "+u.getAccountNum()+ " \n"+u.getStock()+"원 \n"+u.getBankName()+" 은행"));
        return true;
    }

}
  • User.java( Vo )
package vo;
public class User {

    private String name; //유저 이름
    private int stock;   //
    private String accountNum;  //계좌번호
    private String bankName;   //은행명
    private String pwd;       //비밀번호

    public User(String name,int stock ,String accountNum, String bankName, String pwd) {
        this.name = name;
        this.stock = stock;
        this.accountNum = accountNum;
        this.bankName = bankName;
        this.pwd = pwd;
    }

    public void setStock(int stock) {
        this.stock = stock;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBankName(String bankName) {
        this.bankName = bankName;
    }

    public String getName() {
        return name;
    }

    public int getStock() {
        return stock;
    }

    public String getAccountNum() {
        return accountNum;
    }

    public String getBankName() {
        return bankName;
    }

    public String getPwd() {
        return pwd;
    }
}
  • Account.java ( 팀원 분들이 작성 중 추후 업로드 예정)

3. 아쉬운점, 느낀점⭐

1) App.java, Bank.java 를 더 줄일 수 있을 것 같다.
2) 간단한 기능을 구현하는데 이렇게 많은 코드 줄이 필요가 있나 싶긴하다.
3) 은행마다 고유 계좌 번호가 있는데 입력 받았을 때 그것을 판별하여 은행명을 자동으로 판단하여 저장하는 로직을 구현해보고싶다.
4) DB 즉List<> 를 두개 만들어서 해보자 라는 제안을 바탕으로 작업하고 있는데, 나의 생각 때문에 다른 길로 가는 것은 아닌지 불안하다.
5) 깃 허브 사용에 능숙해지자!

profile
기록하는 습관

0개의 댓글