# Daily

  • 따로 관리하던 프로젝트를 병합해야 하는 상황이 발생했다.

  • git merge --allow-unrelated-histories 옵션을 통해 비교적 간단히 이 작업을 수행할 수 있다.

  • 합쳐진 단일 프로젝트에서 기존의 다수 프로젝트의 commit history를 모두 유지할 수 있다.


예시) 아래의 경우는 필자가 실제로 직면한 상황이다.

Original-Project/
         	.git/
         	.gitignore
         	README.md
         	App.java
         
Original-Server/
		.git/
		.gitignore
		README.md
		ServerApp.java
		
Original-Client/
		.git/
		.gitignore
		README.md
		ClientApp.java
  • 대략적으로 위와 같은 상황이 발생했으며, 하나의 저장소에 세 개의 프로젝트를 모두 병합해야 한다.

  • 위의 상황에서 각 프로젝트는 git 프로젝트이며, 간략화 했지만 다수의 파일이 존재한다.

  • 명령을 이해하며 따라가면 손쉽게 아래와 같은 구조를 만들 수 있다.


결과)

Original-Project/
         .git/
         .gitignore
         Original-Project/
         		README.md
         		App.java
         			
         Original-server/
         		README.md
         		ServerApp.java
         			
         Original-Client/
         		README.md
         		ClientApp.java       
  • 기존의 프로젝트와 서버, 클라이언트로 세 개의 저장소가 존재했고, 각 저장소는 git으로 관리되고 있었다.

  • 이를 하나의 저장소에 합치며 단일 git 프로젝트로 만든 것이다.


과정)

# 먼저 각 프로젝트 폴더를 아래와 같이 구성한다.
# git과 관련된 파일 및 폴더를 제외하고 나머지 파일을 모두 현재의 프로젝트 폴더 이름과 동일한 폴더에 위치시킨다.
Original-Project/
         .git/
         .gitignore
         Original-Project/
         		README.md
         		App.java
         
Original-Server/
	.git/
	.gitignore
	Original-Server/
			README.md
			ServerApp.java
		
Original-Client/
	.git/
	.gitignore
	Origianl-Client/
			README.md
			ClientApp.java

이후 아래의 과정을 수행한다.

# Original-Project의 경로는 /home/user/git/Original-Project 로 가정한다.
# 또한 Original-Server와 Original-Client의 위치는 Original-Project의 위치와 동일하다고 가정한다.
# Original-Project/ 위치에서 아래의 명령을 수행한다.

$ git remote add server ../Original-Server
$ git fetch server
$ git merge --allow-unrelated-histories server/master
$ git remote remove server
$ git add .
$ git commit -m "Merge server project into original-project"

$ git remote add client ../Original-Client
$ git fetch client
$ git merge --allow-unrelated-histories client/master
$ git remote remove client
$ git add .
$ git commit -m "Merge client project into original-project"
  • 원격 저장소를 연결할 때 별칭이나 폴더명은 본인에 맞게 적절히 적용한다.

  • 병합시에 .gitignore 파일이 충돌할 수 있다.

    • 충돌은 파일을 열어 적절히 수정하고 commit하여 해결한다.

  • commit history가 유지되는 것을 확인하고, 추가적으로 필요하다면 github에 새로운 remote repository를 만들어 push할 수 있다.

  • --allow-unrelated-histories 옵션은 세 개의 프로젝트의 commit history의 조상이 같지 않기 때문에 사용한다.

    • 커밋 조상이 같지 않은 프로젝트를 병합하는 것을 허용하겠다는 의미이다.


 

설정

사용자 이름과 이메일 설정

  • git config --global user.name "UserName"
  • git config --global user.email "UserEmail"

 

 

텍스트 편집기 설정

  • git config --global core.editor vim

 

Line Ending 설정

  • git config --global core.autocrlf [ true | input | false ]
    • windows에서는 true로 설정하고 linux, mac, unix에서는 input을 사용한다.

