mkdir: 디렉토리 생성 예: mkdir folder_name
touch: 파일이 존재한다면 updatedAt 갱신, 아니라면 파일 생성 예: touch file_name.java
mv: 파일의 이름을 변경한다. 경로를 바꿀 수도 있다. 예: mv file_name.java folder_name/new_file_name.java
cp: 파일을 다른 이름으로 복사한다(해당 이름의 파일이 존재할 경우 덮어씀). -fi 옵션으로 overwrite를 확인 후 복사할 수 있다. -R 옵션으로 디렉토리를 복사할 수 있다. 예: cp -R -fi folder_name copy_folder_name
리눅스에서 파일 및 디렉토리 관리를 위한 기본 명령어는 다음과 같습니다:
mkdir(make directory)는 새로운 디렉토리를 생성하는 명령어입니다. 주요 옵션으로는 -p(부모 디렉토리가 없을 경우 함께 생성)가 있습니다. 예를 들어, 'mkdir -p projects/web/css'는 projects, web, css 디렉토리를 한 번에 생성합니다.
touch는 빈 파일을 생성하거나 기존 파일의 타임스탬프를 업데이트하는 명령어입니다. 'touch newfile.txt'는 newfile.txt라는 빈 파일을 생성하며, 이미 파일이 존재할 경우 접근 및 수정 시간만 현재 시간으로 업데이트합니다.
mv(move)는 파일이나 디렉토리를 이동하거나 이름을 변경하는 명령어입니다. 'mv file.txt directory/'와 같이 사용하면 파일을 지정된 디렉토리로 이동하고, 'mv oldname.txt newname.txt'와 같이 사용하면 파일 이름을 변경합니다. 디렉토리도 동일한 방식으로 이동하거나 이름을 변경할 수 있습니다.
cp(copy)는 파일이나 디렉토리를 복사하는 명령어입니다. 주요 옵션으로는 -r(디렉토리와 그 내용을 재귀적으로 복사), -i(덮어쓰기 전 확인), -p(파일 속성 유지) 등이 있습니다. 'cp -r source_dir/ destination_dir/'는 디렉토리와 그 내용 전체를 복사합니다.
실제 작업 시나리오 예시:
프로젝트 구조 생성: 'mkdir -p project/src project/docs'로 프로젝트 기본 구조 생성
파일 생성: 'touch project/src/main.js project/src/style.css'로 빈 소스 파일 생성
파일 이름 변경: 'mv project/src/style.css project/src/main.css'로 CSS 파일 이름 변경
파일 복사: 'cp project/src/main.js project/src/backup_main.js'로 백업 파일 생성
디렉토리 이동: 'mv project/docs project/documentation'으로 docs 디렉토리 이름 변경
이와 같이 mkdir, touch, mv, cp 명령어를 조합하여 효율적으로 파일 및 디렉토리 구조를 관리할 수 있습니다.
git add: HEAD와 비교하여 워킹 디렉토리에 반영된 변경 사항들을 파일 단위로 스테이징 영역에 추가한다. 예: git add .(전부) / git add a/b/c.java(특정 파일만. 경로를 모두 포함해야함)
git commit: 스테이징 영역에 있는 모든 변경사항을 스냅샷을 만들어 git history에 추가한다. 추가된 후 기존 HEAD였던 커밋은 만들어진 커밋의 이전 커밋이 되며 만들어진 커밋은 최신 커밋. HEAD가 된다. 예: git commit -m "commit message"
git add는 변경된 파일을 스테이징 영역에 추가하는 명령어입니다. 이는 파일을 Git이 추적할 수 있는 상태로 만들어주며, git add [파일명] 또는 git add . 형식으로 사용할 수 있습니다. 스테이징 영역에 올라간 파일들은 아직 최종 저장된 상태가 아니며, commit 명령어를 통해 최종 저장이 이루어집니다.
git commit은 스테이징된 변경 사항을 저장소에 영구적으로 기록하는 명령어입니다. git commit -m "커밋 메시지" 형식으로 사용되며, 이 시점에서 스테이징 영역에 있던 파일들의 변경사항이 실제로 저장됩니다.
두 명령어의 관계는 다음과 같습니다:
git add를 통해 변경사항을 임시로 스테이징 영역에 올려두고, git commit을 통해 이러한 변경사항들을 하나의 의미 있는 변경 단위로 묶어 저장하는 것입니다.
커밋 메시지는 변경 사항을 설명하는 중요한 요소입니다. 따라서 커밋 메시지는 간결하면서도 변경사항의 핵심적인 내용을 담고 있어야 하며, 이는 나중에 히스토리를 확인할 때 변경사항을 쉽게 이해할 수 있게 해줍니다.
main: 실제 서비스에 사용될 브랜치
develop: main에 반영되기 직전의 개발단계의 브랜치
feature: develop에서 파생되어 develop에 merge/rebase될 기능 개발 단위의 브랜치
release: main에 병합되기 전 QA, 배포 테스트를 위한 브랜치. 버전을 태그로 남기는 경우가 많음. 배포에 문제가 없을 경우 main에 병합하고 수정 사항이 있었다면 develop에도 병합함
hotfix: 긴급하게 수정해야할 코드를 수정하는 브랜치. main에서 파생되어 급한 불을 끄고 main에 병합한다. develop을 거치기엔 너무 오래걸릴 때 사용한다.
main 브랜치는 항상 배포 가능한 상태를 유지하는 주요 브랜치입니다. 이 브랜치는 안정적이고 검증된 코드만을 포함하며, 실제 서비스에 배포되는 코드의 기준이 됩니다.
develop 브랜치는 개발 단계에서 사용되는 브랜치로, 새로운 기능이나 버그 수정이 통합되는 곳입니다. 이 브랜치는 다음 릴리스를 위한 개발 작업이 진행되는 공간으로, feature 브랜치들이 처음으로 병합되는 지점입니다.
feature 브랜치는 새로운 기능을 개발할 때 사용하는 브랜치입니다. develop 브랜치로부터 분기되어 독립적으로 새로운 기능을 개발하고, 개발이 완료되면 다시 develop 브랜치로 병합됩니다. 예를 들어, 'feature/login'이나 'feature/payment' 같은 이름으로 브랜치를 생성하여 사용합니다.
release 브랜치는 배포 준비가 완료된 기능을 안정화하기 위해 사용하는 브랜치입니다. develop 브랜치에서 분기되어 생성되며, 여기서는 버그 수정과 배포 준비를 위한 미세 조정만 수행됩니다. 테스트가 완료되면 main 브랜치와 develop 브랜치 모두에 병합됩니다. 예를 들어, 'release/v1.0'과 같은 이름으로 사용됩니다.
hotfix 브랜치는 배포된 버전에서 발생한 긴급한 버그를 수정할 때 사용됩니다. main 브랜치에서 직접 분기하여 생성하며, 버그 수정이 완료되면 main 브랜치와 develop 브랜치 모두에 병합됩니다. 예를 들어, 서비스 운영 중 심각한 보안 취약점이 발견되었을 때 'hotfix/security-patch' 같은 이름으로 브랜치를 만들어 신속하게 대응할 수 있습니다.
이러한 브랜치 전략을 통해 안정적인 개발과 배포가 가능해지며, 팀 구성원들이 효율적으로 협업할 수 있습니다. 각 브랜치는 명확한 목적과 역할을 가지고 있어 체계적인 개발 프로세스를 구축할 수 있게 해줍니다.
추상화(Abstraction): 실제 사물, 관계, 행동 등을 핵심적인 키워드로 간략하게 표현하는 성질이다. 실제 사물은 복잡하더라도 필요한 요소만 정의해놓음으로서 복잡성을 단순화하여 사용할 수 있게 해준다. 어떤 것이든 객체로 추상화하여 표현할 수 있고, 구성 요소들은 멤버 변수, 행동들은 메서드로 표현할 수 있다. 메서드의 이름만 알고 있으면 내부의 복잡한 연산을 알지 못해도 사용할 수 있게 해주는 것이 추상화의 장점이다.
캡슐화(Encapsulation): 객체 내의 정보 은닉을 해야한다는 성질이다. 외부에서 객체 내부의 변수들을 직접 접근할 수 없고, getter/setter/메서드들로 간접적으로 접근해야한다는 성질이다. 자바에서는 접근 제어자 키워드로 캡슐화를 지원한다. 메서드에서 Object를 반환할 때에도 불변 객체를 반환하여 캡슐화 성질을 유지해야한다. getter/setter/메서드들에서 인증과 인가를 포함한 검증을 추가하여 객체 변수를 제한적으로 다룰 수 있게 한다.
상속(Inherit): 객체는 다른 객체를 상속할 수 있도록 확장에 열려있게 설계해야한다는 성질이다. 여러 객체가 재사용하는 동일한 특성을 부모 객체에 정의해놓음으로서 재사용성을 높이고 다형성을 지원할 수 있게된다.
다형성(Polymorphism): 서로 다른 객체에 동일한 코드를 실행했을 때, 결과값이 다를 수 있다는 성질이다. Java 에서는 객체 상속과 인터페이스 구현으로 다형성을 지원한다. 상속, 구현한 하위 객체에서는 메서드 override를 통해 같은 메서드라도 다른 기능을 수행할 수 있게된다. 생성자 또는 메서드에서 파라미터의 종류와 갯수를 달리하여 오버로딩을 통해서도 다형성을 구현할 수 있다.
추상화: 복잡한 시스템에서 핵심적인 부분만을 추출하여 단순화하는 것입니다. 예시: 자동차 클래스를 설계할 때, 운전에 필요한 '가속', '감속', '정지' 같은 핵심 기능만 추출하고, 엔진의 내부 동작과 같은 세부적인 내용은 추상화합니다.
캡슐화: 데이터와 이를 처리하는 메서드를 하나의 단위로 묶고, 외부 접근을 제한하는 것입니다. 예시: 은행 계좌 클래스에서 잔액(balance) 변수를 private으로 선언하고, 입금(deposit)과 출금(withdraw) 메서드를 통해서만 접근하도록 하여 데이터의 무결성을 보장합니다.
상속: 기존 클래스의 특성을 다른 클래스가 물려받아 재사용하거나 확장하는 것입니다. 예시: Animal 클래스를 만들고, Dog, Cat 클래스가 이를 상속받아 기본 특성(먹기, 자기)은 재사용하면서 각자의 특성(짖기, 야옹하기)을 추가할 수 있습니다.
다형성: 동일한 인터페이스를 통해 서로 다른 객체가 다른 방식으로 동작하는 능력입니다. 예시: Animal 클래스의 makeSound() 메서드를 Dog에서는 "멍멍", Cat에서는 "야옹"으로 다르게 구현하여, 같은 메서드 호출로 다른 동작을 수행할 수 있습니다.
이러한 특징들은 코드의 재사용성을 높이고, 유지보수를 용이하게 하며, 프로그램의 구조를 더 명확하게 만듭니다. 추상화와 캡슐화는 복잡성을 관리하고, 상속과 다형성은 코드의 재사용성과 확장성을 제공합니다.
List: ArrayList, LinkedList 등의 구현 클래스가 있는 리스트(배열) 구조의 인터페이스이다. 배열이라는 단어는 Java의 레거시한 Array([])를 의미하기 때문에 별도로 List(리스트)라고 칭한다. 배열과 다른 점은, 크기를 지정하지 않고 사용할 수 있으며, 리스트는 동적 배열이기 때문에 메모리가 부족하지 않는한 size에 제한이 없다.(기본 크기가 가득 차면 자동으로 2배 크기의 배열로 복사시킴) List는 배열처럼 순서가 있는 유한한 요소들의 집합으로 index를 통해 요소에 접근할 때 O(1)의 시간복잡도를 가진다는 특징이 있다. 실제 사용시 인덱스를 통해 접근할 일이 많고, 순서가 중요한 경우에 리스트를 사용한다. get,(int i) set(int i, E e), remove(E e), removeAt(int i), clear(), contains(E e) 등의 메서드를 사용할 수 있다. ArrayList는 동적 배열, LinkedList는 이중 연결 배열로 구현되어있다.