마우스 이벤트

이벤트 타입 설명
mousedown 마우스 버튼을 누르는 순간
mouseup 마우스 버튼을 눌렀다 떼는 순간
click 왼쪽 버튼을 클릭한 순간
dblclick 왼쪽 버튼을 빠르게 두 번 클릭한 순간
contextmenu 오른쪽 버튼을 클릭한 순간
mousemove 마우스를 움직이는 순간
mouseover 마우스 포인터가 요소 위로 올라온 순간
mouseout 마우스 포인터가 요소에서 벗어나는 순간
mouseenter 마우스 포인터가 요소 위로 올라온 순간 (버블링이 일어나지 않음)
mouseleave 마우스 포인터가 요소에서 벗어나는 순간 (버블링이 일어나지 않음)

키보드 이벤트

이벤트 타입 설명
keydown 키보드의 버튼을 누르는 순간
keypress 키보드의 버튼을 누르는 순간 ('a', '5' 등 출력이 가능한 키에서만 동작하며, Shift, Esc 등의 키에는 반응하지 않음)
keyup 키보드의 버튼을 눌렀다 떼는 순간

포커스 이벤트

이벤트 타입 설명
focusin 요소에 포커스가 되는 순간
focusout 요소로부터 포커스가 빠져나가는 순간
focus 요소에 포커스가 되는 순간 (버블링이 일어나지 않음)
blur 요소로부터 포커스가 빠져나가는 순간 (버블링이 일어나지 않음)

입력 이벤트

이벤트 타입 설명
change 입력된 값이 바뀌는 순간
input 값이 입력되는 순간
select 입력 양식의 하나가 선택되는 순간
submit 폼을 전송하는 순간

스크롤 이벤트

이벤트 타입 설명
scroll 스크롤 바가 움직일 때

윈도우 창 이벤트

이벤트 타입 설명
resize 윈도우 사이즈를 움직일 때 발생

 

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

새로운 데이터 타입과 특징  (1) 2024.12.15
이벤트 자세히 다뤄보기  (1) 2024.12.15
자바스크립트 이벤트  (0) 2024.12.14
console.log와 console.dir의 차이  (0) 2024.12.13
객체, 요소, 노드  (1) 2024.12.13

이벤트 종류 알아보기

1. 이벤트 핸들러 등록하기

HTML의 속성이나 DOM 프로퍼티를 활용해 이벤트를 등록하는 방법 외에 Element.addEventListener('type', 'handler')를 통해서 이벤트 핸들러를 등록할 수 있다. 이 방법이 이벤트 핸들러를 등록할 때 가장 권장되는 방법이다. 이렇게 하면 하나의 요소에 여러개의 독립적인 이벤트 핸들러를 등록할 수가 있다.

<body>
  <div id="content" class="btns">
    <button id="myBtn">JS Click!</button>
    <button onclick="console.log('Hello Codeit!')">HTML Click!</button>
  </div>
  <script src="index.js"></script>
</body>
// 이벤트 등록하기
let btn = document.querySelector('#myBtn');

// btn.onclick = function () {
// 	console.log('Hi Code World!');
// };
// 이렇게 dom요소에 접근에 onclick 프로퍼티를 활용하는 방법 같은 이벤트 핸들러는 한가지 문제를 가지고 있다.
// innerHTML이나 className같은 프로퍼티를 활용할 때도 프로퍼티에 어떤 값을 할당하는 방식은 
// 기존에 있던 값을 덮어쓰는 형태로 동작하기 때문에 기존에 값을 유지하면서 일부만 수정하기는 어려운 단점이 있었다.
// onclick 프로퍼티도 새로 쓰면 기존의 값을 덮어쓴다.

function event1() {
	console.log('Hi Codeit!');
}

function event2() {
	console.log('Hi again!');
}
//위에 코드를 실행시킨다면 Hi Codeit!은 나오지 않고 Hi again!만 출력된다.
//지금은 간단한 코드이지만 각 이벤트 별로 중요한 리턴 값이 있을 경우에 그 리턴 값도 다뤄야 하는 문제가 생긴다.

// elem.addEventListener(event, handler)
btn.addEventListener('click', event1);
btn.addEventListener('click', event2);

Element.addEventListener('event', 'handler')는 이벤트 타입을 문자열로 첫번째 파라미터에 입력하고, 두번째 파라미터에는 이벤트 핸들러를 전달하면 된다. 메소드를 여러번 호출하게 되도 하나의 요소에 여러개의 독립적인 이벤트 핸들러를 등록할 수 있다.

실행해보면 이벤트1과 이벤트2가 동시에 실행되는것을 확인 할 수 있다.


2. 이벤트 핸들러 삭제하기

addEventListener 메소드를 활용해서 이벤트 핸들러를 등록했다면, Element.removeEventListner('type', 'handler')를 통해서 이벤트 핸들러를 삭제할 수 있다. 등록할 때와 똑같이 파라미터를 전달하면 해당되는 이벤트 핸들러가 삭제되는 방식이다.

단, 이벤트를 삭제할 땐 반드시 이벤트를 등록할 때 외부에 함수를 만들어서 해당 함수의 이름으로 핸들러를 전달해줘야 한다.

// elem.removeEventListener(event, handler)
btn.removeEventListener('click', event2);


btn.addEventListener('click', function() {
  console.log('event3!');
});

btn.removeEventListener('click', function() {
  console.log('event3!');
});

//이렇게는 생성도, 삭제도 되지 않는다.

function event3() {
  console.log('Hi event3!');
};
//이렇게 변수에 담아서

btn.addEventListener('click', event3);
//사용을 해주어야 한다

btn.removeEventListener('click', event3);

3. 이벤트 객체 (Event Object)

웹페이지에서 이벤트가 발생하면 관련된 정보를 담은 이벤트 객체가 만들어지고 이벤트 핸들러의 첫번째 파라미터로 전달된다. 이벤트 객체는 이벤트 종류마다 가지고 있는 프로퍼티가 다르고, 이벤트에 대한 유용한 정보들을 프로퍼티로 가지고 있다.

<body>
  <div id="content" class="btns">
    <input type="text" id="myInput" placeholder="type anything">
    <button id="myBtn">click me!</button>
  </div>
  <script src="index.js"></script>
</body>
// 이벤트 객체 (Event Object)
const myInput = document.querySelector('#myInput');
const myBtn = document.querySelector('#myBtn');

function printEvent(event) { //(event) 이벤트 핸들러의 첫번째 파라미터
  console.log(event);
    event.target.style.color = 'red';
}

myInput.addEventListener('keydown', printEvent);
myBtn.addEventListener('click', printEvent);

키보드를 누를땐 키보드 이벤트가, 클릭할 땐 클릭이벤트가 출력된다.
type은 이벤트 타입이, target은 이벤트가 발생한 요소를 담고 있다.

특히나 target은 DOM 요소가 담겨 있기 때문에 event.target.style.color = 'red'; 이런식으로 이벤트가 발생했을 때 해당 요소를 수정한다거나 혹은 그 요소가 가지고 있는 속성 값들을 참조해야 되는 상황에서 유용하게 활용된다.

