
프로젝트 생성
프로젝트의 이름은 'OOP-RPG'로 설정하며, 저장 위치는 원하시는 곳으로 지정하시면 됩니다. 빌드는 IntelliJ를 사용할 예정이고, 자바 버전은 17로 설정하여 프로젝트를 생성하시기 바랍니다. 그리고 'Create Git repository' 도 꼭 함께 설정해주셔야 합니다.

Git Commit
커밋(Commit)은 Git 버전 관리 시스템에서 프로젝트의 특정 상태를 기록하는 행위 또는 그렇게 기록된 상태를 가리킵니다. 개발자가 프로젝트에서 어떤 변경을 수행한 후, 그 변경을 기록하려면 Git Commit을 생성해야 합니다.
커밋은 다음과 같은 정보를 포함합니다:
- 커밋을 생성한 개발자의 정보 (이름, 이메일 등)
- 커밋이 생성된 시점의 날짜와 시간
- 커밋 메시지
: 커밋과 관련된 설명을 작성할 수 있는 부분으로, 변경사항에 대한 간략한 요약이나 커밋의 목적 등을 포함할 수 있습니다. - 변경된 파일들과 그 변경 사항
커밋(Commit)은 프로젝트의 히스토리를 구성하는 기본 단위이며, 각 커밋은 고유한 ID(보통 SHA-1 해시라는 40자리의 문자열)를 가지고 있습니다. 이 ID를 통해 개발자는 특정 커밋을 참조하거나, 이전 상태로 롤백하거나, 다른 브랜치로 이동하는 등의 작업을 수행할 수 있습니다.
해시 문자열은 특정 데이터를 고정된 길이의 문자열로 변환한 결과입니다. 해시 함수를 사용하여 원본 데이터를 압축하며, 일반적으로 이 결과 문자열은 원래 데이터와는 거의 구별할 수 없는 형태가 됩니다. 해시 함수의 주요 특징 중 하나는 동일한 입력에 대해 항상 동일한 출력을 생성하지만, 입력이 조금이라도 변경되면 완전히 다른 출력이 만들어집니다. 이러한 특성 때문에 해시를 암호학, 데이터 무결성 검사 및 빠른 검색을 위한 인덱싱에 활용하기도 합니다.
- git status

위 메세지는 Git의 상태 메시지로, `git status` 명령어를 실행했을 때 보게 되는 메시지입니다.
- On branch master
: 현재 작업하고 있는 브랜치가 master 브랜치라는 것을 알려줍니다. Git에서는 한 프로젝트에 대해 여러 개의 브랜치를 만들어 다양한 작업을 동시에 진행할 수 있습니다. - No commits yet
: 아직 master 브랜치에 커밋된 내역이 없다는 것을 알려줍니다. 즉, 새로운 레포지토리이거나, 아직 첫 커밋을 만들지 않은 상태입니다. - Changes to be committed
: 다음 커밋에 포함될 변경 사항들을 나열합니다. 이 경우, 여러 개의 새 파일이 추가되었는데, 이 파일들은 이미 Staging Area(또는 Index)에 추가되어 있으므로 다음에 git commit 명령을 실행하면 이 파일들의 현재 상태가 커밋에 포함됩니다.- (use "git rm --cached <file>..." to unstage) : Staging Area에서 특정 파일을 제거하려면 이 명령을 사용하라는 안내입니다. 이를 통해 커밋에 포함시키지 않을 파일을 Staging Area에서 제거할 수 있습니다.
- new file
: `Staging Area`에 추가된 새 파일들의 목록입니다. 이 파일들은 다음 커밋에 포함될 예정입니다. .gitignore는 Git이 추적하지 않아야 할 파일이나 디렉터리를 지정하는 파일이고, .idea 디렉터리와 그 아래의 파일들은 IntelliJ IDEA라는 Java 개발 환경에서 생성하는 프로젝트 설정 파일들입니다. OOP-RPG.iml 역시 IntelliJ IDEA 프로젝트 파일입니다.
- git commit

