[Routine] 9 주차 시작!

[Routine] 9 주차 시작!

2023년 3월 13일 부터 3월 19일 까지의 나의 루틴.

#목차

2023-03-13

2023-03-13

  • 오늘도 어김없이 영한 님의 인강을 들으면서 출근하였다.
  • 저번 주 주말 내내 이것이 자바다 공부를 했는데 문득 드는 생각이 너무 정리하면서 공부하려고 해서 늦어지는거 같다는 생각이 들었다.
  • 정말 중요하거나 블로그에 적어야할 거 같은 내용만 적고 무슨 챕터를 진행했는지만 블로그에 적으려 한다.

데이터 입출력

성능 향상 스트림

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;

public class Example {
    BufferedInputStream bis = new BufferedInputStream(/* 바이트 입력 스트림 */);
    BufferedOutputStream bos = new BufferedOutputStream(/* 바이트 출력 스트림 */);

    BufferedReader br = new BufferedReader(/* 문자 입력 스트림 */);
    BufferedWriter bw = new BufferedWriter(/* 문자 출력 스트림 */);
}

Continue with Buffer Commit

import java.io.BufferedReader;
import java.io.FileReader;

public class Example {
    BufferedReader br = new BufferedReader(new FileReader("file path"));
    while (true) {
        String str = br.readLine();  // 파일에서 한 행씩 읽음
        if (str == null) break;     // 더 이상 읽을 행이 없을 경우(파일 끝) while 문 종료
    }
}

Continue with BufferReader Commit

기본 타입 스트림

import java.io.DataInputStream;
import java.io.DataOutputStream;

public class Example {
    DataInputStream dis = new DataInputStream(/* 바이트 입력 스트림 */);
    DataOutputStream dos = new DataOutputStream(/* 바이트 출력 스트림 */);
}

Continue with DataInputOutputStream Commit

프린트 스트림

import java.io.PrintStream;
import java.io.PrintWriter;

public class Example {
    PrintStream ps = new PrintStream(/* 바이트 출력 스트림 */);
    PrintWriter pw = new PrintWriter(/* 문자 출력 스트림 */);
}

Continue with PrintStream Commit

객체 스트림

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Example {
    ObjectInputStream ois = new ObjectInputStream(/* 바이트 입력 스트림 */);
    ObjectOutputStream oos = new ObjectOutputStream(/* 바이트 출력 스트림 */);
    
    // writeObject로 객체를 직렬화
    // oos.writeObject(/* 객체 */);
    
    // readObject로 역직열화
    // 객체타입 변수 = (객체타입) ois.readObject();
}

Continue with ObjectInputOutputStream Commit


2023-03-14

2023-03-14

  • 오늘도 어김없이 영한 님의 인강을 들으면서 출근하였다.
  • 얼른 이것이 자바다를 끝내고 영한님의 인강을 들으면서 코드를 치면서 정리해보고 싶다는 생각이 들었다.

데이터 입출력

성능 향상 스트림

Serializable 인터페이스
  • 자바 직렬화란 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술바이트로 변환된 데이터를 다시 객체로 변환하는 기술(역직렬화)을 아울러서 이야기한다.
  • 시스템적으로 이야기하자면 JVM(Java Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 같이 이야기한다.
import java.io.Serializable;

public class Example implements Serializable {
    // 직렬화 : 일렬로 늘어선 바이트 데이터 => | field1 | field2 | field3 | field14 |
    public int field1;
    protected int filed2;
    int filed3;
    private int filed4;
    
    public static int filed5;   // 정적 필드는 직려로하에서 제외
    transient int filed6;       // transient로 선언된 필드는 직렬화에서 제외

}
serialVersionUID 필드
  • 직렬화할 때 사용된 클래스와 역직렬화할 때 사용된 클래스는 기본적으로 동일한 클래스여야 한다.
  • 만약 클래스의 이름이 같더라도 클래스의 내용이 다르면 역직렬화에 실패한다.
import java.io.Serializable;

public class Example implements Serializable {
    int filed1;
    int filed2;
}
예) Member 클래스로 생성한 객체를 직렬화하면
오른쪽 Member 클래스로 역직렬화 할 수 없다.
—X—>그 이유는 오른쪽 Member 클래스에는
filed3이 있기 때문이다.
public class Member
   implements Serializable {
   int file1;
   int filed2
}
—X—>public class Member
   implements Serializable {
   int filed1;
   int filed2;
   int filed3;
}
  • 클래스 내용이 다르다 할지라도 직렬화된 필드를 공통으로 포함하고 있다면 역직렬화할 수 있는 방법이 있다.
  • 두 클래스가 동일한 serialVersionUID 상수값을 가지고 있으면 된다.
   
