공부의 기록/자바 풀 스택 : 수업내용정리

자바 풀 스택 12/26 오전 기록 025-1

파티피플지선 2024. 12. 26. 13:17

9:15경 학원 도착

엊그제 하다가 간거 다시 시도해보려고 함... 실패 ㅎ

 

<9:30 1교시>

엊그제 작업하던 깃허브 공동작업 공간에 리셋된 것에 다시 만들어서 추가하는데 2빠로 성공 ㅎㅎ

vs code로 git 작업하면 생각보다 자동화 되어 있는게 편리하긴 한데, 따로 작업할 때는 아무래도 각자 올리게 되니까 시간에 쫓겨서 할 필요 없고, 이제 2빠는 했으니까 나머지 시간에는 공부한다 생각하고 천천히 올려봐야겠다.

 

이번에는 git bash 이용해서 올려봐야지.는 그냥 또 vs code로 해버렸는데 너무 편하네;;;

 

머릿속에 이미지를 그려보자.

 

맨 처음 공동 작업 장의 사진을 내려 받을 때에는 내 컴퓨터에 새로 추가되거나 변경되어서 지저분한 가지 상태가 아니어야 함.

그래서 혹시라도 변경된 사항이 있다면 commit을 해 놓은 상태에서 공동작업장의 사진들을 내려 받아야 함.

pull로 작업장 내용을 전부 내려 받았다면 merge를 시도하는데, 이때 merge하느라 발생한 충돌을 해결할 필요가 있을 수 있다.

충돌을 해결하고 내가 올리고 싶은 사진을 만든 상태라면 다시 stage에 올려서 commit을 진행하고 push로 공동작업장에 올리는데, 이때 내가 위의 작업을 하는 동안 다른 누군가가 자신의 작업을 push 한 상태라면 위의 내용을 다시 반복해서 진행하면 된다.

 

아무튼 1교시는 또 이렇게 git 관련한 내용을 해보았...

쉬는 시간에다른 수강생이 터미널로 git 하는거 옆에서 거들었는데 위에 내용이 어쨋든 핵심인듯...

 

 

<10:30 2교시>

어제 오후에 못 했던거 답 알려주심... 아쉽다 ㅠㅠ 접근 방법은 맞았는데 아직 식을 쓰거나 대입하는게 서툰 부분이 있다.

더보기
package test.frame05;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MyFrame extends JFrame {
	JTextArea ta=new JTextArea();
	//생성자
	public MyFrame() {
		//프레임 제목
		this.setTitle("나의 프레임");
		//프레임 위치와 크기 설정 setBounds(x, y, width, height)
		setBounds(100,100,500,500);
		//종료 버튼을 눌렀을 때 프로세스 전체가 종료되도록 하기
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		//레이아웃 메니저 객체 생성
		BorderLayout layout =new BorderLayout();
		//프레임의 레이아웃 메니저 설정
		setLayout(layout);
		
		//TextField 와 Button을 배치할 패널객체
		JPanel topPanel=new JPanel();
		topPanel.setBackground(Color.red);
		//TextField와 Button을 생성해서
		JTextField inputMsg= new JTextField(30);
		JButton sendBtn=new JButton("전송");
		//Panel에 추가
		topPanel.add(inputMsg);
		topPanel.add(sendBtn);
		//프레임의 위쪽에 패널 추가
		add(topPanel, BorderLayout.NORTH);
		
		
		ta=new JTextArea();
		//textarea를 스크롤 패널에 감싼다
		JScrollPane scroll = new JScrollPane(ta);
		//프레임의 가운데에 TextArea 추가
		Font font=new Font("Times New Roman", Font.BOLD, 20);
		ta.setFont(font);
		add(scroll, BorderLayout.CENTER);
		sendBtn.addActionListener((event)->{
			//TextField 에 입력한 문자열을 읽어온다.
			String msg=inputMsg.getText();
			//미리 준비된 메소드를 호출하면서 입력한 문자열을 등록함
			request(msg);			
		});
		
		//화면상에 실제 보이도록 하기
		setVisible(true);
		
	}
	//매개변수에 전달되는 주소로 요청하는 메소드
	public void request(String requesturl) {
        try {
            // 요청 보낼 URL 설정
            URL url = new URL("https://acornacademy.co.kr"); // 예제 URL
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // HTTP 요청 메서드 설정
            connection.setRequestMethod("GET");

            // 헤더 설정 (필요에 따라 추가)
            connection.setRequestProperty("Accept", "application/json");

            // 응답 코드 확인
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            //응답한 문자열을 누적시킬 객체 
            StringBuilder response = new StringBuilder();
            //만일 정상적인 응답이라면 
            if (responseCode == HttpURLConnection.HTTP_OK) {
            	//응답하는 내용을 읽어들일 객체 
            	BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));           
                //반복문 돌면서
            	while (true) {
                	//한줄씩 읽어들이고 
                	String line=br.readLine();
                	//만일 다 읽었다면 
                	if(line==null) {
                		break; //반복문 탈출
                	}
                	//읽은 문자열 한줄을 누적시킨다.
                    response.append(line+"\r\n");
                }
               
            } else {
                System.out.println("Request failed. Response Code: " + responseCode);
            }
            //누적된 문자열을 출력하기 
           // System.out.println(response.toString());
            //누적된 문자열을 TextArea에 출력하기
            ta.setText(response.toString());
            // 연결 해제
            connection.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        }
	}
	//main 메소드
	public static void main(String[] args) {
		new MyFrame();
	}
}

 