Local Repository를 위한 Git Command

  • git init
    • git 저장소 초기화

 

  • git add [ filename | . | * ]
    • untracked 파일을 tracked로 만들거나 unstaged 파일을 staged로 만들 때 사용
    • 즉, 추적하지 않은 파일을 추적하거나 수정된 파일을 commit 하기 위해 staging area에 등록하는 데 사용하는 명령어

 

  • git commit
    • staged 상태의 내역을 최종적으로 저장소에 반영하는 명령
    • -a 옵션은 add를 동시에 수행하며, -m 옵션은 간단한 commit 메시지 작성을 위해 사용한다.

 

  • git commit --amend
    • git status가 clean한 상태에서 최신 커밋(마지막 커밋) 내용을 수정한다.
      • 부가적으로 설명하면, 마지막 커밋의 내용을 수정하는 것이 아니라, 마지막 커밋을 대체하는 새로운 커밋을 만드는 것이다.
      • 해당 커밋의 체크섬 값이 변화하는 것을 확인할 수 있다.
    • 이미 remote repository에 push한 경우 주의해서 사용한다.

 

  • git status
    • 현재 저장소의 상태 확인을 위한 명령
    • 추적되지 않은 파일이 있거나 변경되었는데 commit되지 않은 내역 등을 알려준다.

 

  • git branch
    • 해당 명령 자체로는 어떠한 branch가 존재하는지 확인할 수 있다.
    • -a 옵션 또는 -r 옵션을 이용하여 원격 저장소의 연결된 브랜치를 확인할 수 있다.

 

  • git branch [ BranchName ]
    • 해당 브랜치를 생성한다.

 

  • git checkout [ BranchName ]
    • 해당 브랜치로 체크아웃한다.
    • -b 옵션을 통해 브랜치를 생성하면서 동시에 체크아웃할 수 있다.

 

  • git merge [ BranchName ]
    • 현재 작업중인 branch에 명시한 branch를 병합한다.

 

  • git log
    • -5와 같이 옵션을 사용해 해당 개수만큼 로그를 확인할 수 있다.

 


Remote Repository를 위한 Git Command

  • git clone https://github.com/user-name/repository-name.git  
    • 위의 형태로 원격 저장소의 내용을 로컬 저장소로 가져올 수 있다.
    • clone 한 저장소의 별칭은 따로 명시하지 않으면 origin으로 지어진다.

 

  • git remote add origin https://github.com/user-name/repository-name.git 
    • 원격 저장소와 로컬 저장소를 연결한다.
    • 위의 경우는 origin이라는 별칭으로 현재 로컬 저장소와 링크로 명시한 원격 저장소를 연결한다.

 

  • git remote -v
    • 원격 저장소와의 연결을 확인할 수 있다.

 

  • git push
    • 기본적으로 commit을 원격 저장소의 master branch에 업로드한다.
    • 또한, 다양한 옵션을 통해 특정 branch를 가져오거나 업로드할 수 있으며 tag를 업로드할 수 있다.

 

  • git push origin [ --all | BranchName ]
    • 현재 로컬 저장소의 모든 branch를 별칭에 해당하는 원격 저장소에 업로드한다.
    • 만약 원격 저장소에 로컬 저장소에서 업로드하는 이름의 branch가 없다면 새로 생성한다.

 

  • git pull & git fetch
    • 원격 저장소의 정보를 가져와 로컬 branch에 merge까지 수행한다.
      • 즉, fetch + merge의 형태이다.
    • pull을 사용하면 병합되면서 변경된 프로젝트의 세세한 부분을 파악할 수 없다.
      • 따라서 팀 프로젝트에서 권고되지 않으며, fetch를 이용해 원격 저장소의 커밋을 가져오고 로컬 저장소에서는 이를 수동으로 merge 하는 방법이 권고된다.

기타 명령어

  • git tag [태그 내용] [commit checksum]
    • 특정 커밋을 참조하는 태그를 붙인다.
    • 간단하게 이름만 붙이는 light weight tag와 보다 많은 정보 전달을 위한 annotated tag가 있다.
    • 보통 배포 버전을 명시하는데 활용된다.

 

  • git tag -l
    • 현재 저장소에 존재하는 태그의 리스트를 출력한다.

 

  • git show-ref --tags
    • 태그와 함께 태그가 붙은 commit의 체크섬 값을 같이 출력한다.

 

  • git tag -a [태그 내용] [commit checksum]
    • annotated 태그를 붙인다.
    • 해당 명령을 수행하면 에디터가 실행된다.
      • 보통 언제, 누가, 왜 이 태그를 붙였는지 입력한다.

 

  • git show [tag]
    • 태그를 확인한다.

 

  • git push [remote repository] [branch] --tags
    • 로컬의 특정 branch의 모든 태그를 명시한 별칭의 원격 저장소에 push
    • oriigin master가 기본값

 