프로퍼티 설명
type 이벤트 이름 (click, mouseup, keydown 등)
target 이벤트가 발생한 요소
currentTarget 이벤트 핸들러가 등록된 요소
timeStamp 이벤트 발생 시각(페이지가 로드된 이후부터 경과한 밀리초)
bubbles 버블링 단계인지를 판단하는 값

4. 이벤트 버블링 (Event Bubbling)

이벤트는 전파가 된다. 어떤 요소에서 이벤트가 발생하면 해당 요소에 등록된 이벤트 핸들러가 동작하는 것뿐만 아니라 (같은 타입의 이벤트에 한해서) 부모 요소로 이벤트가 계속해서 전파되면서 각 요소에도 등록된 이벤트 핸들러가 있다면 차례로 이벤트 핸들러가 동작한다.(최상단의 윈도우 객체를 만날때까지 반복)  자식 요소에서 부모 요소로 이벤트가 전파되는 것을 이벤트 버블링(Event Bubbling)이라고 한다.

이벤트 버블링이 일어나도 이벤트 객체의 target 프로퍼티는 변하지 않고 처음 이벤트가 발생한 시작점을 담고 있다.

참고로 이벤트 버블링은 이벤트 객체의 stopPropagation 메소드로 전파를 막을 수 있다.

for (let item of items) {
  item.addEventListener('click', function(e) {
    console.log('item Event');
    console.log(e.currentTarget);
    e.stopPropagation();
  });
};

//이 코드를 쭉 살펴보자면 items에 있는 item을 파라미터로 담고, 반복문을 실행한다.
//item에 클릭했을 때 이벤트 리스너 프로퍼티를 부여한다. 어떤 함수가 실행될거냐면
//console.log에 item Event라고 나오고, console.log에 이벤트 핸들러가 등록된 요소를 출력해주고
//버블링을 멈춰줘

위 코드를 위에서부터 해석해보자면,

for of 문으로 반복문을 실행할건데 items 함수에 담긴 item, 각 li 요소를 말한다. item이 클릭되는 이벤트가 발생하면 함수를 실행해주세요, 어떤 함수? console에 'item Event'라는 문자열 출력해주시고, console에 e.currentTarget 이벤트 리스너가 연결된 (핸들러가 등록된) 요소(즉, 클릭된 li 요소)를 출력해주세요. 그리고 나서 이벤트가 부모요소로 전파되는 버블링을 멈춰주세요.

메소드 하나로 간단하게 버블링을 막을 수는 있지만 정말 필요한 경우가 아니라면 가급적 버블링을 막는 일은 피하는것이 좋다. 지금처럼 아이템 영역에서 이벤트 버블링을 막아버리면 바로 위에 있는 리스트 뿐만 아니라 모드 부모요소 입장에서 아이템 영역만큼의 이벤트를 발생시킬 범위가 사라져버리게 된다.

예를들자면 페이지 전체에 어떤 이벤트를 만들고 싶을 경우 document나 body 같은 문서 전체를 다룰 수 있는 상위 요소의이벤트 핸들러를 만들어 줄텐데 버블링이 막혀있는 구간이 존재하게 되면 당연히 클릭 했을 때 버블링이 막혀버리기 때문에 그 부분만 원하는 이벤트 결과를 얻지 못한다. 버블링을 잘 이해하고 이벤트를 설계한다면 버블링을 막을 일이 많지 않다.

+여담

버블링 외에도 캡쳐링(capturing)이라는 흐름이 존재한다. 실제 코드에서 자주 쓰이진 않는다. 캡처링 단계에서 이벤트를 발생시켜야 하는 일은 매우 드물다.

  1. 캡처링 단계 : 이벤트가 하위 요소로 전파되는 단계
  2. 타깃 단계 : 이벤트가 실제 타킷 요소에 전달되는 단계 = 이벤트 객체의 target 프로퍼티가 되는 요소에 등록되어있던 이벤트 핸들러가 동작하는 단계 (가장 처음 이벤트 핸들러가 동작하는 순간)
  3. 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계

캡처링은 이벤트가 발생하면 가장 먼저, 그리고 버블링의 반대방향으로 진행되는 이벤트 전파 방식이다.

이벤트가 발생하면 가장먼저 window 객체에서부터 target까지 이벤트 전파가 일어나고, (캡쳐링) 타겟에 도달하면 등록된 이벤트 핸들러가 동작하고, (타깃) 이후에 다시 window 객체로 이벤트가 전파된다. (버블링)

자주 사용되진 않지만 그럼에도 불구하고 캡처링 단계에서 이벤트 핸들러를 동작해야 된다면? addEventListener에 세번째 프로퍼티에 true 또는 { capture:true }를 전달하면 된다.

for (let elem of document.querySelectorAll('*')) {
  elem.addEventListener("click", e => alert(`캡쳐링 단계: ${elem.tagName}`), true);
  elem.addEventListener("click", e => alert(`버블링 단계: ${elem.tagName}`));
}

5. 이벤트 위임 (Event Delegation)

버블링 개념을 활용하면 자식 요소 각각에 이벤트 핸들러를 하나씩 등록할 필요 없이 부모 요소에서 한 번에 자식 요소들에 발생한 이벤트를 관리할 수도 있다.

이렇게 이벤트를 다루는 방식을 자식 요소의 이벤트를 부모 요소에 위임한다고 해서 이벤트 위임(Event Delegation)이라고 한다.

예시 상황

만약 이미 있는 요소들에 이벤트 핸들러를 다 설정했는데 새로운 아이템을 추가 하는 상황이 발생하게 되면 추가된 아이템에는 이벤트 핸들러가 동작하지 않는다. 그래서 매번 추가할 때마다 이벤트 핸들러를 새로 등록해야 되는 문제가 있다. 이럴땐 이벤트 버블링을 활용하자.

자식요소에서 발생하는 이벤트를 부모요소에서 다루는 방식 = 이벤트 위임

리스트에 이벤트 핸들러를 하나밖에 등록하지 않았지만 아이템 각각의 이벤트 핸들러를 등록한것처럼 동작하고, 나중에 추가한 아이템도 이벤트 핸들러가 잘 동작한다. 하지만 그래도 문제가 한가지 있다. 자식요소를 제외한 온전한 부모요소를 클릭해도 이벤트 핸들러가 동작된다. item(li)영역을 벗어난 list(ul)영역을 선택해도 done class가 toggle되어 이벤트가 발생한다. 그래서 이벤트 위임을 할때는 명확하게 원하는 요소에서 의도한 동작이 일어나게끔 따로 처리를 해줘야한다.

// 이벤트 위임 (Event Delegation)
const list = document.querySelector('#list');

list.addEventListener('click', function(e) {
	// target프로퍼티의 tagName이 LI인지 확인하거나
	// if (e.target.tagName === 'LI')
  if (e.target.classList.contains('item')) {
    //classList의 contains 메소드를 이용해 item이라는 class를 가지고 있는지 확인하면 해결할 수 있다.
    e.target.classList.toggle('done');
  }
});

const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);