public class Member
   implements Serializable {
   static final long
      derialVersionUID = 1;
   int filed1;
   int filed2;
}
—O—>public class Member
   implements Serializable {
   static final long
      serialVersionUID = 1;
   int filed1;
   int filed2;
   int filed3}

File과 Files 클래스

File 클래스
import java.io.File;

public class Example {
    File file = new File("path");
    
    // max path : /
    File macFile = new File("user/dev/thisisjava/test.txt");
    
    // window path : \\ or /
    File windowFile1 = new File("C:/Temp/file.txt");
    File windowFile2 = new File("C:\\Temp\\file.txt");
    
    // 파일이나 폴더가 존재한다면 true를 리턴
    boolean isExist = file.exists();
}

Continue with File Class Commit

입출력 스트림을 생성할 때 File 객체 활용하기
  • 파일 또는 폴더의 정보를 얻기 위해 File 객체를 단독으로 사용할 수 있지만, 파일입출력 스트림을 생성할 때 경로 정보를 제공할 목적으로 사용되기도 한다.
import java.io.File;
import java.io.FileInputStream;

public class Example {
    // 첫 번째 방법
    FileInputStream fis = new FileInputStream("filepath");
    // 두 번째 방법
    File file = new File("filepath");
    FileInputStream fileFis = new FileInputStream(file); 
}
Files 클래스
  • Files 클래스는 정적 메서드로 구성되어 있고, File 보다 좀 더 많은 기능을 제공한다.
public class Example {
    Path path = Path.get(String first, String... more);

    // 예)
    Path path = Path.get("C:/Temp/dir/file.txt");
    Path path = Path.get("C:/Temp/dir", "file.txt");
    Path path = Path.get("C", "Temp", "dir", "file.txt");

    // 절대 경로와 상대 경로
    Path path = Path.get("dir/file.txt");
    Path path = Path.get("./dir/file.txt"); 
    Path path = Path.get("../dir/file.txt"); 
    
}

Continue with Files Class Commit

네트워크 입출력

네트워크 기초

  • LANLocal Area Network은 가정, 회사, 건물, 특정 여역에 존재하는 컴퓨터를 연결하는 것이다.
  • WANWide Area NetworkLAN을 연결한 것으로, 쉽게 말해 인터넷Internet이다
서버와 클라이언트
  • 서비스를 제공하는 프로그램을 일반적으로 서버Server라고 한다.
  • 서비스를 요청하는 프로그램을 클라이언트Client라고 한다.
  • 인터넷에 두 프로그램이 통신하기 위해서는 먼저 클라이언트가 서비스를 요청하고, 서버는 처리결과를 응답으로 제공해준다.
IP 주소
  • IPInternet Protocol는 컴퓨터의 고유한 주소이다.
  • Mac에서는 ifconfig, Window에서는 ipconfig를 터미널/CMD창에서 검색하게 되면 ip 정보를 볼 수 있다.
  • DNSDomain Name System는 도메인 이름으로, IP를 등록하는 저장소이고, 컴퓨터의 IP 주소를 검색한다.
  • 대중에게 서비스를 제공하는 대부분의 컴퓨터는 다음과 같이 도메인 이름으로 IP를 미리 DNS에 미리 등록해 놓는다.