[JAVA] 제너릭 메소드(Generic Method) 설명 및 예제

  • 이 포스팅은 이미 제너릭을 학습했고, 제너릭 메소드의 개념이 모호하신 분들이 읽으시길 추천드립니다.

제너릭 메소드

  • 제너릭 메소드는 파라미터 타입과 반환 타입으로 타입 파라미터를 가지는 메소드를 말한다.
  • 아래와 같이 메소드의 반환타입 앞에 "<T>" 형태로 명시한다.

     

public static <T> int add(T a, T b) { ... } 
  • 해당 타입 파라미터는 메소드 내에서만 유효하다.
    • 제너릭 클래스에서 명시한 타입 파라미터와 메소드에서 명시한 타입 파라미터는 다르다.

이미 제너릭을 학습한 개발자라면 위의 내용을 이해하는데 무리가 없을 것이다. 본격적으로 예제로 살펴본다.

public static void main(String[] args) {
    
    /* add1 */
    List<String> stringList = add1(new LinkedList<>(), "AAA");
    System.out.println(stringList);
    //List<Integer> integerList = add1(new LinkedList<>(), 123); // Error
    System.out.println("--------------------");
}  
private static List<String> add1(List<String> list, String element) {
    list.add(element); 
    return list;
}

위와 같이 하나의 List와 문자열을 인자로 받아 리스트에 해당 문자열을 추가한 뒤 새로운 List를 반환하는 함수가 있다고 가정한다. 위 코드는 객체지향 프로그램에 적합하지 않는 코드이다. 만약 Integer 형태의 요소를 추가하고 싶다면 메소드를 오버로딩 해야하는가? 우린 조금전에 제너릭 메소드를 학습했다. 바로 적용해본다.

 

public static void main(String[] args) {    
    /* add2 */
    List<String> stringList2 = add2(new LinkedList<>(), "AAA");
    System.out.println(stringList2);
    List<Integer> integerList2 = add2(new LinkedList<>(), 123); // Good
    System.out.println(integerList2);
    // LinkedList<Double> doubleList2 = add2(new LinkedList<>(), 3.1415); // Error    
    System.out.println("--------------------");
}
private static <T> List<T> add2(List<T> list, T element) {
    list.add(element);
    return list;
}

제너릭 메소드의 형태로 바꾸고 모든 레퍼런스 타입이 사용 가능해졌다. 하지만 파라미터의 타입과 반환 타입이 List에 한정되어 있다. 예를들어, Collection의 형태로 파라미터를 전달할 수 없다.

  • 이 문제에서 Collection을 전달하고 싶다면?

  • 더하여 반환 타입을 Collection이 아니라 인자로 전달되는 타입(Collection의 하위 클래스가 될 수 있음)으로 지정하고 싶다면?

제너릭 메소드의 작은 변형이 이를 가능하게 해준다.

 

  public static void main(String[] args) {
    /* add3 */
    Collection<String> stringList3 = add3(new LinkedList<>(), "AAA");
    System.out.println(stringList3);
    //List<Integer> integerList3 = add3(new LinkedList<>(), 123); // Error
    System.out.println("--------------------");
  }
  private static <T> Collection<T> add3(Collection<T> list, T element) {
    list.add(element);
    return list;
  }

위 코드는 다형성을 이용해 Collection의 하위 클래스들을 파라미터로 전달 가능하게 만들었다. 하지만 이전 메소드인 add2에서 명시한 두 번째 요구사항을 충족하지 못했다. 즉, main 메소드에서 List<String> stringList = add(new LinkedList<>(), "AAA") 라는 명령을 수행할 경우 Collection 타입이 반환되기 때문에 에러가 발생하고, 이를 해결하기 위해 아래와 같이 명시적으로 형변환해야 한다.

  • List<String> stringList = (List<String>)add3(new LinkedList<>(), "AAA")