tagName 프로퍼티는 해당 요소의 태그 이름 값을 대문자로 담고 있는 프로퍼티이고, classList의 contains 메소드는 파라미터로 전달하는 값이 해당 요소의 클래스 속성에 있는지 확인해 불린형태로 결과를 리턴해주는 메소드이다.


6. 브라우저의 기본 동작

브라우저에는 각 태그별 혹은 상황별로 기본적으로 약속된 동작들이 있다.

예를 들어 마우스 오른쪽 버튼을 클릭하면 상황에 맞는 메뉴 창이 뜬다거나, input 태그에 커서를 두고 키보드 키를 누르면 해당 값이 입력된다거나 하는. 만약 이런 동작들을 막고 싶다면 이벤트 객체의 preventDefault 메소드를 통해 막을 수가 있다.

<body>
  <a id="link" href="https://www.codeit.kr/">Link</a>
  <input type="checkbox" id="checkbox">
  <input type="text" id="input" placeholder="input">
  <p id="text">
    I Love Codeit!
  </p>
  <script src="index.js"></script>
</body>
// 브라우저의 기본 동작
const link = document.querySelector('#link');
const checkbox = document.querySelector('#checkbox');
const input = document.querySelector('#input');
const text = document.querySelector('#text');

//event.preventDefault 브라우저의 기본적인 동작을 막는 메소드
link.addEventListener('click', function(e) {
  e.preventDefault(); //링크가 클릭되면 기본동작(href속성 값으로 넘어가는것)이 되지 않고
  alert('지금은 이동할 수 없습니다.'); //경고창을 띄워주세요.
});

//키도브 이벤트로 활용해보기
input.addEventListener('keydown', function(e) {
  if (!checkbox.checked) { //체크박스가 체크되지 않으면
    e.preventDefault(); //input태그에서 키가 입력되지 않게 막아주시고
    alert('체크박스를 먼저 체크해 주세요.'); //경고창을 띄워주세요.
  }
});

//마우스 우클릭 방지해보기, 마우스 우클릭 = contextmenu 라는 타입으로 이벤트가 발생된다.
text.addEventListener('contextmenu', function(e) {
	e.preventDefault(); //다른곳에서는 우클릭이 되지만 텍스트 위에서 우클릭을 할 경우
	alert('마우스 오른쪽 클릭은 사용할 수 없습니다.'); //경고창이 띄워진다.
});

//문서 전체에 우클릭 방지를 하고 싶다면 text를 document로 바꿔주면 된다.

하지만 각 HTML 태그들이 가지고 있는 고유한 역할과 의미를 훼손하게 될 수도 있기 때문에 꼭 필요한 경우에만 주의해서 사용해야 한다.


'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

이벤트 자세히 다뤄보기  (1) 2024.12.15
어떤 이벤트들이 있을까?  (0) 2024.12.14
console.log와 console.dir의 차이  (0) 2024.12.13
객체, 요소, 노드  (1) 2024.12.13
이벤트와 클릭  (0) 2024.12.13

여러 개발자가 하나의 저장소에 작업을 할 때, 협업을 좀 더 효과적으로 하기 위해 git branch 에 대한 규칙을 정하고 저장소를 잘 활용하기 위한 workflow 를 정의하는 것을 바로 git branch 전략이라고 한다.

그 중에서도 대표 브랜치 전략인 flow에 대해서 알아보자.

Git Flow는 소프트웨어 개발에서 Git을 사용하여 브랜치를 관리하는 대표전략 중 하나로, 팀의 협업을 효율적으로 지원한다. 이 전략은 명확한 브랜치 구조를 제공하여 개발, 배포, 유지보수를 체계적으로 관리할 수 있게 해준다. 

브랜치 종류

Main (혹은 Master)   Develop Feature Release Hotfix
제품 출시 버전을 관리하는 메인 브랜치 다음 출시 버전을 위해 개발하는 브랜치 새로운 기능을 개발하는 브랜치 다음 출시 버전을 준비하는 브랜치 출시된 제품의 버그를 고치기 위한 브랜치

특징 및 장점

1. 명확한 브랜치 구조: 각 브랜치의 용도와 역할이 명확하게 정의되어 있어 협업이 용이
2. 효율적인 작업 관리: 기능 개발, 버그 수정, 배포 준비 등의 작업이 체계적으로 관리된다.
3. 릴리즈 준비 과정의 독립성: 릴리즈 준비와 기능 개발이 독립적으로 진행될 수 있어, 안정성을 높인다.
4. 버전 관리 용이: 각 릴리즈 버전이 명확하게 관리되어, 이전 버전으로의 롤백이 쉬워진다.

*릴리즈(Release) : 특정 버전의 소프트웨어를 공식적으로 배포하거나 공개하는 과정
*롤백(Rollback) : 특정 변경 사항이나 상태를 이전 버전으로 되돌리는 과정

단점

1. 복잡성: 브랜치가 많아질수록 관리가 복잡해 작은 팀이나 간단한 프로젝트에는 과도할 수 있다.
2. Git Flow의 개념을 이해하고 적용하는 데 시간이 필요다.


+여담, 또 다른 대표 브랜치 전략

GitHub Flow는 Git Flow보다 훨씬 단순하며, 빠른 배포와 지속적인 통합(CI/CD)에 초점을 맞춘 브랜치 전략이다. 이 전략은 'master' 브랜치 하나와 기능별 'feature' 브랜치를 사용하는 것이 전부다. 왜냐하면 GitHub Flow는 코드 변경 사항을 빠르게 배포하고, 팀원 간의 협업을 간소화하기 위해 설계되었기 때문

특빠른 반복 개발과 배포가 필요한 스타트업이나 소규모 팀에 적합하고, 간단한 구조 덕분에 새로운 팀원도 빠르게 적응할 수 있으며, 배포 과정의 단순화로 인해 개발에 더 집중할 수 있다.

'코린이 개념잡기 > GIT' 카테고리의 다른 글

Git branch merge 방법  (0) 2024.12.13
HEAD와 branch의 관계  (0) 2024.12.09
branch  (0) 2024.12.09
커밋 다루기  (0) 2024.12.08
커밋 메시지 작성하기  (1) 2024.12.08

브랜치(branch)란 무엇인가?

프로그램 소스 버전을 관리하기 위한 개념으로, 간단히 말하면 복사본이다. "Branch"라는 이름 그대로, 원본에서 가지치기해서 복사한 소스를 가지고 별도의 버전을 새로 생성하는 것.

그렇다면 머지(merge)는 뭐지?

현재 branch를 다른 branch와 병합하는 과정.

단어 뜻 자체가 병합!

머지(merge)하는 방법

Fast-Forward merge

git merge 명령어를 사용해 브랜치를 병합할 때, 현재 브랜치가 병합할 브랜치의 직계 조상일 경우에 사용하고, 커밋 히스토리가 직선 형태로 유지되는 특징이 있다.

$ git checkout main
$ git merge feature

예를 들어, main branch에서 feature branch를 병합할 때 feature branch에서 새로운 커밋이 추가되지 않았다면 단순히 포인터를 이동한다.

✅장점

  • 히스토리가 깔끔하고 이해하기 쉽다.
  • 커밋 기록이 단순해서 추적이 용이하다.