도메인 이름IP주소
www.naver.com222.122.195.5
  • 웹 브라우전즌 웹 서버와 통신하는 클라이언트로, 상요자가 입력한 도메인 이름으로 DNS에서 IP 주소를 검색해 찾는 다음 웹 서버와 연결해서 웹 페이지를 받는다.

2023-03-15

2023-03-15

  • 오늘도 어김없이 영한 님과…🤩

네트워크 입출력

네트워크 기초

Port 번호
  • Port는 운영체제가 관리하는 서버 프로그램의 연결 번호이다.
  • 서버는 시작할 때 특정 Port 번호에 바인딩 한다.
  • 클라이언트도 서버에서 보낸 정보를 받기 위해서는 Port 번호가 필요한데, 서버와 같이 고정적인 Port 번호에 바인딩하는 것이 아니라 운영체제가 자동으로 부여하는 번호를 사용한다.
  • 이 번호는 클라이언트가 서버로 요청할 때 함게 전송되어 서버가 클라이언트로 데이터를 보낼 때 사용된다.

IP 주소 얻기

  • JavaIP 주소를 java.net 패키지의 InetAddress로 표현한다.
  • InetAddress를 이용하면 로컬 컴퓨터의 IP 주소를 얻을 수 있고, 도메인 이름으로 DNS에서 검색한 후 IP 주소를 가져올 수도 있다.
import java.net.InetAddress;

public class Example {
    // local 컴퓨터의 InetAddress를 얻고 싶을 때
    InetAddress is = InetAddress.getLocalHost();
    
    // 컴퓨터의 도메인 이름을 알고 있다면 두 개의 메서드를 사용하여 InetAddress 객체를 얻을 수 있다.
    InetAddress is = InetAddress.getByName(String domainName);          // 단 하나의 IP 주소를 get
    InetAddress[] iaArr = InetAddress.getAllByName(String domainName);  // 등록된 모든 IP 주소를 배열로 get
    
    // 위 메서드들로부터 얻은 InetAddress 객체에서 IP 주소를 얻고 싶을 때
    String ip = InetAddress.getHostAddress();
}

Continue with IP 주소 얻기 Commit

TCP 네트워킹

  • IP 주소로 프로그램들이 통신할 때는 약속된 데이터 전송 규약이 있다. 이것을 전송용 프로토콜Protocol이라고 부른다.
  • 인터넷 에서 전송용 프로토콜은 TCPTransmission Control ProtocolUDPUser Datagram Protocol가 있다.
  • TCP는 연결형 프로토콜로, 상대방이 연결된 상태에서 데이터를 주고 바는다.
  • TCP는 보낸 데이터가 순서대로 전달되며 손실이 발생하지 않는다.
  • TCP는 웹 브라우저가 웹 서버에 연결할 때 사용되며 이메일 전송, 파일 전송, DB 연동에도 사용된다.
  • JavaTCP 네트워킹을 위해 java.net 패키지에서 ServerSocketSocket 클래스를 제공하고 있다.
  • ServerSocket은 클라이언트의 연결을 수학하는 서버 쪽 클래스이고, Socket은 클라이언트에서 연결 요청할 때와 클라이언트와 서버 양쪽에서 데이터를 주고 받을 대 사용되는 클래스이다.
TCP 서버
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Example {
    // 50001번의 port에 바인딩
    ServerSocket serverSocket = new ServerSocket(50001);

    // 기본 생성자로 객체를 생서하고 port 바인딩을 위해 bind() 메서드를 호출
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(new

    InetSocketAddress(50001));

    // 서버 컴퓨터에 여러 개의 IP가 할당되어 있을 경우, 특정 IP에서만 서비스를 하고 싶다면
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(new

    InetSocketAddress("xxx.xxx.xxx.xxx",50001));

    // ServerSocket이 생성되었다면 연결 요청을 수락하기 위해 accept() 메서드를 실행
    Socket socket = serverSocket.accept();
    
    // return된 Socket을 통해 연결된 클라이언트의 IP 주소와 Port 번호를 얻고 싶다면
    InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
    String clientIp = isa.getHostName();
    String portNo = isa.getPort();
    
    // 서버를 종료하려면 close()
    serverSocket.close();
}