위의 문제를 해결하기 위해 마지막으로 조금 복잡한 형태의 제너릭 메소드를 사용한다.

 

  public static void main(String[] args) {
    /* add4 */
    Collection<String> stringList4 = add4(new LinkedList<>(), "AAA");
    System.out.println(stringList4);
    LinkedList<Integer> integerList4 = add4(new LinkedList<>(), 123);
    System.out.println(integerList4);
    List<Double> doubleList4 = add4(new ArrayList<>(), 3.1415);
    System.out.println(doubleList4);
  }
  private static <T, R extends Collection<T>> R add4(R collection, T element) {
    collection.add(element);
    return collection;
  }

최종적으로 위에서 발생한 문제들을 모두 해결한 형태가 add4 메소드이다. 이 메소드에서 타입 파라미터는 T, R이 사용되는데 T 타입의 인자를 강제했으므로 Collection에는 T 타입의 요소들만 사용 가능하다. 따라서 두 번째 인자로 전달되는 element의 타입과 충돌할 이유가 없다. 또한 나머지 타입 파라미터인 R을 보면 Collection 클래스로 상한 제한이므로 Collection을 포함한 하위 클래스에서만 사용 가능하다.

 

main 메소드의 예시들을 보면, add4의 결과로 Collection, LinkedList, ArrayList를 사용했을 때 문제가 없음을 확인할 수 있고 두 번째 인자로 넘어가는 element의 타입과도 충돌이 발생하지 않음을 확인할 수 있다.


 

'# Programming Language > Java' 카테고리의 다른 글

java.util.Date vs java.sql.Date  (1) 2019.12.18
Short-Circuit Evaluation  (0) 2019.12.18

JSP 프로젝트 구성

방법 01

GraalVM(JDK) + Eclipse + Tomcat 환경에서 Hello World를 작성해본다.

 


이클립스에서 프로젝트 준비

  • [File] - [New] - [Project]로 이클립스에서 프로젝트를 생성할 수 있다.
  • 항목 중 [Web]에서 [Dynamic Web Project]를 선택하고 JSP 개발을 위한 프로젝트를 만든다.
  • 프로젝트 이름을 설정하고, 필요에 따라 [Target Runtime]과 [Configuration]을 설정한다.
    • 현재는 <None>, <custum>으로 진행
  • 다음 단계는 소스 폴더를 설정하는 것인데, [src] 디렉토리를 사용한다.
    • 자바 소스코드는 [src]에 존재하며, 컴파일된 바이트 코드는 [build\classes]에 존재함을 알 수 있다.
  • Web Module 설정에서는 Context Root와 Content Directory를 볼 수 있다.
    • Context Root는 어플리케이션의 접속 경로를 설정한다.
      • 만약 test라고 지정할 경우 웹에서의 접속 경로는 https://localhost:8080/test 가 된다.
    • Context Directory는 JSP, HTML, 이미지 등의 파일이 위치할 디렉터리이다.
      • 기본값을 사용한다.
    • 마지막으로 아래의 web.xml 생성은 체크를 하도록 한다.
      • 추후에 다시 다루겠지만, 어플리케이션과 관련된 설정 내용을 저장하는 파일이다.
  • 추가적으로 프로젝트 생성 도중 이클립스 레이아웃을 JavaEE로 변경할 것인지를 선택하는 상자가 나온다.
    • JavaEE Perspective는 웹 개발에 적합하므로 변경하도록 한다.

Hello World 프로그램 작성

  • [Web Content] - [New] - [Folder] - [Test]
  • [Test] - [New] - [JSP File]
    • 파일이름은 HelloWorld.jsp이며 템플릿은 New Jsp File(html 5)를 사용한다.
  • jsp 파일을 만들고 나면 코드 왼쪽 상단에 `<%` 부분에 빨간줄이 그이면서 에러를 명시한다.

Error 해결 방법

  • 프로젝트에 오른쪽 버튼을 클릭하면 Properties 항목이 있다.
  • 해당 항목에서 왼쪽 탭에 Project Facets를 누른다.
  • 이후 [Java] - [Runtime]에서 설치한 Tomcat 디렉토리를 지정하면 에러가 사라진다.