⛔단점

  • 여러 개발자가 동시에 작업하면서 머지(merge, 병합)을 자주할 경우 히스토리가 단조로워질 수 있다.

Three-Way Merge

두 브랜치가 서로 다른 커밋을 가진 경우, git은 세 개의 커밋을 비교하여 병합한다. (공통 조상, 현재 브랜치의 최신 커밋, 병합할 브래치의 최신커밋)

기본적으로 git이 자동으로 충돌을 해결하고, 충돌이 발생할 경우 수동으로 해결해야 한다는 특징이 있다.

✅장점

  • 두 브랜치의 변경사항을 모두 반영할 수 있어, 기능이나 버그 수정이 잘 통합된다.
  • 여러 개발자들이 작업한 내용을 쉽게 병합할 수 있다.

⛔단점

  • 충돌이 발생할 경우, 수동으로 해결해야 하므로 추가적인 작업이 필요하다.
  • 히스토리가 복잡해질 수 있다.

Squash Merge

여러 커밋을 하나의 커밋으로 합치는 방식, 주로 기능 개발이 완료된 후, 커밋 기록을 정리하고 싶을 때 사용한다.

$ git checkout main
$ git merge --squash feature
$ git commit -m "Feature implemented"

feature 브랜치의 모든 커밋이 하나의 커밋으로 압축되어 main 브랜치에 추가된다.

✅장점

  • 히스토리가 깔끔하게 유지되고 기능단위로 커밋을 정리 할 수 있다.
  • 필요없는 중간 커밋 제거 가능, 프로젝트 이력이 더 명확해진다.

⛔단점

  • 원래의 커밋 히스토리를 잃게 되어 문제가 발생했을 때 원인을 추적하기 어려울 수 있다.
  • 협업시 각 개발자의 작업 내용을 상세히 기록하지 않기 때문에 나중에 코드 리뷰가 어려워질 수 있다.

Rebase Merge

한 브랜치의 커밋을 다른 브랜치의 끝으로 이동시키는 과정이다. 주로 기능 브랜치를 메인 브랜치의 최신 상태로 업데이트할 때 사용한다.

$ git checkout feature
$ git rebase main

feature 브랜치의 커밋이 main 브랜치의 최신 커밋 뒤로 이동한다. 이 과정에서 충돌이 발생할 수 있으며, 충돌을 해결한 후 진행해야 한다.

✅장점

  • 커밋 이력이 선형으로 유지, 이력 추적에 용이하다.
  • 협업시 최신 변경 사항을 쉽게 반영할 수 있다.

⛔단점

  • 이미 원격에 푸시된 커밋을 리베이스 할 경우 다른 개발자와 충돌이 발생될 수 있다. 원격에 푸시하기 전 주의!
  • 복잡한 커밋 히스토리를 가진 경우에는 충돌 해결이 번거로울 수 있다.

‼️결론

상황에 따라 적절한 방법을 이용해 사용하면 될 듯 하다.

Fast-Forward Merge는 간단한 경우에 유용하고, Three-Way Merge는 복잡한 상황에서 강하며, Squash Merge는 히스토리를 정리하고 싶을 때 유용하고, Rebase는 커밋 이력을 선형으로 유지하며 최신 변경 사항을 반영할 때 사용한다.

'코린이 개념잡기 > GIT' 카테고리의 다른 글

Git Flow 브랜치 전략  (0) 2024.12.13
HEAD와 branch의 관계  (0) 2024.12.09
branch  (0) 2024.12.09
커밋 다루기  (0) 2024.12.08
커밋 메시지 작성하기  (1) 2024.12.08

1. window 객체

window 객체는 브라우저 창을 대변하면서 자바스크립트에서 최상단에 존재하는 객체이다.
자바스크립트 코드 어느 곳에서나 항상 접근할 수 있는 객체이기 때문에 전역 객체, Global Object라고 부르고,
어떤 프로퍼티나 메소드를 사용하든 결국 전역 객체 내부의 것이기 때문에 앞에 window.을 생략할 수도 있다.

window.console.log(window);
window.console.log(window.innerWidth);
window.console.log(window.innerHeight);

2. DOM (Document Object Model, 문서 객체 모델)

간단하게 표현하면 웹 페이지(웹 문서)에 나타나는 HTML 문서 전체를 객체로 표현한 것으로 생각하면 되는데, 이때 각 객체를 노드(Node)라는 용어로 표현하고, 태그는 요소 노드, 문자는 텍스트 노드로 구분된다.

console.log(document);

출력되는 화면, DOM을 직접적으로 접근하게 되면 객체가 아니라 DOM에 해당하는 HTML이 출력된다.

자바스크립트에서 사용해봤던 document 객체가 이 웹 문서의 최상단 객체로 진입점의 역할을 한다.
그래서 document 객체를 활용하면 웹 페이지 내부에 무엇이든 수정할 수 있고, 새로운 콘텐츠를 만들 수도 있다.

3. DOM 트리

DOM 트리

HTML의 계층 구조는 DOM에서도 반영되는데 이러한 계층구조를 나무에 비유해서 DOM 트리라고 부른다.
각 노드 간의 관계는 부모, 자식, 형제라는 용어로 표현한다. DOM 트리의 구조를 잘 파악하고 필요한 노드에 좀 더 자유롭게 접근하기 위해서는 관계(부모, 자식, 형제)를 잘 이해하는것이 중요하다.

태그를 표현하는 노드를 요소 노드(Element Node)라고 부르고, 문자를 표현하는 노드를 텍스트 노트(Text Node)라고 부른다. 일반적으로 텍스트 노드들은 요소 노드의 자식 노드가 되고, 따로 자식 노드를 가질 수 없기 때문에 나무의 잎사귀에 비유해서 잎 노드(Leaf Node)라고 한다. 

4. DOM 이동 시 활용 가능한 프로퍼티

프로퍼티 유형 결과
element.children 자식 요소 노드 element의 자식 요소 모음(HTMLCollection)
element.firstElementChild 자식 요소 노드 element의 첫 번째 자식 요소 하나
element.lastElementChild 자식 요소 노드 element의 마지막 자식 요소 하나
element.parentElement 부모 요소 노드 element의 부모 요소 하나
element.previousElementSibling 형제 요소 노드 element의 이전(previous) 혹은 좌측(left)에 있는 요소 하나
element.nextElementSibling 형제 요소 노드 element의 다음(next) 혹은 우측(right)에 있는 요소 하나
node.childNodes 자식 노드 node의 자식 노드 모음(NodeList)
node.firstChild 자식 노드 node의 첫 번째 자식 노드 하나
node.lastChild 자식 노드 node의 마지막 자식 노드 하나
node.parentNode 부모 노드 node의 부모 요소 하나
node.previousSibling 형제 노드 node의 이전(previous) 혹은 좌측(left)에 있는 노드 하나
node.nextSibling 형제 노드 node의 다음(next) 혹은 우측(right)에 있는 노드 하나

요소 노드에 대한 이동 프로퍼티  /  모든 노드에 대한 이동 프로퍼티

