22일차 내용 정리

채공부·2025년 6월 24일

Git

🔴 원격 저장소 연결 및 상태 확인

현재 작업 디렉토리 : test11
git remote -v : 원격 저장소 목록 확인

🔴 GitHub에서 README 추가 및 커밋

GitHub에서 test11 저장소로 접속 
Add a READ ME click : 저장소 설명 추가 기능
README.md 내용 작성

# 테스트 저장소 입니다
- 어쩌구...
- 저쩌구...
- ```javascript
      let a = 10;
      function test(){

      }

Preview 로 미리보기 확인 후 Commit changes ➜ Commit click : 커밋 완료
저장소 화면에서 작성한 README 설명이 반영된 것을 확인 가능

🔴 원격 저장소 커밋 이력 내려받기

History에서 커밋 확인 : 기존 커밋 5개 + `create README.md` 커밋 1개

해당 create README.md 을 내려받으려면? (원격 저장소의 최신 커밋 내려받기)
                  ↱ main 브랜치의 commit 이력을 내려 받겠다 commit 이력을 내려 받겠다
git fetch origin main
            ↳ origin 이라는 원격 저장소로부터 

origin/main : 원격 저장소를 로컬에서 추적하는 참조

🔴 현재 상태와 워킹 트리

현재 HEAD는 로컬 main 브랜치를 가리킨다 ➜ README.md은 아직 워킹트리에 반영되지 않은 상태
      ⤷ HEAD가 가리키고 있는 상태대로 워킹 트리가 변화
ㅇ - origin/main
|
ㅇ - main ⭠ HEAD
|
ㅇ
|
ㅇ
|
ㅇ

🔴 원격 변경사항 적용 방법

<첫번째 방법>
git merge origin/main : main 브랜치에서 원격 커밋 병합

<두번째 방법>
git checkout origin/main : 원격 브랜치로 직접 이동 (워킹 트리에 원격 상태 반영

git checkout origin/master : 워킹트리에 README.md 파일 나타남
git switch main : 다시 main 브랜치로 이동 ➜ 다시 README 파일 사라짐

git merge origin/main : README.md 파일이 워킹트리에 존재 ➜ fast-forward 방식

⚠️ 원격 저장소 이력을 한 번에 가져와 병합하려면?

git pull origin main : fetch와 merge 동시 실행
➜ 원격 저장소의 변경사항이 로컬 main에 반영

🔴 GitHub에서 README 수정 후 로컬 반영

GitHub 에서 README.md 파일을 수정
  ## java 코드
  ``java
      int num1 = 10;
      Scanner scan = new Scanner(System.in);
  ``
➜ 아직 로컬에서 반영 안 됨

git pull origin main ➜ 수정된 내용이 로컬 워킹트리에 반영

🔴 로컬에서 작업 후 커밋 & 푸시

GitHub에서 test11 깃허브 저장소 위치 복사
다른Com 폴더 안 git_repos 에서git bash 열기

git clone test11_저장소_URL
cd test11 : test11 폴더로 이동
ls : README.md, study.html, index.html 파일 존재 확인

vim README.md : 편집기 열기
i : 편집 mode로 전환
"## 집에서 제목을 추가함" 이라는 내용 추가
esc ➜ :wq 로 저장 후 편집기 종료

git status : 수정 확인
git add . : 스테이징
git commit -m "README.md 파일 수정함"
git push origin main : 원격 저장소로 푸시 ➜ 저장소 들어가면 REAME.md 파일 수정된 걸 확인 가능
VS Code 에서도 터미널로 git pull origin main : 워킹트리 최신화 ➜ 워킹트리에서도 해당 내용 추가된 걸 확인

🔴 VS Code에서 다른 커밋 추가

VS Code에서 README.md 파일에 "## 학원에서 추가함" 작성
"+" click : 스테이징
"README.md 파일 수정" 메세지 작성 후 Commit click

🔴 서로 다른 장소에서 동시에 커밋한 상황

<Git Bash  커밋 : "## 집에서 제목을  추가함">
vim README.md : 편집기 열기
i : 편집 mode로 전환
"## 집에서 제목을 또 추가함" 이라는 내용 추가
esc ➜ :wq 로 저장 후 편집기 종료

git add .
git commit -m "집에서 제목을 또 추가함"

Git Bash(집) 와 VS Code(학원) 각각 다른 커밋 생성
<acorn>			<git hub>		<home>
ㅇ- main                        ㅇ-main
| 								|
ㅇ-origin/main    ㅇ-main       ㅇ - origin/main
|                 |			    |
ㅇ                ㅇ			   ㅇ
|                 |  		    |
ㅇ                ㅇ			   ㅇ

⚠️ 왜 push가 불가능한가?

  • 두 로컬(acorn, home) 모두 서로 다른 커밋을 만들었고 아직 GitHub에는 반영 안 된 상태
  • 먼저 push하는 쪽은 성공하지만 다른 쪽이 그 상태를 모른 채 push하면 Git은 거부
<acorn>			<git hub>		<home>

ㅇ- main          ㅇ             ㅇ-main origin/main
| 				  |			    |
ㅇ-origin/main    ㅇ-main       ㅇ
|                 |			    |
ㅇ                ㅇ			   ㅇ
|                 |  		    |
ㅇ                ㅇ			   ㅇ

➜ GitHub의 최신 상태를 반영하지 않은 채 push 하면 기존 커밋과 덮여쓰기 될 위험이 존재

  • 해결방법
git pull origin main
충돌 발생하기에 해결
git push origin main

🔴 fetch ➜ merge ➜ push 과정 다이어그램

GitHub로 부터 커밋 이력을 내려받으려면? : fetch

<acorn>		   <git hub>	  <home>

ㅇ- main          ㅇ             ㅇ-main origin/main
|				  |			    |  ㅇ origin/main
| 				  |			    | /
ㅇ-origin/main    ㅇ-main       ㅇ
|                 |			    |
ㅇ                ㅇ			   ㅇ
|                 |  		    |
ㅇ                ㅇ			   ㅇ

➜ fetch하고 merge 해야하는 상황

fetch 후 충돌 상태

<acorn>		     <git hub>	        <home>

								      ㅇ-main
									 / \
									ㅇ  \
ㅇ- main-origin/main ㅇ -main	    |  ㅇ origin/main
| 				     |			    | /
ㅇ                   ㅇ             ㅇ
|                    |			    |
ㅇ                   ㅇ			   ㅇ
|                    |  		    |
ㅇ                   ㅇ			   ㅇ

병합 후 push 성공 상태

<acorn>		     <git hub>	       <home>

					ㅇ-main 	     ㅇ-main - origin/main    
				    /\	    	     /\                 
				   ㅇ \		        ㅇ \
                    \  \            |  ㅇ-origin/main
ㅇ-main-origin/main  \  ㅇ		    | /
| 				      \/		    |/
ㅇ                    ㅇ            ㅇ
|                     |			    |
ㅇ                    ㅇ			   ㅇ
|                     |  		    |
ㅇ                    ㅇ            ㅇ

JAVA

다형성

첫번째 그림 삽입

상속관계 구조 예시

object
  ↑
  | extends
phone
  • 객체를 생성할 때 타입을 object나 phone 으로 설정할 수 있다.
p1 = new Phone() 

  ⤷ 즉, 부모 타입으로도 자식 객체를 담을 수 있다

메소드 오버라이딩

  • p1.takePicture()을 호출하면?
    자식 클래스의 메서드가 호출된다
    이는 자식이 부모의 메서드를 오버라이드(재정의) 했기 때문이다

부모의 메서드도 같이 호출하고 싶다면?

  • super.takePicture() 를 사용하면 부모의 메서드도 호출

📘 키워드 설명

  • super: 부모 클래스 참조
  • this: 현재 객체 자신
  • super(): 부모 클래스의 생성자 호출

SmartPhone 예제

// SmartPhone 클래스

public class SmartPhone extends HandPhone {
	// 생성자
	public SmartPhone() {
		System.out.println("SmartPhone 생성자 호출됨");
	}
	
	// 메소드
	public void doInternet() {
		System.out.println("인터넷을 해요!");
	}
	
	@Override
	public void takePicture() {
		System.out.println("1억 화소의 사진을 찍어요~");
	}
}
// Main 클래스

import test.mypac.SmartPhone;

public class MainClass06 {
	public static void main(String[] args) {
		SmartPhone p1 = new SmartPhone();
		p1.takePicture();
	}
}

👉 만약 이렇게 작성한다면?

@Override
public void takePicture() {
	super.takePicture(); // 부모 메서드도 실행
	System.out.println("1억 화소의 사진을 찍어요~");
}

출력 결과

30만 화소의 사진을 찍어요~
1억 화소의 사진을 찍어요~

가상의 도형 클래스 예제

// SmartPhone 클래스

public class Shape {
	// 도형의 위치
	private int x;
	private int y;
	
	public Shape(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
}
  • 생성자를 하나라도 만들면 기본 생성자(default constructor) 는 사라진다 ➜ new Shape()는 사용 불가

객체 생성 가능 예시

Shape s1 = new Shape(100, 200)

Override

Circle 예제

// Circle 클래스

public class Circle extends Shape{
	// 원의 반지름을 저장할 필드
	private int radius;
	
	public Circle(int x, int y, int radius) {
		super(x, y); // super() 는 부모 클래스의 생성자 호출
		this.radius = radius;
	}
	
	public void printArea() {
		// 원의 넓이
		double area = Math.PI*radius*radius;
		System.out.println("원의 넓이:"+area);
	}

	@Override
	public void printInfo() {
		super.printInfo();
		System.out.println("반지름:"+radius);
	}
}
// Main 클래스

import test.mypac.Circle;
import test.mypac.Shape;

public class MainCLass07 {
	public static void main(String[] args) {
		// Shape 객체 생성
		Shape s1 = new Shape(100, 200);
		s1.printInfo();
		
		Circle c1 = new Circle(200,300, 10);
		c1.printArea();
		c1.printInfo();
	}
}

출력결과

실습 예제

  • 목표 : Shape 클래스를 상속하여 Rect 클래스 정의
// 아래 코드가 동작할 수 있도록 작성하세요
Rect r1 = new Rect(100, 200, 50);
r1.printArea();   // 사각형의 넓이
r1.printInfo();   // 좌표와 한 변의 길이 출력
// Rect 클래스

public class Rect extends Shape{
	private int sideLength;
	
	public Rect(int x, int y, int sideLength) {
		super(x,y);
		this.sideLength = sideLength;
	}
	
	public void printArea() {
		double extent = sideLength*sideLength;
		System.out.println("사각형의 넓이:"+extent);
	}

	@Override
	public void printInfo() {
		super.printInfo();
		System.out.println("한변의 길이:"+sideLength);
	}
}
// Main 클래스

import test.mypac.Rect;

public class MainCLass07 {
	public static void main(String[] args) {

		Rect r1 = new Rect(100,200,50);
		r1.printArea();
		r1.printInfo();
	}
}

출력결과

클래스 간의 포함 관계 & 생성자 활용

회사 사원(Employee) 정보 관리 프로그램 예제

// Department 클래스

public class Department {
	// 부서명과 부서 위치를 저장하는 필드
	private String deptName;
	private String location;
	
	// 부서명과 부서의 위치를 생성자로 전달받아서 필드에 저장하는 생성자
	public Department(String deptName, String location) {
		this.deptName = deptName;
		this.location = location;
	}
	
	// 부서정보를 콘솔에 출력하는 테스트 메소드
	public void printInfo() {
		System.out.println("부서명:"+deptName);
		System.out.println("위치:"+location);
	}
}
// Employee 클래스

public class Employee {
	// 사원 이름
	private String name;
	// 사원 급여
	private int salary;
	// 근무하는 부서의 정보
	private Department dept;
	
	// 필드에 저장할 정보를 생성자로 전달받아서 저장
	public Employee(String name, int salary, Department dept) {
		this.name = name;
		this.salary = salary;
		this.dept = dept;
	}
	
	// 테스트 메소드
	public void printInfo() {
		System.out.println("이름:"+name);
		System.out.println("급여:"+salary);
		dept.printInfo();
	}	
}

객체를 변수로 먼저 생성 후 전달

Department d = new Department("교육부", "역삼동");
Employee e1 = new Employee("김구라", 1000, d);
e1.printInfo();

Employee 객체 생성 시 Department를 직접 생성자에 삽입

Employee e2 = new Employee("원숭이", 2000, new Department("교육부", "역삼동"));
e2.printInfo();

Employee 객체 생성 + 메서드 호출을 한 줄로 처리

new Employee("주뎅이", 3000, new Department("SALES", "LA")).printInfo();

상속 예제

  • Employee 클래스를 상속받은 Manager 클래스
    추가 필드 : position
// Manage 클래스

public class Manager extends Employee{
	private String position; // ex: "팀장", "부장", "이사"
	
	// 생성자
	public Manager(String name, int salary, Department dept) {
		super(name, salary, dept);
	}
	
	// 필드에 값을 넣어주는 setter 메소드
	public void setPosition(String position) {
		this.position = position;
	}
	
	@Override
	public void printInfo() {
		super.printInfo();
		System.out.println("매니저의 직책:"+position);
	}
}

출력
1. Manager 객체 사용

Manager m1 = new Manager("KING", 5000, new Department("기획부", "서울"));
m1.setPosition("이사");
m1.printInfo();
사원이름 : KING
급여 : 5000
부서명 : 기획부
부서의 위치 : 서울
매니저의 직책: 이사
  1. Employee 타입으로 Manager 사용
Employee m2 = new Manager("KING2", 500, new Department("기획부", "서울"));
m2.printInfo(); // 직책 없음

Manager m3 = (Manager) m2;
m3.setPosition("이사");
m2.printInfo();
사원이름 : KING2
급여 : 500
부서명 : 기획부
부서의 위치 : 서울
매니저의 직책: 이사

For문

배열에 객체 3개를 저장해 for문 사용하는 예제

// Main 클래스

Department d1 = new Department("영업부", "대전");

Employee e1 = new Employee("유재석", 3000, d1);
Employee e2 = new Employee("박명수", 2000, d1);
Employee e3 = new Employee("정준하", 1000, d1);

Employee[] emp = new Employee[3];
emp[0] = e1;
emp[1] = e2;
emp[2] = e3;
  1. 기본 for문
for(int i = 0; i < emp.length; i++) {
	emp[i].printInfo();
}
  1. 향상된 for문
for(Employee e : emp) {
	e.printInfo();
}

➜ 향상된 for문은 배열의 타입을 기준으로 반복자를 선언해야 한다

emp → Employee[] 이므로
Employee e : emp 형식 사용

setter & getter

생성 이유

private String name;
  • private 접근 제어자는 해당 클래스 내부에서만 접근 가능

  • 외부 클래스에서는 직접 접근 불가

item.name = "시계"; ➜ error
System.out.println(item.name); ➜ error

   ⤷ 데이터 은닉(Encapsulation) 원칙을 지키기 위함

∴ 필드에 값을 넣거나 불러오기 위한 접근용 메소드가 필요
setter , getter 메소드 사용

  • 표준에 맞는 setter/getter를 만든다면?
    객체의 참조값을 어디에 전달했을 때 자동으로 만들어주는 기능이 많다
    = 자동화를 위해 필요

생성 방법

// Item 클래스

public class Item {
	private String name;
	private int price;
	private String madeBy;
	
	// setter 메소드
	public void setName(String name) {
		this.name = name;
	}
	
	// getter 메소드
	public String getName() {
		return name;
	}
}

활용 방법

  • 필드에 값 저장 ➜ setter
Item item = new Item();
item.setName("전자시계"); // 내부 name 필드에 값 저장
  • 필드값 가져오기 ➜ getter
String a = item.getName();
System.out.println(item.getName());
  • 활용 예시
// 1) 변수에 담기
String name = item.getName();

// 2) 다른 메소드/생성자에 전달
printItem(item.getName());

// 3) 콘솔 출력
System.out.println("상품명: " + item.getName());
profile
학원 공부 내용 정리

0개의 댓글