Hello.jsp

<!-- 아래는 page 지시어로, JSP 페이지 형식을 지정한다. JPS 파일에 기본적으로 들어가 있어야 하며 추후에 다시 설명한다. -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>HelloWorld</h1>
    <!-- 아래는 간단한 JSP 표현식이다. -->
	new java.util.Date() : <%=new java.util.Date()%>
</body>
</html>

서버 설정

 

  • JSP 파일을 선택하고 [Run As] - [Run on Server]를 선택해 설치한 톰캣을 선택한다.
  • [Next]를 선택하면 다음 화면에서는 톰캣이 설치된 폴더를 지정한다.
  • [Next]를 선택하면 다음 화면에서는 실행에 포함시킬 프로젝트를 선택한다.
  • 실행 확인을 위한 다른 방법은, http://localhost:8080/project_name/jsp_file_name 에 연결할 수 있다.

 

방법 02

GraalVM(JDK) + Eclipse + Tomcat + gradle 환경에서  HelloWorld.jsp를 작성해본다.

 

  • webstudy라는 폴더를 만든 후 gradle init으로 초기화
    • Application, Java, Groovy, JUnit4 순서로 선택
  • 프로젝트 폴더에서 build.gradle 파일을 열어 수정
plugins {    
    id 'java'
    
    // 기존의 application 삭제 하고 아래 두 줄 추가
    id 'eclipse-wtp'
    id 'war'
}
repositories {
    jcenter()
}
dependencies {
    // 이 내용은 mvnrepository.com/ 에서 Java Servlet API를 선택하고 Gradle에 있는 내용 복사
    providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
    
    implementation 'com.google.guava:guava:28.0-jre'
    testImplementation 'junit:junit:4.12'
}
// 아래의 application { ... } 삭제

 

  • gradle eclipse 수행
  • src/main/webapp 추가
    • 아래에 index.html(또는 Hello.jsp)추가
  • src/main/java/App.java 삭제
  • src/test/java/AppTest.java 삭제
  • 이클립스에 프로젝트 추가
    • [File] - [Import] - [Existing Projects into Workspace] 에서 프로젝트 폴더 추가
  • 아래의 Servers에서 Tomcat 실행
    • Tomcat v9.0 Server at localhost 오른쪽버튼 - Add and Remove - 프로젝트 추가
  • 웹 브라우저에서 http://localhost:8080/project-name/index.html

  • 프로젝트가 커지면서 하위 디렉토리를 별도의 프로젝트로 분리해야하는 상황이 발생했다.
  • subtree 명령을 이용하여 쉽게 작업을 진행할 수 있다.
  • 분할된 각각의 프로젝트가 commit 내역을 유지하므로 Github에서 잔디를 유지할 수 있다.

예시) 아래의 경우는 필자가 실제로 직면한 상황이다.

Original_Project/		
         SubDirectory01/
         SubDirectory02/
         docs/
         .git/
  • 대략적으로 위와 같은 상황이 발생했으며, SubDirectory02가 너무 커져서 다른 프로젝트로 분리해야하는 상황이다.
  • 명령을 이해하며 따라가면 손쉽게 아래와 같은 구조를 만들 수 있다.

결과

new_project_name01/
		# 기존 폴더 내용 유지
        docs/         
        .git/

new_project_name02/
		# 기존 폴더 내용 유지
        docs/         
        .git/
  • 즉 SubDirectory01과 SubDirectory02가 하나의 프로젝트였지만, 각각의 프로젝트 디렉토리로 분리하고 필요한 파일들을 해당 프로젝트에 맞게 옮겨주는 작업이다.
  • 필요에 따라 Original_Project에 SubDirectory01을 남기고 SubDirectory02만 다른 프로젝트로 분리할 수 있다.

과정

# Original_Project/ 위치에서 아래의 명령을 수행한다.
# Original_Project의 경로는 /home/user/git/Original_Project 로 가정한다.