<body>
  <div id="content">
    <h2 id="title-1">Cat-1</h2>
    <ul id="list-1">
      <li></li>
      <li></li>
      <li></li>
    </ul>
    <h2 id="title-2">Cat-2</h2>
    <ul id="list-2">
      <li></li>
      <li></li>
      <li></li>
      <li></li>
    </ul>
  </div>
  <script src="index.js"></script>
</body>
//DOM 트리 여행하기
const myTag = document.querySelector('#content');

console.log(myTag);

//자식 요소 노드
console.log(myTag.children); 
console.log(myTag.children[1]);  //자식 요소 노드의 1번째 인덱스에 오는 요소. list-1
console.log(myTag.firstElementChild);  //첫번째 자식 요소. title-1
console.log(myTag.lastElementChild);  //마지막 자식 요소. list-2

//부모 요소 노드
console.log(myTag.parentElement); //body태그가 선택된다.

//형제 요소 노드
console.log(myTag.previousElementSibling); //이전, 좌측에 있는 형제. null
console.log(myTag.nextElementSibling); //다음, 우측에 있는 형제. script

5. 주요 요소 노드 프로퍼티

프로퍼티 내용 참고사항
element.innerHTML 요소 노드 내부의 HTML코드 문자열로 리턴
(줄바꿈이나 들여쓰기, 띄어쓰기도 모두 포함)
요소 안의 정보를 확인할 수도 있지만, 내부의 HTML 자체를 수정할 때 좀 더 자주 활용
element.outerHTML 요소 노드 자체의 전체적인 HTML 코드를 문자열로 리턴 (해당요소 포함)
(줄바꿈이나 들여쓰기, 띄어쓰기도 모두 포함)
outerHTML은 새로운 값을 할당하면 요소 자체가 교체되어 버리기 때문에 주의 (수정X 처음 선택한 요소는 사라진다.)
element.textContent 요소 노드 내부의 내용들 중에서 HTML을 제외하고 텍스트만 리턴 textContent는 말그대로 텍스트만 다루기 때문에 HTML태그를 쓰더라도 모두 텍스트로 처리됨
<body>
  <div id="content">
    <h2 id="title-1">Cat-1</h2>
    <ul id="list-1">
      <li>wonderful</li>
      <li>beautiful</li>
      <li>great</li>
    </ul>
    <h2 id="title-2">Cat-2</h2>
    <ul id="list-2">
      <li>dog</li>
      <li>cat</li>
      <li>monkey</li>
      <li>pig</li>
    </ul>
  </div>
  <script src="index.js"></script>
</body>
//요소 노드 주요 프로퍼티
const myTag = document.querySelector('#list-1');

//innerHTML
console.log(myTag.innerHTML);
myTag.innerHTML = '<li>Exotic</li>';
myTag.innerHTML += '<li>Exotic</li>'; //덧셈 할당 연산자를 통해 기존 HTML 마지막 부분에 추가할 수도 있다.

//outerHTML
console.log(myTag.outerHTML);
myTag.outerHTML = '<ul id="new-list"><li>Exotic</li></ul>';
//수정이 아닌 교체. 처음 선택한 요소는 사라지고 새로 HTML을 만드는 것이다.

//textContext
console.log(myTag.textContext);
myTag.textContext = 'new text!';
//새로운 값을 할당하면 innerHTML과 마찬가지로 내부의 값을 완전히 새로운 값으로 교체

innerHTML 수정 전(좌)과 수정 후(우)

6. 요소 노드 다루기

1. 요소 노드 만들기: document.createElement('태그이름')
2. 요소 노드 꾸미기: element.textContent, element.innerHTML, ...
3. 요소 노드 추가 혹은 이동하기: element.prepend, element.append, element.after, element.before
4. 요소 노드 삭제하기: element.remove()

<body>
  <div>
    <h1>오늘 할 일</h1>
	<ol id="today">
	  <li>자바스크립트 공부</li>
	  <li>고양이 화장실 청소</li>
	  <li>고양이 장난감 쇼핑</li>
	</ol>
	<h1>내일 할 일</h1>
	<ol id="tomorrow">
	  <li>자바스크립트 공부</li>
	  <li>뮤지컬 공연 예매</li>
	  <li>유튜브 시청</li>
	</ol>
  </div>
  <script src="index.js"></script>
</body>
// 요소 노드 추가하기
const tomorrow = document.querySelector('#tomorrow');

// 1. 요소 노드 만들기: document.createElement('태그이름')
const first = document.createElement('li');

// 2. 요소 노드 꾸미기: textContent, innerHTML, ...
first.textContent = '처음';

// 3. 요소 노드 추가하기: NODE.prepend, append, after, before
tomorrow.prepend(first);

const last = document.createElement('li');
last.textContent = '마지막';
tomorrow.append(last);

const last = document.createElement('p');
prev.textContent = '이전';
tomorrow.before('문자열');

const last = document.createElement('p');
next.textContent = '다음';
tomorrow.after(next);
// 노드 삭제와 이동
const today = document.querySelector('#today');
const tomorrow = document.querySelector('#tomorrow');

// 노드 삭제하기: Node.remove()
tomorrow.remove();
today.children[2].remove();

// 노드 이동하기: prepend, append, before, after
today.append(tomorrow.children[1]);
//today에 tomorrow의 1번째 인덱스 자식요소를 가져와줘 (today의 맨마지막에 추가된다.)
tomorrow.children[1].after(today.children[1]);
//tomorrow에 자식요소 1번째 인덱스 뒤에 today 자식요소 1번째 인덱스를 옮겨줘
tomorrow.children[2].before(today.children[1]);
//tomorrow의 자식요소 2번째 인덱스 앞에 today 자식요소 1번째 인덱스를 옮겨줘 
tomorrow.lastElementChild.before(today.children[1]);
//tomorrow의 마지막 자식 요소의 앞에 today 자식요소 1번째 인덱스 가져와줘

7. HTML 속성 다루기

대부분의 HTML 속성은 DOM 객체의 프로퍼티로 변환이 된다. 하지만, 표준 속성이 아닌 경우에는 프로퍼티로 변환이 안 되는데, 아래 메소드를 활용하면 표준이 아닌 HTML 속성들도 다룰 수 있다.

1. 속성에 접근하기: element.getAttribute('속성')
2. 속성 추가(수정)하기: element.setAttribute('속성', '값')
3. 속성 제거하기: element.removeAttribute('속성')

// HTML 속성 (HTML attribute)
const tomorrow = document.querySelector('#tomorrow');
const item = tomorrow.firstElementChild;
const link = item.firstElementChild;

// elem.getAttribute('속성'): 속성에 접근하기
console.log(tomorrow.getAttribute('href'));
console.log(item.getAttribute('class')); //getAttribute를 활용할 때는 class라는 문자열을 그대로 전달

// elem.setAttribute('속성', '값'): 속성 추가(수정)하기
tomorrow.setAttribute('class', 'list'); // 추가
link.setAttribute('href', 'https://www.codeit.kr'); // 수정

// elem.removeAttribute('속성'): 속성 제거하기
tomorrow.removeAttribute('href'); 
tomorrow.removeAttribute('class');