Continue with TCP 서버 Commit

TCP 클라이언트
  • 클라이언트가 서버에 연결 요청을 하려면 Socket 객체를 생성할 때 생성자 매개값으로 서버 IP 주소와 Port 번호를 제공하면 된다.
  • 로컬 컴퓨터에서 실행하는 서버로 연결 요청을 할 경우에는 IP 주소 대신 localhost를 사용할 수 있다.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Example {
    Socket socket = new Socket("IP", 50001);

    // IP 주소 대신 도메인 이름을 사용하고 싶다면, DNS에서 IP 주소를 검색할 수 있도록 생성자 매개값으로 InetSocketAddress를 제공
    Socket socket = new Socket(new InetSocketAddress("domainName", 50001));

    // Socket 생성과 동시에 연결 요청을 하지 않고 기본 생성자로 Socket을 생성한 후 connect() 메서드로 연결 요청할 수도 있다.
    Socket socket = new Socket();
    socket.connect(new

    InetSocketAddress("domainName",50001));

    // 연결 요청 시 두 가지 예뵈가 발생할 수 있다.
    // UnknownHostException은 IP 주소가 잘못 표기 되었을 때 발생
    // IOException 제공된 IP와 port 번호로 연결할 수 없을 때 발생
    // 따라서 두 가지 예외 모두 처리해야 한다
    try {
        Socket socket = new Socket("IP", 50001);
    } catch(UnknownHostException e) {
        // IP 표기 방법이 잘못되었을 경우
        e.printStackTrace();
    } catch(IOException e) {
        // IP와 Port로 서버에 연결할 수 없는 경우
        e.printStackTrace();
    }
    
    // 서버와 연결된 후에 클라이언트에서 연결을 끊고 싶다면
    socket.close();
}

Continue with TCP 클라이언트 Commit

입출력 스트림으로 데이터 주고 받기
  • 클라이언트가 연결 요청(connect())을 하고 서버가 연결을 수락(accept())했다면 클라이언트와 서버의 양쪽 Socket 객체로부터 가각 입력 스트림InputStream과 출력 스트림스트림OutputStream을 얻을 수 있다.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Example {
    Socket socket = new Socket();
    InputStream is = socket.getInputStream();
    OutputStream os = socket.getOutputStream();

    // UTF-8로 인코딩 후 바이트 배열을 얻어내고, write() 메서드로 전송
    String data = "보낼 데이터";
    byte[] bytes = data.getBytes("UTF-8");
    os.write(bytes);
    os.flush();

    // 문자열을 좀 더 간편하게 보내고 싶다면 보조 스트림인 DataOutputStream을 사용
    DataInputStream dos = new DataOutputStream(socket.getOutputStream());
    dos.writeUTF(data);
    dos.flush();
    
    // 받는 데이터가 문자열이라면
    byte[] bytes = new byte[1024];
    int num = is.read(bytes);
    String data = new String(bytes, 0, num, "UTF-8");
    
    // 해당 방법은 상대방이 DataOutputStream으로 문자열을 보낼 때만 가능
    DataInputStream dis = new DataInputStream(socket.getInputStream());
    String data = dis.readUTF();
}

Continue with 입출력 스트림으로 데이터 주고 받기 Commit


2023-03-16

  • 오늘은 병원 외래 진료 때문에 휴가이다~~🥳🥳🥳

데이터 입출력

UDT 네트워킹

  • UDPUser Datagram Protocol는 발신자가 일방적으로 수신자에세 데이터를 보내는 방식.
  • TCP 처럼 연결 요청 및 수락 과정이 없기 때문에 TCP보다 데이터 전송 속도가 상대적으로 빠르다.
  • JavaUDP 네트어킹을 위해 java.net 패키지에서 DatagramSocketDatagramPacket 클래스를 제공하고 있다.
  • DatagramSocket은 발신점과 수신점에 해당하고 DatagramPacket은 주고 받는 데이터에 해당한다.