`git commit` 명령을 실행한 후에 보게 되는 Git의 출력 메세지입니다. 이 메시지는 커밋이 성공적으로 생성되었음을 알려주며, 커밋에 대한 일부 정보를 제공합니다.
- git commit -m "Project First Commit"
: 이 명령은 Git에게 새로운 커밋을 생성하라고 지시합니다. -m 옵션은 커밋 메시지를 지정하는데 사용되며, 이 경우 "Project First Commit"이라는 메시지가 커밋과 함께 저장됩니다.- [master (root-commit) 07b21f7] Project First Commit: 이 부분은 생성된 커밋에 대한 정보를 보여줍니다. `master`는 이 커밋이 추가된 브랜치의 이름을 가리킵니다. (root-commit)은 이 커밋이 해당 브랜치의 첫 번째 커밋임을 의미합니다. `07b21f7` 은 커밋의 고유한 해시 값입니다. 이 해시 값은 이 커밋을 참조할 때 사용되며, 이 커밋의 변경사항, 시간, 작성자 등의 정보를 기반으로 계산됩니다. "Project First Commit"은 커밋 메시지입니다.
- 6 files changed, 99 insertions(+)
: 이 부분은 이 커밋에서 변경된 파일의 수와 총 변경된 라인 수를 나타냅니다. 이 경우 6개의 파일이 변경되었으며, 그 결과로 99줄이 새로 추가되었습니다. - create mode 100644 .gitignore 등
: 이 부분은 각 파일에 대한 변경 내용을 보여줍니다. 이 경우, 모든 파일이 새로 생성되었습니다. 100644는 파일의 권한을 나타내는 숫자이며, 이 숫자는 Unix 스타일의 파일 권한을 나타냅니다. 100644는 일반 파일을 나타내며, 사용자에게 읽기/쓰기 권한이 있고, 그룹과 다른 사용자에게는 읽기 권한만 있음을 의미합니다.
- git log
`git log` 명령어는 Git 커밋 히스토리를 보여주는 도구입니다. 기본적으로, git log 명령어의 출력은 가장 최근의 커밋부터 시작하여 역순으로 커밋을 나열합니다.

git log 명령어를 실행했을 때 보게 되는 Git 커밋 로그의 일부입니다. 이 로그는 커밋의 상세한 정보를 보여줍니다.
- commit 07b21f787de2e04640d39dc88794f864739b6b27 (HEAD -> master)
: 이 부분은 커밋의 고유한 SHA-1 해시 값을 보여줍니다. (HEAD -> master)는 현재 브랜치가 master이고, HEAD 포인터가 이 커밋을 가리키고 있음을 의미합니다. HEAD는 현재 체크아웃된 커밋을 가리키는 포인터입니다.
Git 라이프사이클: 리마인드

Git에서 파일 상태는 크게 Untracked와 Tracked로 나눌 수 있습니다. 이 두 상태는 Git이 해당 파일을 추적하고 있는지 여부를 나타냅니다.
- Untracked Area
: 이 영역에 있는 파일들은 Git에 의해 추적되지 않고 있습니다. 즉, Git이 이 파일들의 변경사항을 기록하지 않습니다. 이 파일들은 새로 생성된 파일이거나 .gitignore 파일에 명시된 경우일 수 있습니다. - Tracked Area
: 이 영역에 있는 파일들은 Git에 의해 추적되고 있습니다. 이 파일들의 변경사항은 Git에 의해 기록됩니다.- Unstaged Area
: 추적 중인 파일이지만, 최근 변경사항이 아직 Staging Area에 추가되지 않은 상태를 말합니다. 즉, 이 파일들의 최근 변경사항은 다음 커밋에 포함되지 않습니다. `git add` 명령어를 사용해 이 파일들을 Staging Area로 이동시킬 수 있습니다. - Staging Area
: 추적 중인 파일 중에서 다음 커밋에 포함될 변경사항이 담긴 파일들의 상태를 말합니다. `git commit` 명령어를 실행하면, Staging Area에 있는 변경사항들이 새로운 커밋으로 저장됩니다.
- Unstaged Area
이렇게 Git은 파일의 상태를 관리함으로써, 개발자가 원하는 시점에 원하는 변경사항만을 커밋할 수 있도록 지원합니다.
캐릭터 - 추상클래스
`Character` 라는 추상 클래스를 정의한 것입니다. 각 캐릭터 객체에 대한 정보와 기본 기능을 설계하고 있습니다.