// id 속성
console.log(tomorrow);
console.log(tomorrow.id);

// class 속성
console.log(item);
console.log(item.className); //프로퍼티 이름으로 접근할때는 className이지만

// href 속성
console.log(link);
console.log(link.href);
console.log(tomorrow.href);

8. 스타일 다루기

자바스크립트로 태그의 스타일을 다루는 방법에는 크게 두 가지가 있다.

1. style 프로퍼티 활용하기: element.style.styleName = 'value';
2. class 변경을 통해 간접적으로 스타일 적용하기: element.className, element.classList

‼️style 프로퍼티를 통해서 css 속성을 다룰 때 여러 단어를 이어서 만든 속성은 카멜 표기법을 사용해야한다.

// 스타일 다루기
const today = document.querySelector('#today');
const tomorrow = document.querySelector('#tomorrow');

// style 프로퍼티
today.children[0].style.textDecoration = 'line-through';
today.children[0].style.backgroundColor = '#DDDDDD';
today.children[2].style.textDecoration = 'line-through';
today.children[2].style.backgroundColor = '#DDDDDD';

style 프로퍼티를 활용하면 태그에 직접적으로 적용되어 버리기 때문에 스타일 우선순위가 높아진다는 문제가 있다.
그래서 style 프로퍼티를 사용하는 것보다 태그의 클래스를 변경하는 방식이 조금 더 권장되는 방식이다.

css에 미리 스타일을 지정해두고,

.done {
  opacity: 0.5;
  text-decoration: line-through;
}
// elem.className
today.children[1].className = 'done';

className 프로퍼티에 새로운 값을 할당해서 코드를 실행해보면, done 클래스에 미리 작성해둔 스타일이 입혀지는 방식인 것이다. 다만 한가지 문제는 className 프로퍼티로 값을 변경하게 되면 클래스 속성 값 전체가 바뀌게 된다. 기존에 있던 class는 사라지고 새로 부여한 class만 남는다는 뜻!

하지만 상황에 따라서 기존에 class는 그대로 둔 채로 새로 추가 하고 싶을 수도 있을 것이다. 그럴 때는 classList를 사용하면 된다.

// elem.classList
console.log(today.classList);
console.log(today.children[1].classList);

// elem.classList: add, remove, toggle
const item = tomorrow.children[1];
item.classList.add('done'); //추가
item.classList.remove('done'); //삭제
item.classList.toggle('done'); //있으면 제거, 없으면 추가

//add와 remove는 여러개의 파라미터 값을 줄 수 있다.
item.classList.add('done', 'other');

//toggle은 여러개의 파라미터는 줄 수 없고, 두번 째 파라미터가 boolean형태의 값을 전달 받아서 
//true일 땐 add의 기능만, fales일 땐 remove의 기능만하도록 toggle의 기능을 강제하는 역할을 한다.
item.classList.toggle('done', false);

classList는 클래스의 속성 값을 유사배열로 다루는 프로퍼티이다. 클래스 속성을 하나씩 다룰 수 있는 것 뿐만 아니라 add, remove, toggle이라는 메소드도 활용할 수 있다.

위 코드의 classList 출력(consol.log)값

메소드 내용 참고사항
classList.add 클래스 추가하기 여러 개의 값을 전달하면 여러 클래스 추가 가능
classList.remove 클래스 삭제하기 여러 개의 값을 전달하면 여러 클래스 삭제 가능
classList.toggle 클래스 없으면 추가, 있으면 삭제하기 하나의 값만 적용 가능하고, 두 번째 파라미터로 추가 또는 삭제 기능을 강제할 수 있음

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

자바스크립트 이벤트  (0) 2024.12.14
console.log와 console.dir의 차이  (0) 2024.12.13
이벤트와 클릭  (0) 2024.12.13
태그 선택하기  (0) 2024.12.12
조건문  (0) 2024.01.20

이벤트 : 웹 페이지에서 발생하는 대부분의 일. ex)마우스를 움직이는 일, 클릭, 스크롤, 키보드 입력 등

<body>
  <div>
    <button id="myBtn">Click!</button>
  </div>
</body>
// 이벤트(Event)와 버튼 클릭
const btn = document.querySelector('#myBtn');

// 이벤트 핸들링(Event Handling)
btn.onclick = function() { // 이벤트 핸들러(Event Handler)
  console.log('Hello Codeit!');
};

해당 태그를 변수로 담고, onclick이라는 프로퍼티에 함수를 할당해주면 버튼에 대한 클릭이벤트에 원하는 동작을 할 수 있다.

이벤트 핸들링 : 이벤트가 발생했을 때 어떤 특별한 동작을 하도록 이벤트를 다루는 것

이벤트 핸들러 : 구체적인 동작들을 코드로 표현한 함수 부분

그리고 잘 사용하진 않지만 HTML에서 바로 이벤트 핸들러를 등록 할 수도 있다.

<body>
  <div>
    <button id="myBtn" onclick="console.log('Hello Codeit!')">Click!</button>
  </div>
</body>

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

console.log와 console.dir의 차이  (0) 2024.12.13
객체, 요소, 노드  (1) 2024.12.13
태그 선택하기  (0) 2024.12.12
조건문  (0) 2024.01.20
함수  (0) 2024.01.20

ID로 선택하기

//id로 태그 선택하기
document.getElementById('Id');

ID속성을 통해서 어떤 요소를 가져 오겠다는 뜻이다. id 값을 문자열로 전달해 주게 되면 해당되는 태그가 선택되는 원리이다.

const myTag = document.getElementById('myNumber');
console.log(myTag);

//출력되는 값, HTML에 적혀 있는 태그가 보인다.
<div id="myNumber">0</div>

뿐만 아니라 자식요소가 있는 부모요소를 선택하게 되면 부모태그 요소에 있는 모든 내용들이 표시 되고, 존재하지 않는 태그를 선택하게 되면 null값이 리턴된다.

장점 : 필요한 태그를 명확하게 선택할 수 있다.


Class로 선택하기

//class로 태그 선택하기
document.getElementsByClassName('class');

class는 id와는 다르게 여러 태그에 붙을 수 있어 Element"s"로 작성해야 하니 주의하자.

const myTags = document.getElementsByClassName('color-btn');
console.log(myTags);

출력된 화면

"color-btn" 클래스가 있는 모든 태그들이  대괄호로 감싸져 배열의 형태로 선택됐다. length 프로퍼티도 있어서 배열 같지만, 완벽한 배열은 아니다. 배열을 다룰 때 사용하는 splice나 push 같은 메소드는 사용할 수가 없기 때문에 배열이라고 부르기는 어렵다.

console.log(myTags[1]);
console.log(myTags.length);

for (let tag of myTags) {
  console.log(tag);
}

배열 메소드는 사용할 수 없지만 대괄호 표기법으로 1번 인덱스에 접근한다거나, length 프로퍼티를 활용할 수 있고, for...of 문을 사용하는데에는 아무런 문제가 없다.

+ 여러개의 값을 담고 있는 배열과 형태는 유사하지만 배열의 메소드는 사용할 수 없는 것들을 가리켜서 유사배열(Array-Like Object)이라고 한다.