UDP 서버
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;

public class Example {
    // DatagramSocket 객체 생성과 port 번호 생성자 매개값
    DatagramSocket datagramSocket = new DatagramSocket(50001);

    // UDP 서버는 클라이언트가 보낸 DatagramPacket을 항상 받을 준비를 해야 한다. 이 역할을 하는 메서드가 receive()이다
    DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
    datagramSocket.receive(receivePacket);

    // 수신된 데이터와 바이트 수를 얻는 방법 및 문자열
    byte[] bytes = receivePacket.getData();
    int num = receivePacket.getLength();
    String data = new String(bytes, 0, num, "UTF-8");

    // getSocketAddress() 메서드를 호출하면 정보가 담긴 SocketAddress 객체를 얻을 수 있다.
    SocketAddress socketAddress = receivePacket.getSocketAddress();
    
    // 클라이언트로 보맬 Datagrampacket을 생성할 때 네 번째 매개값으로 사용
    String data = "처리 내용";
    byte[] bytes = data.getBytes("UTF-8");
    DatagramPacket sendPacket = new DatagramPacket(bytes, 0, bytes.length, socketAddress);
    
    // 클라이언트에 보낼 때
    datagramSocket.send(sendPacket);
    
    // UDP 종료
    datagramSocket.close();
}
UDP 클라이언트
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class Example {
    // 기본생성자
    DatagramSocket datagramSocket = new DatagramSocket();

    // 요청을 보내기 위한 DatagramPacket을 생성
    String data = "요청 데이터";
    byte[] bytes = data.getBytes("UTF-8");
    DatagramPacket sendPacket = new DatagramPacket(
            bytes, bytes.length, new InetSocketAddress("localhost", 50001)
    );
    
    // UDP 서버로 전송
    datagramSocket.send(sendPacket);
    
    // close();
    datagramSocket.close();
}

Continue with UDP 서버/클라이언트 Commit

서버의 동시 요청 처리

TCP EchoServer 동시 요청 처리

Continue with TCP 동시 요청 처리 Commit

UDP NewsServer 동시 요청 처리

Continue with UDP 동시 요청 처리 Commit

