16-20일차 스터디 정리본
어차피 이번 주에 주로 공부한 git에 대해서는, 개별적인 포스팅으로 남겼기 때문에....
배우고 정리한 개념들 위주로만 주제별로 묶어 남긴다.
Javascript로 DOM 다루기
💎Create 생성
document.createElement('div') //createElement를 통해 생성한다.
아래와 같이 작업의 결과를 변수에 담아주는 식으로 자주 사용한다.
const tweetDiv = document.createElement('div');
//이렇게 변수에 담아주기도 가능.
💎Append 추가
부모 노드에 포함 시키는 것을 말한다.
document.body.append(tweetDiv) //append를 사용해서 body에 넣어준다는 의미.
💎Read 읽어오기, 조회하기
querySelector를 써서 DOM을 확인할 수 있다. html, id, class 세 가지 모두 가능하다. 아래처럼 querySelector에 '.tweet' 을 첫 번째 인자로 넣으면, 클래스 이름이 tweet인 HTML 엘리먼트 중에서도 첫 번째 엘리먼트를 조회 가능하다.
const oneTweet = document.querySelector('.tweet')
여러 개의 요소를 한 번에 가져오기 위해서는 querySelectorAll을 사용하면 된다. 이런 방식으로 조회한 HTML요소들은 배열처럼 for문을 사용하여 다룰 수 있다.(그러나 진짜 배열은 아니고, 유사배열객체)
const container = document.querySelector('#container')
//HTML에서 아이디 container을 가지는 컨테이너를 불러온 뒤, container 변수에 담았다.
const tweetDiv = document.createElement('div')
//tweetDiv라는 변수에 div태그를 새로 생성해 넣었다.
container.append(tweetDiv)
//불러온 HTML 컨테이너 내부에 생성한 tweetDiv를 밀어넣었다.
💎Delete 삭제하기
remove는 하나만 삭제된다. 여러 개를 지우려면 innerHTML을 쓸 수 있지만, 이 메소드는 '보안에 몇 가지 문제를 가진다.'... 악성 해킹 위험이 있다는 뜻이다.
따라서 다른 메서드를 사용하는 편이 낫다. removeChild로 자식 요소를 지정하여 삭제가 가능하다.
const container = document.querySelector('#container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
아래처럼 tweet이 클래스 이름인 요소만 골라서 삭제할 수도 있다.
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
// or
for (let tweet of tweets){
tweet.remove()
}
해당 엘리먼트를 querySelector 등을 이용해 가져온 후 value라는 속성으로 접근할 수 있습니다. 예를 들어, <input type="text" id="username">의 값을 가져오려면, 다음과 같이 접근합니다.
console.log(document.querySelector('#username').value);
값을 설정할 수도 있습니다.
document.querySelector('#username').value = '새로운 값';
텍스트 추가하거나 값을 가져오는 방법 'textContent'. innerText와의 차이?
innerHTML, innerText, textContent 속성은 node나 element의 텍스트값을 읽어오고 설정할 수 있다는 점에서 비슷합니다.
innerText는 이처럼 사용자에게 보여지는 텍스트를 가져옵니다. 사용자가 브라우저에서 div의 내용을 Ctrl+C하여 클립보드에 복사한 내용을 가져온다고 생각하면 이해하기 쉽습니다.
보안 위험은 innerHTML 속성을 통해 유해한 코드라도 HTML 코드의 모든 부분을 삽입할 수 있기 때문에 발생합니다. 다음 섹션에서 이 부분에 대해 논의할 것입니다. MDN은 요소의 텍스트를 변경하기 위해 node.textContent를 사용할 것을 권장합니다. HTML 내부의 자식 노드를 textContent 매개변수에 할당한 text로 바꿉니다.
element.innerHTML -> 보안 문제로 지양
element 안의 HTML, XML을 읽습니다.
element.innerText
element 안의 텍스트를 사용자에게 "보여지는 대로" 읽습니다.
node.textContent
node 안의 텍스트를 (<script>, <style>에 상관없이) 읽습니다.
https://choonse.com/2022/02/13/924/
input과 같은 form 요소의 값을 가져오고 싶을 때는 .value 를 사용한다. 그 외 div 나 span 등의 요소 안에 있는 text를 읽고 싶을 때는 .textContent 의 메소드를 쓴다고 한다.
textContent로 불러온 걸 변환 가능.
.setAttribute()
선택한 요소(element)의 속성(attribute) 값을 정합니다.
let aElement = document.createElement('a')
aElement.setAttribute('id', 'javascript')
id= "javascript"인 <a>태그 생성
💎찾아오기
getElementById: id로 DOM에서 요소를 선택하는 데 사용된다. document.getElementById("sel");와 같이 아이디가 sel이라면 이미 아이디를 찾아오고 있는 것이기에 앞에 #을 붙이지 않는다(이게 또 querySelector과 은근히 헷갈리는 개념이기에 잘 알아두길 권한다.) 과거에 자주 사용되었고 요새는 querySelector을 많이 쓰는 중.
getElementsByClassName: 클래스명을 기반으로 선택한다. 이 메소드는 둘 이상의 요소를 HTML 객체의 '배열'로 반환해준다. 이 역시 굳이 .을 붙이지 않아도 찾아올 수 있다.
getElementsByName: name속성이 있는 요소를 선택한다. HTML 노드 이름 속성을 지정. 이 메서드는 HTML 객체의 배열을 반환하는데 특히 특정 스타일, CSS 클래스를 가진 여러 요소를 선택하고 한번에 모든 요소에 적용하려 할 경우 사용된다.
getElementsByTagName: HTML 태그를 기반으로 요소를 선택한다. 가령 DOM에 있는 모든 div 요소에 대해서만 일부 작업을 수행할 수 있다. 이름에서 알 수 있듯이 HTML 객체의 배열을 반환한다.
querySelector: querySelector 기능은 좀 더 일반적으로 선택하는 데에 사용한다. 매개변수에 전달된 조건을 충족하는 첫 번째 요소를 반환하는 특징이 있다. 요즘 많이 쓰는 추세이며 아이디라면 #, 클래스라면 .을 붙여줘야 한다.
querySelectorAll: 기능이야 querySelector와 유사하지만, 위와 달리 단 한개가 아닌 여럿을 전부 찾아준다.
https://hianna.tistory.com/485
1. getElementById()
2. getElementsByClassName()
3. getElementByTagName()
4. querySelector()
5. querySelectorAll()
html을 삽입할 때
innerHTML -> 보안상 문제로 지양하는 편.
innerText -> 텍스트 내용만 삽입 가능
node.textContent
함수의 HTML요소를 삭제할 때 remove()
removeChild() 자식 요소 중에서 일치하는 아이디 값을 찾아 해당하는 요소를 삭제
- remove() 와 removeChild()
remove() 는 노드를 메모리에서 삭제하고 종료합니다. 반면 removeChild()는 노드를 삭제하는 것이 아닙니다. 메모리에 해당 노드는 그대로 존재하며, 부모 노드와의 부모-자식관계를 끊어 DOM 트리에서 해제하는 것입니다. 최종적으로는 관계를 끊은 해당 노드의 참조를 반환합니다.
반환값을 변수에 저장하지 않으면 삭제하는 노드의 참조가 더이상 없기 때문에, 자바스크립트 엔진의 GC(Garbage Collection)에 의해 잠시 후 메모리에서 삭제됩니다.
반환된 노드 참조를 변수에 담아 다른 DOM 위치에 붙일 수 있습니다.
각 브라우저마다 JS를 다르게 쓰다보니, 개발자들이 다 도망가서 만든 규칙이 ECMA Script (ES5, ES6)
ECMA Script + Dom+ Bom(브라우저 객체)
https://engineer-mole.tistory.com/151
[JavaScript] Object.assign에 대한 이해
Object.assign을 이용해서 객체를 합치는 것이 가능하다. 또한 합칠 때는 2개의 객체가 같은 프로퍼티를 가지고 있다면 그 값을 덮어쓰기 해주며, 객체의 복제에서도 사용될 수 있다. Object.assign는 폼
engineer-mole.tistory.com
Git vs Github ?
Git 은 2005년 Linus Torvalds에 의해 발표되었으며 개발자들이 소스를 효율적으로 관리하도록 편의를 제공하는 일종의 시스템이다. 깃은 개발자들에게 버전 관리(문서를 저장하고 수정 기록을 기록함), 백업, 협업을 도와주었다. 깃허브 Desktop, TortoiseGit, SourceTree 등을 사용하여 깃을 쓸 수 있으며, 터미널을 통한 CLI환경에서도 깃에 접근할 수 있다. 대부분 CLI를 자주 사용한다.
여기서 등장하는 두 개념이 있다. 바로 로컬 레파지토리와 원격 레파지토리다. 로컬 레파지토리(저장소)는 자신의 컴퓨터에 파일을 저장하는 공간을 말한다. 반면 원격 레파지토리는 다른 사람들이 접근하기 쉽도록 자신의 컴퓨터가 아니라 다른 서버에 만든 저장소이다. 이것을 로컬 레파지토리와 연결하여 파일을 관리한다.
GitHub은 바로 이 원격 레파지토리의 한 종류로 원활한 깃 사용을 위한 원격 저장소라고 할 수 있겠다. 타인의 저장소에 접근해서 오픈 소스를 활용하거나, 각종 협업, 버전관리, 백업을 할 수 있으며 그간 commit 기록을 한눈에 보도록 할 수 있기에 몹시 유용하다.
HTTPS vs SSH key?
SSH는 Secure Shell로, 비밀 키(private)와 공개(public)키라는 한 쌍을 생성해서 컴퓨터를 인증하는 식의 '보안 강화' 방식으로 정보를 교환한다. 사용자가 컴퓨터에서 SSH키를 생성할 시 위와 같이 두 개의 키를 만들 수 있다. 이 중 공개 키를 Github에 서버에 저장한 뒤, 저장을 마치면 이후에는 로그인을 매번 하지 않아도 바로 깃허브 저장소에 접근할 수 있다. 컴퓨터의 비밀 키와 github에 저장된 공개 키를 비교하여 일치할 시 연결되는 방식이다. 사용자 프로필에 추가할 수 있는 키의 수에는 제한이 없다.
또한 Azure DevOps에 저장된 SSH 키는 5년 후에 만료되는데, 이후 새 키 또는 동일한 키를 업로드하여 계속 사용할 수 있다. HTTPS 주소 방식으로 clone 할 시에는 push, pull할 때마다 매번 이름과 비밀번호를 입력하라는 창이 뜬다. 그러니 SSH로 인증이 되어 있다면 SSH주소를 사용하여 clone 하는 것이 더 간편하다.
만약 생성한 레파지토리가 public이 아닌 프라이빗(private)일 시엔 어떻게 할까?
먼저 clone 전에 settings -> collaborators -> add people를 눌러 함께 참여할 협업자를 추가해주어야 한다. 프라이빗 저장소는 권한 있는 사람만 접근 가능하기 때문이다. 이때 추가 완료된 된 협업자는 프라이빗 저장소라도 push, pull, commit가 가능하다. SSH주소로 clone하는 경우, SSH키를 등록한 뒤에 사용하면 쉽게 사용이 가능하다.
하지만 간혹 회사 보안차 SSH주소가 아닌 HTTPS만 사용 가능한 경우가 있다. 이럴 때에는 PAT(personal access token)을 사용하는 방법이 있다. 토큰은 깃 패스워드를 대체하여 인증할 수 있는 수단으로, 여러 개 생성이 가능하지만 보안 때문에 1년동안 사용 되지 않으면 곧바로 폐기된다.
github 내에서 Settings -> Developer Settings -> Personal access tockens로 생성이 가능하다.
브랜치?
브랜치란, 여러 사람이 작업하던 코드를 main 브랜치에 한번에 올려버리면 원본 파일이 심하게 훼손될 수 있어서 각 팀원에게 각각 공간을 생성해 주는 개념이다. 브랜치 생성은 git checkout -b "이름" 을 통해 가능하다. 초기 설정할 때 main branch를 먼저 세팅해주고, 첫 레파지토리를 만들 때 read.md 파일을 함께 넣으면 자동으로 main branch가 생성된다. 이후 git checkout "branch명"을 통해 브랜치 전환이 가능하다.
fork 떠서 클론하면 상관 없지만 그게 아닐 시에는 레파지토리를 만든 사람에게 초대 메일을 요청해야 한다. git push origin "브랜치 이름" 을 통해 push가 가능하다. 이후 Pull Request를 하여 merge 전에 먼저 확인을 받는다.
웬만하면 merge는 한 사람이 담당하는 것이 좋다.
모달 vs 팝업vs페이지 이동
💎팝업
갑자기 툭! 생성되는 새 창을 말한다.(브라우저 윈도우 팝업, alert 시스템 팝업, 레이어 팝업)
- 브라우저 윈도우 팝업 : 기존 브라우저와 별개로 작은 브라우저 창을 띄운다. 메모리와 트래픽 증가를 유발한다. 과거 팝업은 원치 않는 광고의 대명사로 불리웠기에 사용자에게 부정적인 이미지가 강하고, 또 현재는 브라우저들이 제공하는 팝업 차단 기능들 때문에 잘 사용하지 않는다.(모달로 교체 되었음!) 다만 SNS로그인, 카드 결제, 파일 업로드, 공지 등에는 아직도 종종 사용.
- 시스템 팝업 : 사용하는 브라우저에 따른 기본 디자인을 사용한 아주 기본적인 팝업으로, 사용자 행위에 대한 일방적 경고나 확인 용도로 쓰인다. (alert창: 확인 용도, confirm창: 취소와 확인이 둘다 가능) 최근에는 기본 앱 실행 시 필요한 위치 허용, 사진 접근 권한 허용, 통화 기록 권한 등에 쓰이고 있다. 이처럼 상호작용 용도는 거의 없으며 일방적인 알림이다.
- 레이어 팝업 : 모달과 유사. 기존 브라우저 위에 레이어 형태로 겹쳐지는 팝업! 부모 창(브라우저)와 상호 작용이 가능한 것이 특징이다. 지금은 모달과 크게 구분하지 않는다.
💎모달
기존 브라우저 페이지 위에 자식 창 레이어를 까는 방식이다. 나타난 자식 창을 닫기 전까지, 부모 창과는 상호작용이 불가하도록 한다(모달리스는 가능). 부모 창을 닫는 순간 모달도 같이 사라진다. 부모 창의 동작 여부에 따라 모달/모달리스로 구분!
실행한 채 부모창이 스크롤 가능하면 모달리스, 불가하면 모달로 불린다.
서비스 사용 중 독립적인 프로세스가 필요할 때 주로 사용된다.

(유튜브의 모달. 저 상태로도 부모 브라우저에서 스크롤이 가능하기 때문에 모달리스에 속한다.)
하지만, Apple UI에서는 주의를 끌어야 하는 중요한 순간 외에는 모달 사용을 지양하도록 설명하고 있다. 대다수의 사용자들은 자신의 흐름이 갑자기 툭 튀어나오는 모달이나 경고창 따위로 방해 받기를 원하지 않기 때문.
💎페이지 이동
한 페이지 내 다른 페이지 url로 이동하는 방식이다. 한번에 페이지 전체가 바뀌는 전환으로, 다른 모달이나 팝업보다 강제성이 높은 편이다. 따라서 아주 중요도가 높은 페이지에만 사용되어야 한다. (ex 계약서 작성, 반드시 읽어봐야 하는 라이센스 등)
참고 자료: https://brunch.co.kr/@bcc5736f7b26444/1
변수의 유효범위와 클로저
https://ko.javascript.info/closure
렉시컬 환경 등에 다루는 깊이 있는 글인데, 나중에 진지하게 읽어볼 것. ...
이번 주 단어
Azure DevOps 데브옵스(Development + Operation) : Microsoct사에서 운영. 클라우드 플랫폼에서 애플리케이션을 구축, 배포 및 릴리스하기 위한 수많은 기능을 갖춘 완전한 소프트웨어 개발 프로젝트 서비스.
Shell 쉘 : CLI로 구현된 프로그램, 인간이 입력하는 명령어들을 컴퓨터가 이해할 수 있게 해석해주는 해석기 역할을 한다. 쉘을 통해 명령어를 입력하면 쉘에 의해 해석되어 kernal로 전달, 커널에서 각 명령을 실행한다. 터미널 위에서 쉘이 실행되는 것(터미널을 킴과 동시에 실행된다.).
새로 배운 TIP
- DOM 구조를 조회할 때에는 console.dir이 유용하다(나중에 자주 쓸 것 같음). console.dir 은 console.log 와 달리 DOM을 객체의 모습으로 출력한다.
ERROR!
<script>를 body 아래 쓰지 않고 위에 쓰면
Uncaught (in promise) TypeError: Cannot read properties of null
이런 에러가 뜬다. 정의되지 않은(undefined) 객체(object)의 속성(property) 값 또는 함수를 읽으려고 하거나 호출하려고 할 때 발생하는 오류. 여러 이유 때문에 발생할 수 있지만, 내 경우에는 script가 위에 있어서 발생.
단, 이 현상은 script 내에 defer을 쓰면 에러가 사라진다.
(왜?)-> https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
async vs defer attributes
The async and defer attributes for the <script> element have great support now, so it’s time to learn exactly what they do!
www.growingwiththeweb.com