그리고 클래스가 하나 밖에 없는 값에 접근하려고 하면, 태그가 하나 밖에 없으니 딱 그 태그가 선택될거라고 생각할 수 있다. 확인을 해보면 요소가 한개가 들어있는 HTMLCollection이 출력되기 때문에 그 태그를 선택하려면 [0] 번째 인덱스에 접근 해야 된다.

존재하지 않는 태그를 선택하게 되면 null값이 리턴되던 id 태그 선택과는 다르게 비어있는 HTMLCollection이 출력된다.

console.log(myTags === null); //false, 비어있는 HTMLCollection은 null값과는 다르다.
console.log(myTags.length); //0

+ 여담

유사배열의 특징

  1. 숫자 형태의 indexing이 가능하다. : 유사배열도 배열과 마찬가지로 각 요소에 0부터 시작하는 숫자 형태의 index가 있어야 한다.
  2. length 프로퍼티가 있다. : 숫자 형태의 index가 있더라도 length 프로퍼티가 없다면 유사배열이라기 보다 그냥 숫자 형태의 key로 구성된 일반적인 객체라고 볼 수 있다.
  3. 배열의 기본메소드를 사용할 수 없다. : 인덱싱을 통해 유사배열의 요소에 접근은 쉽지만 수정이나 삭제는 까다롭다. 그래서 내부 요소들은 배열처럼 다룰 수 있으면서 배열의 메소드 사용을 막고싶거나 일반 배열에는 없는 특별한 메소드를 제공하고 싶을 때 유사 배열을 활용한다.
  4. Array.isArray(유사배열)은 false다. : 유사 배열은 배열과 비슷하지만 배열이 아니기 때문에 결과값이 false이다.

태그 이름으로 선택하기

//태그 이름으로 태그 선택하기
document.getElementsByTagName('태그이름');

class와 마찬가지로 Element"s"로 작성해야 하니 주의! 실행결과 역시 class와 똑같이 HTMLCollection을 리턴한다.

const allTags = document.getElementsByTagName('*');

css선택자처럼 '*' 값을 전달하게 되면 모든 태그를 선택할 수도 있다. 하지만 명확한 의도 없이 많은 요소를 한꺼번에 다루면 예상치 못한 실수를 할 수 있으니 주의하자. 많이 사용되는 메소드는 아니다.


CSS 선택자로 선택하기

//css 선택자로 태그 선택하기
document.querySelector('css선택자');

ID 는 #, class는 .을 이용해서 작성할 수 있다.

const myTag = document.querySelector('#myNumber');
console.log(myTag);

const myTag2 = document.getElementById('myNumber');
console.log(myTag2);

위 코드는 같은 값을 출력한다. #과 getElementById는 ID 속성을 가진 태그를 가져온다.

const myTag = document.querySelector('.color-btn');
console.log(myTag);

출력된 화면

HTML Collection과 같은유사배열이 출력될 것 같았지만, color-btn 클래스가 붙어있는 태그들 중에 가장 첫번째 요소(0번째 인덱스)가 선택되었다. 만약 같은 class를 가진 태그 여러개를 가져오고 싶다면 querySelectorAll 메소드를 활용할 수 있다.

const myTags = document.querySelectorAll('.color-btn');
console.log(myTags);

const myTags2 = document.getElementsByClassName('color-btn');
console.log(myTags2);

출력되는 화면

document.querySelectorAll('.color-btn')는 NodeList가 출력됐고, getElementsByClassName('color-btn')는 HTML Collection이 출력됐다. 뭔가 이름은 조금 다르지만 안에 있는 요소는 동일하다.

+존재하지 않는 요소를 선택할 경우 querySelector는 (id 선택과 마찬가지로) null값을, querySelectorAll은 비어있는 NodeList를 리턴한다. 


 

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

객체, 요소, 노드  (1) 2024.12.13
이벤트와 클릭  (0) 2024.12.13
조건문  (0) 2024.01.20
함수  (0) 2024.01.20
예약어  (0) 2024.01.19

코딩하는데 4시간, 배포하는데 1시간 걸린 멍청이의 첫 배포 일지. 내가 보기 위해 내가 정리하는 내.보.내.정

git으로 배포하기 배우면서 알게된 점들을 주황글씨로 새겨볼까 한다.

먼저 레포지토리 포크를 해야한다.

포크를 할 때 이 내용은 꼭 체크해제 해줘야 한다.

포크한 레포지토리의 브랜치 목록에 내 이름이 있는지 확인을 꼭 한 후 진행해야한다.

하트 이모지가 붙은게 내 브랜치!

확인이 끝났으면 포크한 레포지토리에서 저장소 URL을 복사 후 브랜치 클론 작업을 해줘야한다.

내 이름으로 된 브랜치(basic-내이름)에서 초록색 code 부분을 눌러서 저장소 url을 복사해준다.
vscode에서 terminal 열기 (그냥 바탕화면에서 vs code를 실행한 후 terminal을 실행해주면 된다.)

clone : 온라인에 있는걸 통째로 내 컴퓨터로 가져온다. 저장소 url을 clone할 때 적는 이유 : 구체적으로 어떤 코드를 가져오는지 알기 위해서 URL을 적어 명명하는 것이다.

$ git clone -b Basic-본인이름 --single-branch {저장소 URL}
$ git clone -b Basic-이코딩 --single-branch https://github.com/12124334@!#@$#@!

그 다음 clone해 온 폴더를 열어줘야 한다.

open folder 선택
폴더 선택 후 선택 눌러서 열어준다!(위 사진은 예시이다. 클론해 온 폴더 열어줘라)

이게 무슨 말이냐면, 예를 들어 바탕화면에 폴더(디렉토리)를 만들고서 그 안에서 클론을 하면 폴더 안에 폴더가 생긴다. 안에 생긴 폴더에서 작업을 해주면 된다.

clone 해 온 브랜치에 새로운(나의) 브랜치 생성!

//예시
$ git checkout -b Basic-본인이름-sprint1

git checkout -b 새로운 브랜치로 만들면서 이동하기

클론 해 온 폴더를 열고 베이스 브랜치가 main이 아닌 본인 이름-sprint1인지 잘 확인하기!

+ 만약 다른 브랜치로 설정 되어 있으면 git checkout 명령어로 브랜치 이동해주기!

$ git checkout 이동할 브랜치명

이렇게 만든 브랜치 내에서 미션을 진행하면 된다!

그런 다음 내가 한 작업물 보내기 위한 작업을 진행한다.

$ git add .
$ git commit -m "메시지"
$ git push origin <브랜치명>

//예시
$ git push origin Basic-본인이름-sprint1

add 지정 / commit 저장 / origin 내 레포지토리 주소

여기까지 됐다면 Pull Request를 할 수 있다. pull request = 검토받기 위한 작업, 만약에 내가 신입개발자로 뽑혀서 들어가 중요 프로젝트에 투입됐는데 내가 만든 브랜치를 바로 머지 할 수 있는가? 아마 사수나 상사가 무조건 확인 후에 올릴것이다. 그래서 PR을 하는것이라고 생각하면 된다.

스티커 부분을 눌러서 PR 해주기!