JSON 데이터 형식

  • 네트워크 통신에서 가장 많이 사용되는 데이터 형식은 JSON`JavaScript Object Notation이다.
표기code설명
객체 표기{
    "속성명": 속성값,
    "속성명": 속성값,
    ···
}
속성명: 반드시"로 감싸야 함
속성값으로 가능한 것
- "문자열", 숫자, true/false
- 객체{···}
- 배열[···]
객체 표기[항목, 항목, ···]항목으로 가능한 것
- "문자열", 숫자, true/false
- 객체{…}
- 배열[…]
{
  "id": "spring",
  "name": "여름",
  "age": 25,
  "student": true,
  "tel": {
    "home": "02-1234-1234",
    "mobile": "010-1234-1234",
    "skill": [
      "java",
      "spring"
    ]
  }
}

데이터베이스 입출력

JDBC 개요

  • Java는 데이터베이스(DB)와 연결해서 데이터 입출력 작업을 할 수 있도록 JDBCJava Database Connectivity 라이브러리(java.sql 패키지)를 제공한다.

애플리케이션
         V
JDBC(java.sql패키지) 인터페이스
         V
JDBC Driver —> ORACLE DATABASE
JDBC Driver —> MySQL
JDBC Driver —> MariaDB
JDBC Driver —> SQL Server

  • DriverManager : JDBC Driver를 관리하며 DB와 연결해서 Connection 구현 객체를 생성한다.
  • Connection : Statement, PreparedStatement, CallableStatement 구현 객체를 생성하며, 트랜잭션Transaction 처리 및 DB 연결을 끊을 때 사용한다.
  • Statement : SQLDDLData Definition LanguageDMLData Manipulation Language을 실행할 때 사용한다. 주로 변경되지 않은 정적 SQL 문을 실행할 때 사용한다.
  • PreparedStatement : Statement와 동일하게 SQLDDL, DML 문을 실행할 때 사용한다. 차이점은 매개변수화된 SQL 문을 사용할 수 있기 때문에 편리성과 보안성이 좋다. 그래서 Statement보다는 PreparedStatement를 주로 사용한다.
  • CallableStatement : DB에 저장되어 있는 프로시저procedure와 함수function를 호출할 때 사용한다.
  • ResultSet : DB에서 가져온 데이터를 일을 때 사용한다.

프로시저와 함수 호출

  • 프로시저와 함수는 DB에 저장되는 PL/SQL 프로그램이다.
  • 클라이언트 프로그램에서 매개값과 함께 프로시저 또는 함수를 호출하면 DB 내부에서 일련의 SQL 문을 실행하고, 실행 결과를 클라이언트 프로그램으로 돌려주는 역할을 한다.
import java.sql.CallableStatement;
import java.sql.Connection;

public class Example {
    public static void main(String[] args) {
        Connection conn = null;
        // 프로시저를 호출할 경우
        String sql = "{ call 프로시저명(?, ?, ?)}";
        CallableStatement cstmt = conn.prepareCall(sql);
        cstmt.setString(1, "값");                // 프로시저 첫 번째 매개값
        cstmt.setString(2, "값");                // 프로시저 두 번째 매개값
        cstmt.registerOutParameter(3, 리턴타입);    // 세 번째 ?는 OUT값(리턴값)임을 지정

        // 함수를 호출할 경우
        String sql = "{ ? =  call 함수명(?, ?)}";
        CallableStatement cstmt = conn.prepareCall(sql);
        cstmt.registerOutParameter(1, 리턴타입);    // 첫 번째 ?는 리턴값을 지정
        cstmt.setString(2, "값");                // 함수의 두 번째 매개값
        cstmt.setString(3, "값");                // 함수의 세 번째 매개값
        
        // 프로시저 또는 함수를 호출하기 위해
        cstmt.execute();
        
        int result = cstmt.getInt(3);   // 프로시저
        int result = cstmt.getInt(1);   // 함수
        
        // 종료
        cstmt.close();
    }
}

트랜잭션 처리

  • 트랜잭션transaction은 기능 처리의 최소 단위를 말한다.
  • 하나의 기능은 여러 가지 소작업들로 구성된다.
  • 최소 단위라는 것이 이 소작업들을 분리할 수 없으며, 전체를 하나로 본다는 개념이다.
  • 트랜잭션은 소작업들이 모두 성공하거나 실패해야 한다.
// 출금 작업
UPDATE accounts SET balance=balance-이체금액 WHERE ano=출금계좌번호

// 입금 작업
UPDATE accounts SET balance=balance-이체금액 WHERE ano=입금계좌번호

  • 드디어 이것이자바다를 다 읽었다… 🥳🥳🥳
  • 이제 다른거 읽어야징~~

2023-03-17

2023-03-17

2023-03-18

  • 블로그의 미완성 부분들을 모두 주석하였다.
  • 차근차근 기존 포스팅했던 내용들을 다듬어 수정할 계획이다.

2023-03-19

  • 오늘은 여자친구와 만나 여자친구는 일을… 난 개인 공부를 진행하였다.
  • 항상 대중교통을 이용하여 이동할 때는 인강을 듣고 이동하는데, 영한 님의 인강을 들을 때마다 IntelliJ 단축키를 스타크래프트 프로게이머처럼 사용하고 싶다는 생각이 들곤 했다.
  • 그런데 오늘 인프런에 찾아보니까 향로님이 올려주신 IntelliJ에 관한 영상이 있어서 해당 영상을 참고해야겠다는 생각이 들었다.

Reference

Back to [Routine] 8 주차 시작!

Continue with [Routine] 10 주차 시작!