$ git subtree split -P SubDirectory02 -b copybranch
$ mkdir ../new_project_name02
$ cd ../new_project_name02
$ git init
$ git pull /home/user/git/Original_Project/ copybranch
$ git remote add origin https://github.com/user_id/new_project_name02
$ git remote -v
$ git push origin -u master
  • user_id와 new_project_name은 본인에 맞게 입력한다.
  • 위의 작업 이후 commit 내역은 유지되면서 SubDirectory02가 다른 프로젝트 폴더로 분리됐음을 확인할 수 있다.
  • 또한 가장 중요한 잔디가 살아있음을 확인할 수 있다.

SubDirectory01을 Original_Directory에 유지하고 싶다면 아래와 같은 작업을 수행한다.

# Original_Project/ 위치에서 아래의 명령을 수행한다.
# Original_Project의 경로는 /home/user/git/Original_Project 로 가정한다.

$ git rm -r SubDirectory02
$ git commit -m "split SubDirectory02 and remove SubDirectory02 in Original_Directory"
$ git branch -D copybranch
  • SubDirectory01 또한 다른 프로젝트 디렉토리로 구성해야 하는 상황이라면 위의 작업 대신 SubDirectory02에 진행한 작업을 수행한 후 기존의 Original_Directory를 로컬과 원격 저장소에서 제거한다.
  • 단, 삭제하기 전에 docs/ 와 같은 추가적으로 옮겨줘야 할 파일이 있다면 신경쓰도록 한다.

Git 저장소 만들기(git init, git clone)

두 가지 방법으로 Git 저장소를 생성할 수 있다.

하나는 기존에 사용하던 프로젝트 디렉토리를 Git 저장소로 만드는 것이고, 다른 하나는 서버에 있는 저장소를 로컬로 복제하는 것이다.


기존에 사용하던 디렉토리를 Git 저장소로 만들기

$ mkdir git_study
$ cd git_study
$ git init
  • 위 명령을 실행하면 git_study 디렉토리에 .git이라는 하위 디렉토리가 생성된다.
  • .git 디렉토리에는 프로젝트 저장소에 필요한 파일들이 들어 있다.
  • Git은 현재 어떤 파일도 관리하지 않으며, 파일을 관리하게 하려면 저장소에 파일을 추가하거나 수정하고 commit해야 한다.

 

$ git add Hello.java
$ git add .gitignore
$ git commit -m "create project directory"
  • git add 명령은 Stage Area(index)에 파일을 추가하고 git commit 명령은 Stage Area의 스냅샷을 찍어 로컬 저장소에 저장한다.
  • 자세한 내용은 추후에 다룬다.

기존 저장소를 복제하기

  • 오픈소스(다른 프로젝트)에 참여해서 기여하거나 다른 저장소를 복제하고 싶을 때 git clone 명령을 이용한다.
  • 기존의 VCS와의 차이점은 원격 저장소(서버)에 있는 거의 모든 데이터를 복사한다는 점이다.
    • 서버의 저장소가 망가져도 클라이언트의 저장소를 이용해 복구할 수 있다.
$ git clone https://github.com/yh0921k/TIL.git
$ git clone https://github.com/yh0921k/TIL.git myTIL # 다른 디렉토리 이름으로 clone

위의 명령은 TIL이라는 디렉토리를 만들고 그 안에 .git 디렉토리를 만들며 저장소를 초기화한다.

또한 서버의 히스토리를 모두 가져와서 적용하므로 당장 작업을 시작할 수 있다.


[출처]

https://git-scm.com/book/en/v2

[라이센스]

https://creativecommons.org/licenses/by-nc-sa/3.0/

Git의 세 가지 상태

2019. 12. 18. 14:46

Git은 파일을 Committed, Modified, Staged의 세 가지 상태로 관리한다.

  • Committed란 데이터가 로컬 데이터베이스에 안전하게 저장됐음을 의미한다.
  • Modified는 수정한 파일을 아직 로컬 데이터베이스에 commit하지 않은 상태를 말한다.
  • Staged란 현재 수정한 파일을 곧 commit할 것이라고 표시한 상태를 의미한다.

위의 세 가지 상태는 Git 프로젝트의 세 가지 단계와 연결된다.

  • Git 디렉토리, 워킹 트리, Staging Area를 이해해야 한다.