PR제목은 [본인이름] sprintN로 꼭 통일하기! (ex. 미션 2번하는 홍길동이라면 => [홍길동] sprint2)

미션 1부터
-base repository: 코드잇 레파지토리/기수-Sprint-Mission / base: Basic-본인이름 (🚨반드시 main 브랜치가 아닌, Basic-본인이름 브랜치로 설정)
-head repository: 내 레파지토리/기수-Sprint-Mission / compare: Basic-본인이름-sprintN

미션 5부터
-base repository: 코드잇 레파지토리/기수-Sprint-Mission / base: React-본인이름 (🚨반드시 main 브랜치가 아닌, React-본인이름 브랜치로 설정)
-head repository: 내 레파지토리/기수-Sprint-Mission / compare: React-본인이름-sprintN

미션 9부터
-base repository: 코드잇 레파지토리/기수-Sprint-Mission / base: Next-본인이름(🚨 반드시 main 브랜치가 아닌, Next-본인이름 브랜치로 설정)
-head repository: 내 레파지토리/기수-Sprint-Mission / compare: Next-본인이름-sprintN

제목을 생성하면 PR 템플릿을 작성하도록 나온다.

## 요구사항

### 기본

- [x]
- []
- []

### 심화

- [x]
- []

## 주요 변경사항

-
-

## 스크린샷

![image](이미지url)

## 주강사님에게

-
-
- 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

💡 PR 템플릿을 활용하실  때 주의할 것
-PR 템플릿은 마크다운 문법을 준수해서 작성하기
-체크리스트를 만들고 싶다면 [ ], 체크를 하고싶다면 [x]와 같이 작성해 주기
-스프린트 미션이 안내된 레슨의 셀프 채점 부분에 있는 체크리스트를 PR에도 반영하기
-PR에서 큰 변경사항이 있을 때에는 '주요 변경사항'에 기록하기(e.g. 랜딩 페이지 추가, 로그인/회원가입 페이지 반응형 디자인 적용 등)
-주강사님이 작업한 내용을 빠르게 이해할 수 있도록 png, jpg, gif 등의 이미지를 '스크린샷'에 첨부하기. 참고로, 이미지 첨부를 위한 마크다운 문법은 ![대체 텍스트](이미지 URL)
-코드의 특정 영역에 대해 질문이 있을 때는 PR에 코멘트를 작성하는 방식으로 진행하기

나는 이때 [기본]에다가 netlify로 배포한 사이트 주소를 넣었다. (나중에 강사님이 맞게 잘 하셨다면서 확인해주심.)

본문을 다 작성했다면 평일 강사님을 Reviewers에 추가해주고 (k로 시작하심) Label로 원하는 피드백 스타일을 표시한다.

label

 

이렇게 까지 했다면 아직 끝난게 아니라 미션 설문을 제출 + 디스코드에서 강사님께 미션완료 코드리뷰 요청을 드려야한다.

 

+이후 강사님께서 제출된 PR의 내용을 확인 후 리뷰를 남기고 머지(Merge)해 주신다.

+PR은 강사님 리뷰 후에 머지 되기 때문에 리뷰에 대한 개선작업은 그 다음 스프린트 미션에 반영해주면 된다.


그 다음 프로젝트 진행하기

본인 프로젝트 열고, Basic-본인이름-sprint 브랜치에서 Basic-본인이름 브랜치로 이동을 해준다.

$ git checkout Basic-본인이름

그 다음 github 레포지토리의 Basic-본인이름 브랜치에서 변경된 코드를 가져온다.

//github 레포지토리를 upstream 이라는 이름으로 연결한다.
//git remote add로 연결한 후에는 추후에 다시 연결하지 않아도 된다.
$ git remote add upstream 저장소-url

//github 레포지토리의 Basic-본인이름 브랜치에서 변경된 사항을 내 Basic-본인이름 브랜치로 가져온다.
$ git pull upstream Basic-본인이름

여기서 $ git remote add upstream 저장소-url 은 

이 때 봤던 Basic-내 이름 말고 main 에서의 주소이다. 왜냐! 위에서 clone해 올 때는 basic-내이름 에서 주소를 가져왔다. $ git push origin Basic-본인이름-sprint1 에서 origin은 내 레포지토리의 주소이다. 그럼 가져올 저장소의 위치도 알려줘야 한다. 그래서 내가 가져오려는 github 레포지토리를 upstream이라는 이름으로 연결해주는 것이다. (매번 주소 다 치기 번거로우니까!)

그리고 다음 미션을 위한 새 브랜치를 생성한다.

$ git checkout -b Basic-본인이름-sprint2

Basic-본인이름-sprint2 브랜치에서 미션을 완수한다.

$ git add .
$ git commit -m "메시지"
$ git push origin <브랜치명>

//예시
$ git push origin Basic-본인이름-sprint2

 
 
 
 

HEAD : 어떤 커밋 하나를 가리킴

branch : 하나의 코드 관리 흐름

사실 branch도 HEAD처럼 어떤 커밋 하나를 가리키는 존재이다. (이것을 포인터라고 부른다.)

git에서 커밋은 이전 커밋에 대한 정보를 가지고 있다.

그래서 master(혹은 main) 포인터가 가장 최신의 커밋만 가리키고 있다고 해도 그 이전 커밋으로 하나씩 거슬러 올라갈 수 있기 때문에 어떻게 프로젝트가 변해왔는지 추적할 수 있다.

그래서 branch가 어떤 코드의 관리 흐름이라는 개념이 성립되는 것이다.

HEAD 역시 어떤 커밋을 가리키는 존재로 포인터이다.  HEAD가 가리키는 커밋의 내용대로 워킹 디렉토리의 내용물이 바뀐다. 하지만 정확하게 말하자면 HEAD는 커밋을 직접적으로 가리키지 않는다. HEAD는 branch를 가리킬 뿐이다.

프리미엄이라는 브랜치를 새로 만들고 git checkout premium으로 HEAD를 premium으로 맞춰줬다. 이 상태에서 다른 커밋을 만들면

HEAD가 가리키던 프리미엄 브랜치가 새로운 커밋을 가리킨다. 이 상태에서 마스터 브랜치로 체크아웃하면 HEAD는 다시 master로 이동한다.

그럼 HEAD 입장에선 다섯번째 커밋을 가리키는것이고 다섯번째 커밋의 내용대로 워킹 디렉토리 내용도 변하게 된다.

위 상태에서 또 새로운 커밋을 만들면 커밋 히스토리의 흐름이 갈라진다 (분기한다)

이렇게 쭉 커밋을 하다가 프리미엄 브랜치와 마스터 브랜치를 머지하게 되면 새로운 커밋을 만들어주는데 이 때 커밋을 머지 커밋이라고 한다.

머지의 뜻

 

'코린이 개념잡기 > GIT' 카테고리의 다른 글

Git Flow 브랜치 전략  (0) 2024.12.13
Git branch merge 방법  (0) 2024.12.13
branch  (0) 2024.12.09
커밋 다루기  (0) 2024.12.08
커밋 메시지 작성하기  (1) 2024.12.08

+ Recent posts