package character;
public abstract class Character {
private String name;
private int hp;
private int mp;
private int exp;
private double x, y;
public Character(String name, int hp, int mp, int exp, double x, double y) {
this.name = name;
this.hp = hp;
this.mp = mp;
this.exp = exp;
this.x = x;
this.y = y;
}
public String getName() {
return name;
}
public int getHp() {
return hp;
}
public int getMp() {
return mp;
}
public int getExp() {
return exp;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public void setHp(int hp) {
this.hp = hp;
}
public void setMp(int mp) {
this.mp = mp;
}
public void setExp(int exp) {
this.exp = exp;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public abstract void move(double x, double y);
public abstract void attack();
}
- `name`, `hp`, `mp`, `exp`, `x`, `y` 라는 인스턴스 변수들이 있습니다. 이들은 각각 캐릭터의 이름, 체력, 마력, 경험치, x 좌표 및 y 좌표를 저장합니다.
- 생성자(Constructor)에서는 전달받은 인자들로 인스턴스 변수들을 초기화합니다.
- 각 변수에 대해 getter/setter 메서드가 정의되어 있어 캐릭터의 속성을 외부로부터 조회하거나 수정할 수 있습니다.
- `move`와 `attack` 메서드는 추상 메서드로 정의되어 있습니다. 이는 파생 클래스에서 이들 메서드를 구체적으로 구현해야 함을 의미합니다.
따라서, 이 Character 추상 클래스는 추후 캐릭터 객체를 생성하는 서브클래스들에게 기본 골격을 제공하고 있으나, 구체적인 이동 및 공격 동작을 구현하도록 상속받는 하위 클래스에게 위임하고 있습니다.
Warrior - Character 구현

import character.Character;
public class Warrior extends Character {
public Warrior(String name, int hp, int mp, int exp, double x, double y) {
super(name, hp, mp, exp, x, y);
}
@Override
public void move(double x, double y) {
setX(x * 1.2);
setY(y * 1.1);
}
@Override
public void attack() {
System.out.printf("%s 가 검으로 몬스터를 공격!\n", getName());
}
}
코드의 각 부분을 살펴보면 다음과 같습니다.
- public class Warrior extends Character
: Warrior 클래스는 Character 클래스를 상속받습니다. 이 말은 Warrior가 Character의 모든 필드와 메서드를 상속받는다는 뜻입니다. extends 키워드를 통해 클래스 상속을 구현합니다. - 생성자: Warrior 클래스의 생성자는 이름, 체력(hp), 마력(mp), 경험치(exp), 위치(x, y)를 매개변수로 받습니다. 이 값들은 super 키워드를 통해 Character 클래스의 생성자로 전달되어, Character 클래스의 필드를 초기화합니다.
- move 메서드
Warrior 클래스는 Character 클래스의 move 메서드를 오버라이드(재정의)합니다. 이를 통해 Warrior 클래스는 고유한 움직임 방식을 가지게 됩니다. 구체적으로, x축 방향으로는 입력받은 값의 20% 더 빠르게, y축 방향으로는 10% 더 넓게 움직일 수 있습니다. - attack 메서드
: Character 클래스의 attack 메서드를 오버라이드합니다. Warrior가 공격할 때 "{name} 이 검으로 몬스터를 공격!"이라는 메시지를 출력합니다.
이 클래스는 객체 지향 프로그래밍의 몇 가지 핵심 개념을 보여주고 있습니다: 상속(inheritance), 추상화(abstraction), 오버라이딩(overriding). 이러한 개념을 사용하여 코드를 재사용하고, 유연성과 확장성을 높일 수 있습니다.
- git status
현재 src/ 디렉터리에서 총 2개의 클래스를 생성하고 코드를 작성한 상태입니다. 그러나 `git status` 명령을 사용하면 변경된 파일 목록이 폴더별로 표시됩니다

변경된 파일에 대한 자세한 정보는 git status -u 또는 git status --untracked-files 명령을 사용하여 확인할 수 있습니다. 이러한 옵션을 사용하면 변경된 모든 파일의 상태를 볼 수 있습니다.

이 메시지를 분석하면 다음과 같습니다:
- Untracked files
: ...: src/character/Character.java 파일과 src/character/jobClass/Warrior.java 파일은 현재 Git에 의해 추적되지 않고 있습니다. 이 파일들은 Git 레포지토리에 새로 추가되었지만 아직 Git에 등록되지 않은 상태입니다.
- (use "git add <file>..." to include in what will be committed): Git이 이 파일들의 변경사항을 추적하도록 하려면, git add <file> 명령을 사용해야 합니다. 이 명령은 변경사항을 스테이징 영역에 추가하는 역할을 합니다.
- (use "git add <file>..." to include in what will be committed): Git이 이 파일들의 변경사항을 추적하도록 하려면, git add <file> 명령을 사용해야 합니다. 이 명령은 변경사항을 스테이징 영역에 추가하는 역할을 합니다.
- nothing added to commit but untracked files present (use "git add" to track): 현재 커밋될 수 있는 변경사항이 없지만, 추적되지 않은 파일들이 존재한다는 것을 알립니다. 이 파일들을 Git이 추적하도록 만들려면 git add 명령을 사용해야 합니다.
- git add [특정파일]
Character.java 파일과 Warrior.java 파일은 현재 Git에 추적되지 않고 있기 때문에, 이들을 Git으로 관리하도록 등록하고 추적할 수 있게 설정해야 합니다. 비교를 위해 먼저 Character.java 파일만 스테이징 영역에 추가하고, 상태 변화를 확인해 보겠습니다.

이 메시지를 분석하면 다음과 같습니다:
- Changes to be committed
: ...: src/character/Character.java 파일은 커밋될 변경사항으로 등록되었습니다. 이는 git add 명령어를 통해 이 파일의 변경사항이 스테이징 영역에 추가되었다는 것을 의미합니다.- (use "git restore --staged <file>..." to unstage): 이는 src/character/Character.java 파일의 변경사항을 스테이징 영역에서 제거하려면 git restore --staged <file> 명령어를 사용하라는 안내입니다.
- Untracked files
: ...: src/character/jobClass/Warrior.java 파일은 현재 Git에 의해 추적되지 않고 있습니다. 이 파일은 Git 레포지토리에 새로 추가되었지만 아직 Git에 등록되지 않은 상태입니다.- (use "git add <file>..." to include in what will be committed): Git이 이 파일의 변경사항을 추적하도록 하려면, git add <file> 명령을 사용해야 합니다. 이 명령은 변경사항을 스테이징 영역에 추가하는 역할을 합니다.
따라서 이 메시지는 Character.java 파일의 변경사항이 커밋될 준비가 되었으며, Warrior.java 파일은 아직 Git에 의해 추적되지 않고 있다는 것을 알려주고 있습니다. Warrior.java 파일의 변경사항을 커밋하려면, 먼저 git add 명령어를 사용하여 이 파일을 Git의 추적 대상에 추가해야 합니다.
이제 모든 파일을 커밋하기 위해 Warrior.java 파일도 스테이징 영역으로 옮길 예정입니다. 파일명을 일일이 `git add`로 입력하지 않고, 한 번에 전체 파일을 스테이징 영역으로 옮기고 싶다면 `git add . `명령어를 사용하면 됩니다. 여기서 `.` 은 현재 디렉터리를 의미하며, 이를 통해 해당 디렉토리 내의 모든 파일들이 스테이징 영역으로 변경됩니다.

- git commit

- git log

인터페이스를 통해 스킬 구현
'워리어' 클래스를 위해 인터페이스를 통해 두 가지 기술을 구현했습니다. 이제 워리어 클래스에서 이 인터페이스를 구현하고, 해당 두 메서드를 오버라이드하여 사용해야 합니다.

WarriorSkill 인터페이스 구현

public class Warrior extends Character implements WarriorSkill {
...
@Override
public void steelStrike() {
System.out.println("강철의 일격!!");
}
@Override
public void stormAttack() {
System.out.println("폭풍 공격!!");
}
}
위 코드는 인터페이스를 활용한 예시를 보여주지만, 실제로 워리어 스킬은 워리어 클래스에서만 사용한다는 점을 고려할 때, 별도로 인터페이스를 생성하기보다는 워리어 클래스 내부에 직접 메서드를 생성하여 사용하는 것이 더 바람직하다고 볼 수 있습니다.
코드 작성 시, 추상 클래스나 인터페이스를 활용하는 목적은 중복되거나 공용으로 사용되는 코드를 효율적으로 재사용하기 위함입니다. 워리어 스킬의 경우에는 이러한 재사용의 이점이 없으므로, 굳이 인터페이스를 별도로 생성하지 않고 워리어 클래스 내부에 메서드를 생성하여 효율성을 높일 수 있습니다.
Main 클래스에서 객체를 생성해서 확인

Git ignore
`.gitignore` 파일은 Git이 추적하지 않을 파일이나 디렉터리를 지정하는 데 사용되는 파일입니다. 이 파일에 명시된 패턴과 일치하는 파일이나 디렉터리는 Git에 의해 무시되며, 이는 변경사항이 추적되지 않고 커밋에 포함되지 않음을 의미합니다. `.gitignore` 파일은 프로젝트의 루트 디렉터리에 주로 위치하며, 각 줄에는 무시할 파일 패턴이 적혀 있습니다. 이 패턴은 파일명, 디렉토리명, 와일드카드(*, ? 등)를 사용할 수 있습니다.

프로젝트를 처음 생성할 때 'Create Git repository' 옵션을 사용하면, 인텔리제이가 자동으로 불필요한 파일들에 대해 .gitignore 파일을 설정해 줍니다. 이렇게 하면 프로젝트를 관리하는 데 있어 편리함이 제공됩니다.

앞서 작성한 코드들을 테스트하기 위해 만든 Main 클래스는 메인 비즈니스 코드가 아니기 때문에, Git 추적에서 제외하고 싶다고 가정해 봅시다. 이때, `.gitignore` 파일에 Main 클래스를 명시하면 자동으로 추적에서 제외됩니다.

현재 `git status` 명령어를 실행하면, Untracked Files에 `src/Main.java` 파일이 표시되는 것을 확인할 수 있습니다. 개발자가 한 번이라도 커밋하지 않으면 Git에서 추적되지 않기는 하지만, 비추적 대상이라는 메시지로 여전히 표시되기 때문에 이를 완전히 예외 처리하여 메시지에 표시되지 않게 해 보겠습니다.

`.gitignore` 파일의 맨 하단에 해당 파일의 경로를 포함하여 입력해 주면, 자동으로 Git 추적에서 제외되게 됩니다.

코드 리팩토링 및 개선
- Character
public abstract class Character {
// 캐릭터의 이름, 체력, 마나, 경험치, 위치를 나타내는 변수들입니다.
private String name;
private int hp;
private int mp;
private int exp;
private double x, y;
// 캐릭터의 공격력을 나타내는 변수입니다.
private int damage;
// 공격력을 가져오는 getter 메서드입니다.
public int getDamage() {
return damage;
}
// 공격력을 설정하는 setter 메서드입니다.
public void setDamage(int damage) {
this.damage = damage;
}
// 각각의 getter 메서드들은 캐릭터의 이름, 체력, 마나, 경험치, 위치를 반환합니다.
public String getName() {
return name;
}
public int getHp() {
return hp;
}
public int getMp() {
return mp;
}
public int getExp() {
return exp;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
// 각각의 setter 메서드들은 캐릭터의 체력, 마나, 경험치, 위치를 설정합니다.
public void setHp(int hp) {
this.hp = hp;
}
public void setMp(int mp) {
this.mp = mp;
}
public void setExp(int exp) {
this.exp = exp;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
// 공격력을 업그레이드하는 추상 메서드입니다. 이 메서드는 하위 클래스에서 구현될 예정입니다.
public abstract void damageUpgrade();
// 캐릭터를 움직이게 하는 추상 메서드입니다. 이 메서드는 하위 클래스에서 구현될 예정입니다.
public abstract void move();
// 캐릭터가 공격하는 행동을 나타내는 추상 메서드입니다. 이 메서드는 하위 클래스에서 구현될 예정입니다.
public abstract void attack();
}
- Warrior
public class Warrior extends Character {
// 이 메서드는 공격력을 증가시키는 도우미 메서드입니다.
// 공격력이 기존 공격력에 50만큼 증가된 값을 반환합니다.
private int damageBoost(int damage) {
return damage + 50;
}
// 이 메서드는 Character 클래스의 move 메서드를 재정의합니다.
// 전사 클래스는 움직임 방식이 특별하게 정의되어 있습니다.
// x 위치로 이동하는 속도가 20% 빠르게 이동이 가능하고,
// y 위치로 이동하는 범위는 10% 더 넓어집니다.
@Override
public void move() {
setX(getX() * 1.2);
setY(getY() * 1.1);
}
// 이 메서드는 Character 클래스의 damageUpgrade 메서드를 재정의합니다.
// 공격력을 증가시키는 도우미 메서드인 damageBoost를 사용하여 공격력을 업그레이드합니다.
@Override
public void damageUpgrade() {
int boost = damageBoost(getDamage());
setDamage(boost);
}
// 이 메서드는 Character 클래스의 attack 메서드를 재정의합니다.
// 전사의 이름과 현재 공격력을 출력하여 전사가 몬스터에게 어떤 데미지로 공격하는지 표시합니다.
@Override
public void attack() {
System.out.printf("%s 이/가 몬스터에게 %f 데미지로 공격!\n", getName(), getDamage());
}
// 이 메서드는 전사의 특수 공격인 강철의 일격을 나타냅니다.
// 강철의 일격은 기본 공격력의 156%의 데미지를 입힙니다.
public void steelStrike() {
System.out.println(String.format("강철의 일격: %f ", getDamage() * 1.56));
}
// 이 메서드는 전사의 특수 공격인 폭풍 공격을 나타냅니다.
// 폭풍 공격은 기본 공격력의 135%의 데미지를 입힙니다.
public void stormAttack() {
System.out.println(String.format("폭풍 공격: %f ", getDamage() * 1.35));
}
}
- Main
public class Main {
public static void main(String[] args) {
Warrior warrior = new Warrior();
warrior.setHp(100);
warrior.setX(2);
warrior.setY(1);
warrior.setExp(0);
warrior.setDamage(30);
Monster monster = new Monster(500, 5, 3);
while (monster.getHp() >= 0) {
double curX = warrior.getX();
double curY = warrior.getY();
if (Math.abs(curX - monster.getX()) <= 1 || Math.abs(curY - monster.getY()) <= 1) {
warrior.damageUpgrade();
warrior.stormAttack();
monster.setHp(monster.getHp() - warrior.getDamage());
if (monster.getHp() <= 0) break;
System.out.println("몬스터 HP = " + monster.getHp());
System.out.println();
} else {
System.out.println("curX = " + curX);
System.out.println("curY = " + curY);
System.out.println();
warrior.move();
}
}
System.out.println("몬스터 사망");
}
static class Monster {
private int hp, x, y;
public Monster(int hp, int x, int y) {
this.hp = hp;
this.x = x;
this.y = y;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
}
최종적으로 Git 커밋하기
이제 앞에서 작성한 코드들을 최종적으로 커밋해 보겠습니다. 커밋 과정은 큰 문제가 없는 한 거의 비슷한 작업으로 이루어집니다. 물론 더 복잡한 기능도 수행할 수 있지만, 현재로서는 상태 확인, 스테이징 영역으로 변경, 커밋, 로그 확인까지의 기본적인 버전 관리를 정확하게 이해하면 충분하다고 볼 수 있습니다.
- git status
한 번이라도 커밋된 파일은 지속적으로 Git의 추적을 받기 때문에, 이후부터는 추적 영역 내(tracked area)에 위치하게 됩니다. 반면 새롭게 추가된 파일들은 커밋된 적이 없기 때문에 추적되지 않은 파일(untracked files)로 나타납니다.

- git add .
이전과 같이 현재 상황에서 모든 파일을 커밋하는 데 문제가 없으므로, `.`을 사용하여 현재 디렉터리의 모든 파일들을 스테이징 영역으로 변경하겠습니다.

- git commit

- git log

GitJav 멘토링 오프라인 활동사진






사진을 불펌하거나 무단도용을 금합니다!!!

여러분의 지적과 피드백은 매우 소중합니다! 만약 제 코드나 설명에 대해
어떤 문제점이나 개선 사항이 있다면 언제든지 댓글로 남겨주세요. 감사합니다:)
'🏄🏻♂️ : activity' 카테고리의 다른 글
| [ SSAFY ] - 10기 JAVA 전공자반: 1학기 회고록 ! (2) | 2023.11.28 |
|---|---|
| [ SSAFY ] - 싸피 10기 전공자 합격 후기 - 지원부터 최종합격까지 ! (2) | 2023.07.08 |
| GitJav 멘토링: Java 기초 문법 총정리 및 Git 사용법 ep.4 (0) | 2023.05.17 |
| GitJav 멘토링: JAVA 배열, 클래스, 객체, 인터페이스, 상속 ep.3 (0) | 2023.05.03 |
| GitJav 멘토링: 자바 프로젝트 생성 및 구조, 조건문과 반복문 ep.2 (0) | 2023.04.19 |