Git 디렉토리는 Git이 프로젝트의 메타데이터와 객체 데이터베이스를 저장하는 곳을 말한다.

  • .git 디렉토리가 Git의 핵심이다.
  • 다른 컴퓨터에 있는 저장소를 복제할 때 해당 디렉토리가 만들어진다.

워킹 트리는 프로젝트의 특정 버전을 Checkout 한 것이다.

  • Git 디렉토리는 지금 작업하는 디스크에 있고 디렉토리 안에 압축된 데이터베이스에서 파일을 가져와서 워킹 트리를 만든다.

Staging Area는 Git 디렉토리에 있다.

  • 단순한 파일이며, 곧 commit할 파일에 대한 정보를 저장한다.
  • "index"라는 이름으로 불리기도 하지만 Staging Area라는 명칭이 표준이 되어가고 있다.

Git에서 하는 일은 기본적으로 아래와 같다.

  1. 워킹 트리에서 파일을 수정한다.
  2. Staging Area에서 파일을 Stage 해서 commit할 스냅샷을 만든다.
  3. Staging Area에 있는 파일들을 commit해서 Git 디렉토리에 영구적인 스냅샷으로 저장한다.

즉, Git 디렉토리에 있는 파일들은 Committed 상태이다. 파일을 수정하고 Staging Area에 추가했다면 Staged이다. 그리고 Checkout 하고 나서 수정했지만, 아직 Staging Area에 추가하지 않았다면 Modified 이다.


[출처]

https://git-scm.com/book/en/v2

[라이센스]

https://creativecommons.org/licenses/by-nc-sa/3.0/

Git 시작하기

설치 및 Version 확인

Ubuntu를 기준으로 apt-get install git 명령을 이용하면 Git을 설치할 수 있다.

또한, 버전을 확인하기 위해 git --version 명령을 이용할 수 있다.


최초 설정

Git을 설치하고 사용환경을 적절하게 설정해야 한다. git config 명령은 설정 내용을 확인하고 변경할 수 있다.

Git은 아래의 세 가지 파일의 설정 내용에 따라 동작한다.

  • /etc/gitconfig
    • 시스템의 모든 저장소와 모든 사용자에게 적용되는 설정 파일
    • git config --system 명령으로 이 파일을 읽고 쓸 수 있다.
  • /.gitconfig, ~/.config/git/config
    • 현재 사용자와 해당 사용자가 사용하는 모든 저장소에 적용되는 설정 파일
    • git config --global 명령으로 이 파일을 읽고 쓸 수 있다.
  • .git/config
    • git 디렉토리에 존재하며 현재 작업 중인 프로젝트에 적용되는 설정 파일
    • --local 옵션을 사용해 사용할 수 있다.

각 설정은 3 > 2> 1 순으로 우선순위가 높다.


사용자 이름과 이메일 설정

Git을 설치하면 가장 먼저 해야하는 설정이다. Git은 commit을 할 때마다 이 정보를 사용하며, 한 번 커밋한 후에는 정보를 변경할 수 없다.

 

    git config --global user.name "User Name"

    git config --global user.email "Email Address"

 

위에서 말했다시피 --global 옵션으로 수행하는 설정은 한 번만 하면 된다.
약 프로젝트마다 다른 이름과 이메일 주소를 사용하고 싶으면 --global 옵션을 빼고 명령을 실행한다.

 

 

에디터 설정

Git에서 사용할 텍스트 에디터를 설정한다.

 

  git config --globla core.editor vim

 


설정 확인

git config --list

Git은 설정 값을 여러 파일에서 읽기 때문에 같은 설정이 존재할 수 있다. 이 때 Git은 가장 나중 값을 사용한다.

 

git config <Key>

위의 명령으로 Git이 특정 Key에 대해 어떤 값을 사용하는지 확인할 수 있다.


[출처]

https://git-scm.com/book/en/v2

[라이센스]

https://creativecommons.org/licenses/by-nc-sa/3.0/

 

 

java.util.Date vs java.sql.Date

2019. 12. 18. 14:43

java.util.Date vs java.sql.Date

  • 자바에서 Date 클래스를 사용하다 보면 java.util의 Date와 java.sql의 Date, 두 가지를 확인할 수 있다.
  • 이 글에서는 두 클래스의 차이를 확인한다.