스레드의 개념

스레드는 실행의 흐름을 말하며, 작업단위가 된다.

run 했을  때 실행되는 흐름은 메인 스레드라고 한다.

아래 코드는 5초간 스레드가 진행되지 않고 sleep(잠을 자며), test()메소드를 호출하게 되면 test 메소드를 호출하고, test()메소드가 실행된 후 리턴(종료)되며, 다음 라인이 실행된 다음 메인 스레드가 종료된다.

 

package test.main;

public class MainClass01 {
	public static void main(String[] args) { //실행의 흐름을 스레드라고 하고, run 했을 때 실행되는 흐름은 main 스레드라고 함.
		System.out.println("메인 메소드가 시작되었습니다");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		test();
		System.out.println("메인 메소드가 종료됩니다");
	}
	
	public static void test() {
		System.out.println("test() 메소드 호출됨");
	}
}

 

Thread.sleep(1000*10);을 하면 에러가 나는데 마우스를 올려서 surround try/catch를 누르면 해결된다.

package test.frame01;

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyFrame extends JFrame {
	//생성자
	public MyFrame(String title) {
		super(title);
		setLayout(new FlowLayout());
		/*
		 * type 추론이 가능하다면 지역 변수의 type 선언 대신에 var로 변수를 선언할 수 있다.
		 * java 10에서 추가된 문법이고, 진부한 코딩을 줄이기 위한 문법이라고 함.
		 * 다만, 아직도 실무에서는 1.8버전을 쓰는 곳이 많으니까 주의하기.
		 * 지역변수에만 사용가능하고 필드에는 사용 불가, 인터페이스는 type 추론이 불가함.
		 * null로 초기화가 불가능함.
		 */
		
		var num=10;
		var name="kim";
		var isRun=true;
		
		
		var startBtn=new JButton("작업시작");
		add(startBtn);
		var startBtn2=new JButton("작업시작2");
		add(startBtn);
		startBtn.addActionListener((e)->{
			System.out.println("10 소요 작업");
			try {
				Thread.sleep(1000*10);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			System.out.println("작업 종료됨");
		});
	}
}

 

 

<11:30 3교시>

메인스레드가 run하면 실행되는데, 그러면 새로운 작업단위(스레드)에서 작업시키고 버튼을 누를 때마다 실행이되는건 메인 스레드.

메인스레드는 시간이 오래 걸리거나 대기하는 작업을 하면 안되기 때문에 새로운 작업 단위 만들어서 실행시키는 방법을 배우는 것.

 

 

빈 클래스에서 컨트롤 스페이스를 누르면 override 할 수 있는 애들 목록이 보인다.

 

package test.frame01;
/*
 * 새로운 스레드를 만드는 방법
 * 1. Thread 클래스를 상속 받은 클래스를 정의함 extends Thread
 * 2. run()메소드를 오버라이드
 * 3. run()메소드 안에서 새로운 스레드에서 작업할 내용을 코딩
 * 4. 만든 클래스로 객체를 생성하고 해당 객체의 start()메소드를 호출하면 새로운 스레드가 시작됨
 * 		new WorkThread().start();
 */
public class WorkThread extends Thread {//1.
	@Override
	public void run() {
		//새로운 스레드에서 해야할 작업을 run() 메소드 안에서 시작한다.
		System.out.println("10초 소요 작업의 시작");
		try {
			Thread.sleep(1000*10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("작업 종료");
	}
}

위의 코드와 아래 코드를 적용하면, 작업시작 버튼은 한번 누르면 아무것도 못하는 바보 버튼이 되는데,

작업시작2버튼은 새로운 독립적인 작업스레드가 생겨서 여러번 작업을 할 수도 있고 작업창을 움직일 수 있다.

작업 단위가 여러개가 필요할 때 이 방법을 통해 새로운 독립적인 1회용 작업스레드를 생성할 수 있도록 해준다.

시간이 걸리거나 대기해야 할 것 같은 작업은 이런식으로 새로운 작업단위로 넘겨서 진행해준다.

package test.frame01;

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyFrame extends JFrame {
	//생성자
	public MyFrame(String title) {
		super(title);
		setLayout(new FlowLayout());
		//this.setBounds(100,100,300,300); //얘 대신에 맨 아래처럼 쓸 수 있다.
		//this.setDefaultCloseOperation(EXIT_ON_CLOSE);//얘도 맨 아래처럼 쓸 수 있음
		/*
		 * type 추론이 가능하다면 지역 변수의 type 선언 대신에 var로 변수를 선언할 수 있다.
		 * java 10에서 추가된 문법이고, 진부한 코딩을 줄이기 위한 문법이라고 함.
		 * 다만, 아직도 실무에서는 1.8버전을 쓰는 곳이 많으니까 주의하기.
		 * 지역변수에만 사용가능하고 필드에는 사용 불가, 인터페이스는 type 추론이 불가함.
		 * null로 초기화가 불가능함.
		 */
		
		var num=10;
		var name="kim";
		var isRun=true;
		
		
		var startBtn=new JButton("작업시작");
		add(startBtn);
		var startBtn2=new JButton("작업시작2");
		add(startBtn2);
		startBtn.addActionListener((e)->{
			System.out.println("10 소요 작업");
			try {
				Thread.sleep(1000*10);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			System.out.println("작업 종료됨");
		});
		startBtn2.addActionListener((e)->{
			//WorkThread 클래스로 객체를 생성해서 참조값을 얻어낸 다음
			WorkThread t=new WorkThread();
			//start() 메소드를 호출해서 새로운 스레드가 시작되도록 한다.
			//그럼 start() 메소드를 통해 run()메소드가 호출되면서 자연스럽게 실행된다.
			t.start();
		});
	}
	//run 했을 때 실행의 흐림이 시작되는 메인 메소드
	public static void main(String[] args) {
		var frame=new MyFrame("나의 프레임");
		//MyFrame 객체 안에서 this.으로 호출했던 메소드를
		//객체 외부에서는 참조값에 .을 찍어서 호출할 수 있다.
		frame.setBounds(100,100, 300,300);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
}

 

스레드(작업단위) 생성하는 또 다른 방법 : 아래 두개 클래스 코드로 활용 가능(Btn2 부분 참고)

이렇게 생성한 스레드는 3,4번을 통해서 시작시킴

Thread t=new Thread(new WorkRunnable());

t.start();

package test.frame02;
/*
 * 새로운 스레드 만드는 방법2
 * 1. Runnable 인터페이스를 구현한 클래스를 정의하기
 * 2. run()메소드를 강제 오버라이드하기
 * 3. Thread 클래스로 객체를 생성하면서 해당 클래스로 만든 객체를 생성자의 인자로 전달하기
 * 4. Thread 클래스로 만든 객체의 start() 메소드를 호출해서 스레드를 시작시키기 * 
 */
public class WorkRunnable implements Runnable{//1.

	@Override
	public void run() {
		System.out.println("10초 소요 작업의 시작");
		try {
			Thread.sleep(1000*10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("작업 종료");
	}

}

 

package test.frame02;

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyFrame extends JFrame {
	//생성자
	public MyFrame(String title) {
		super(title);
		setLayout(new FlowLayout());
		//this.setBounds(100,100,300,300); //얘 대신에 맨 아래처럼 쓸 수 있다.
		//this.setDefaultCloseOperation(EXIT_ON_CLOSE);//얘도 맨 아래처럼 쓸 수 있음
		/*
		 * type 추론이 가능하다면 지역 변수의 type 선언 대신에 var로 변수를 선언할 수 있다.
		 * java 10에서 추가된 문법이고, 진부한 코딩을 줄이기 위한 문법이라고 함.
		 * 다만, 아직도 실무에서는 1.8버전을 쓰는 곳이 많으니까 주의하기.
		 * 지역변수에만 사용가능하고 필드에는 사용 불가, 인터페이스는 type 추론이 불가함.
		 * null로 초기화가 불가능함.
		 */
		
		var num=10;
		var name="kim";
		var isRun=true;
		
		
		var startBtn=new JButton("작업시작");
		add(startBtn);
		var startBtn2=new JButton("작업시작2");
		add(startBtn2);
		startBtn.addActionListener((e)->{
			System.out.println("10 소요 작업");
			try {
				Thread.sleep(1000*10);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			System.out.println("작업 종료됨");
		});
		startBtn2.addActionListener((e)->{
			Thread t=new Thread(new WorkRunnable());
			t.start();
		});
	}
	//run 했을 때 실행의 흐림이 시작되는 메인 메소드
	public static void main(String[] args) {
		var frame=new MyFrame("나의 프레임");
		//MyFrame 객체 안에서 this.으로 호출했던 메소드를
		//객체 외부에서는 참조값에 .을 찍어서 호출할 수 있다.
		frame.setBounds(100,100, 300,300);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
}

 

 

 

3번째 방법 : interface의 익명 객체 생성 방법을 활용해서 만들기

new Runnable(){}   이상태에서 빨간 밑줄 생기는거에 마우스 가져다 대고 unimplemented element 생성하기 넣고

{} 안에 오버라이드 된 run() 안에다가 Thread.sleep에 의한 실행 집어 넣기

package test.frame03;

import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyFrame extends JFrame {
	//생성자
	public MyFrame(String title) {
		super(title);
		setLayout(new FlowLayout());
		//this.setBounds(100,100,300,300); //얘 대신에 맨 아래처럼 쓸 수 있다.
		//this.setDefaultCloseOperation(EXIT_ON_CLOSE);//얘도 맨 아래처럼 쓸 수 있음
		/*
		 * type 추론이 가능하다면 지역 변수의 type 선언 대신에 var로 변수를 선언할 수 있다.
		 * java 10에서 추가된 문법이고, 진부한 코딩을 줄이기 위한 문법이라고 함.
		 * 다만, 아직도 실무에서는 1.8버전을 쓰는 곳이 많으니까 주의하기.
		 * 지역변수에만 사용가능하고 필드에는 사용 불가, 인터페이스는 type 추론이 불가함.
		 * null로 초기화가 불가능함.
		 */
		
		var num=10;
		var name="kim";
		var isRun=true;
		
		
		var startBtn=new JButton("작업시작");
		add(startBtn);
		var startBtn2=new JButton("작업시작2");
		add(startBtn2);
		startBtn.addActionListener((e)->{
			System.out.println("10 소요 작업");
			try {
				Thread.sleep(1000*10);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			System.out.println("작업 종료됨");
		});
		startBtn2.addActionListener((e)->{
			Thread t=new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println("10 소요 작업");
					try {
						Thread.sleep(1000*10);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					System.out.println("작업 종료됨");
				}
			});
			t.start();
		});
	}
	//run 했을 때 실행의 흐림이 시작되는 메인 메소드
	public static void main(String[] args) {
		var frame=new MyFrame("나의 프레임");
		//MyFrame 객체 안에서 this.으로 호출했던 메소드를
		//객체 외부에서는 참조값에 .을 찍어서 호출할 수 있다.
		frame.setBounds(100,100, 300,300);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
}

 

 

 

더 간단한 방법

new Thread(()->{}).start(); 형태로, Thread 안의 함수 형태의 {} 안쪽에 run 메소드에서 작업할 코딩을 추가한다.

		startBtn2.addActionListener((e)->{
			new Thread(()->{//여기가 run 메소드 안에서 할 작업을 코딩하면 되는 곳
				System.out.println("10 소요 작업");
				try {
					Thread.sleep(1000*10);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				System.out.println("작업 종료됨");
			}).start();
		});

 

 

 

입력과 출력 공부를 하기 전 바이트의 개념을 알아봤다.

2진수 8자리를 한 묶음으로 바이트라고 말한다.

바이트의 개념은 알갱이라고 생각하면 편하다.

1바이트는 총 256(=2^8)가지의 경우를 표현할 수 있다. 

화소는 보통 점 1개당 3byte가 필요하다고 함.

 

 

<12:30 4교시>

오늘 아침에 답 온거 실행의 request 흐름을 새로운 스레드에서 작업할 수 있게 바꿔보기

일단 제일 마지막에 한 더 간단한 방법을 활용해서 해보긴 했는데 맞는거 같긴한데 한 80%의 확신만 하고 있음.

package test.main;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MainClass02 extends JFrame {
	JTextArea ta=new JTextArea();
	//생성자
	public MainClass02() {
		//프레임 제목
		this.setTitle("나의 프레임");
		//프레임 위치와 크기 설정 setBounds(x, y, width, height)
		setBounds(100,100,500,500);
		//종료 버튼을 눌렀을 때 프로세스 전체가 종료되도록 하기
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		//레이아웃 메니저 객체 생성
		BorderLayout layout =new BorderLayout();
		//프레임의 레이아웃 메니저 설정
		setLayout(layout);
		
		//TextField 와 Button을 배치할 패널객체
		JPanel topPanel=new JPanel();
		topPanel.setBackground(Color.red);
		//TextField와 Button을 생성해서
		JTextField inputMsg= new JTextField(30);
		JButton sendBtn=new JButton("전송");
		//Panel에 추가
		topPanel.add(inputMsg);
		topPanel.add(sendBtn);
		//프레임의 위쪽에 패널 추가
		add(topPanel, BorderLayout.NORTH);
		
		
		ta=new JTextArea();
		//textarea를 스크롤 패널에 감싼다
		JScrollPane scroll = new JScrollPane(ta);
		//프레임의 가운데에 TextArea 추가
		Font font=new Font("Times New Roman", Font.BOLD, 20);
		ta.setFont(font);
		add(scroll, BorderLayout.CENTER);
		sendBtn.addActionListener((event)->{
			new Thread(()->{
			//TextField 에 입력한 문자열을 읽어온다.
			String msg=inputMsg.getText();
			//미리 준비된 메소드를 호출하면서 입력한 문자열을 등록함
			request(msg);	
			}).start();
		});
		
		//화면상에 실제 보이도록 하기
		setVisible(true);
		
	}
	//매개변수에 전달되는 주소로 요청하는 메소드
	public void request(String requesturl) {
        try {
            // 요청 보낼 URL 설정
            URL url = new URL("https://acornacademy.co.kr"); // 예제 URL
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // HTTP 요청 메서드 설정
            connection.setRequestMethod("GET");

            // 헤더 설정 (필요에 따라 추가)
            connection.setRequestProperty("Accept", "application/json");

            // 응답 코드 확인
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            //응답한 문자열을 누적시킬 객체 
            StringBuilder response = new StringBuilder();
            //만일 정상적인 응답이라면 
            if (responseCode == HttpURLConnection.HTTP_OK) {
            	//응답하는 내용을 읽어들일 객체 
            	BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));           
                //반복문 돌면서
            	while (true) {
                	//한줄씩 읽어들이고 
                	String line=br.readLine();
                	//만일 다 읽었다면 
                	if(line==null) {
                		break; //반복문 탈출
                	}
                	//읽은 문자열 한줄을 누적시킨다.
                    response.append(line+"\r\n");
                }
               
            } else {
                System.out.println("Request failed. Response Code: " + responseCode);
            }
            //누적된 문자열을 출력하기 
           // System.out.println(response.toString());
            //누적된 문자열을 TextArea에 출력하기
            ta.setText(response.toString());
            // 연결 해제
            connection.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        }
	}
	//main 메소드
	public static void main(String[] args) {
		new MainClass02();
	}
}