java.util.Date

  • 1970년 1월 1일 00:00:00 GMT(Epoch Time 또는 POSIX Time) 이후의 특정 시점을 millisecond 단위로 나타낸다.
    • 따라서 클래스 내부에 UTC(협정 세계시)에 대한 정보를 가지고 있다.
  • 자바 11 기준 생성자는 아래와 같다.
Date()
Date(long date)
Date(int year, int month, int date)
Date(int year, int month, int date, int hrs, int min)
Date(int year, int month, int date, int hrs, int min, int sec)
Date(String s)
  • Date 클래스는 더이상 사용을 권고하지 않는다.
    • Date 클래스의 객체는 mutable이며, setTime(0) 등의 메소드로 내부 값을 변경할 수 있다.
      • Immutable 객체의 대한 장점은 이 글에서 다루지 않는다.
    • 또한 Date 클래스는 UTC를 사용하기 때문에 한계를 가진다. 
      • 시스템에 따라 UTC가 다를 수 있다.
  • Java 8이 도입되면서 java.time 패키지의 사용이 권고된다.

java.sql.Date

  • java.sql.Date 클래스는 java.util.Date 클래스를 상속한다.
    • 해당 클래스의 사용 목적은 년도, 월, 일을 유지하는 SQL 데이터를 다루기 위함이다.
    • 즉, 시간 정보는 다루지 않고 0으로 초기화된다.
Date(int year, int month, int day)
Date(long date)

 

  • 해당 클래스는 데이터베이스를 다룰 때 사용되어야 한다.
    • 시간 정보를 유지하지 않으므로, 로컬 환경과 데이터베이스 간의 시간 변환은 JDBC 드라이버의 구현에 따라 다르다.
    • 마지막으로 SQL TIME, SQL TIMESTAMP와 같은 SQL의 데이터 타입을 처리하기 위해 java.sql의 Time 클래스 또는 Timestamp 클래스를 사용할 수 있다.

Conclusion

  • java.util.Date는 Epoch Time 이후 날짜, 시간 정보를 저장한다.
  • java.sql.Date는 시간 정보가 없이 날짜 정보만 저장하며, JDBC에서 일반적으로 사용된다.
  • 자바 8 이후에서는 java.util.Date의 사용을 권고하지 않는다.

Short-Circuit Evaluation

2019. 12. 18. 14:41

Short-Circuit Evaluation

  • SCE를 다루기에 앞서 자바의 논리 연산자를 생각해보자.
  • 논리 연산자에는 AND(&&) 연산과 OR(||) 연산이 있다.
    • 논리 연산자는 피연산자로 boolean 타입 또는 boolean 타입의 값을 결과로 하는 조건식을 취할 수 있다.
    • && 연산이 || 연산보다 우선순위가 높으므로, 함께 사용할 때 괄호를 적절히 사용해야 한다.

AND( && ) 연산

  • 피연산자가 양쪽 모두  참이면 true를 반환한다.

OR( || ) 연산

  • 피연산자 중 한쪽이 참이면 true를 반환한다.
x y x || y x && y
true true true true
true false true false
false true true false
false false false false

SCE

  • 조금만 생각해보면 && 연산에서 왼쪽 피연산자의 조건이 false이면 오른쪽 연산은 볼 필요가 없다는 것을 알 수 있다. 
    • 마찬가지로 ||연산에서 왼쪽 피연산자의 조건이 true이면 어차피 전체 식은 true 이므로 오른쪽의 연산을 확인할 필요가 없다.
      • 즉, 왼쪽의 인자가 전체 식의 값을 결정하기에 충분하지 않은 경우에만 오른쪽의 인자를 평가한다.
    • 더 나아가 논리식이라도 피연산자의 위치에 따라서 연산 속도가 달라질 수 있다.
      • && 연산의 경우, 연산 결과가 false가 나올 가능성이 높은 피연산자를 왼쪽에 놓아야 더 빠른 로직을 구현할 수 있다.
// 아래 코드의 결과를 확인하여 SCE가 무엇인지 확인한다.
int i = 10;
int j = 0;
while(i-->0 || j++<10)
    System.out.printf("%d, %d\n",  i, j);

+ Recent posts