이 글은 DOM을 간단하게 이해하는 정도로만 작성한 글이며 자세한 내용은 구글링을 통해서 개념을 가지는 것이 좋습니다.

DOM이란?

DOM은 Document Object Model 의 줄인말로 HTML 문서를 구조화 한 것으로 프로그래밍 언어가 DOM 구조에 접근 할 수 있는 방법을 제공하여 문서 구조, 스타일, 내용 등을 변경 할 수 있도록 도와주는 인터페이스 역할을 한다.

DOM은 HTML, XML 문서를 Tree형식으로 구조되며, Javascript와 같은 스크립트 언어를 사용하여 수정할 수 있다.

DOM의 Tree 구조 예시는 아래 사진과 같다.

DOM Tree 구조 예시. 출처 : 위키트리

DOM은 언제 사용할까?

그러면 DOM이라는 것을 언제 사용할까?

HTML로 웹페이지를 사용해보고 만들어본 경험자라면 알겠지만, 우리가 흔히 아는 웹페이지는 가만히 보여지는 이미지가 아니다.

버튼을 눌러서 어떠한 동작을 하고, 다른 페이지로 이동, 다운로드, 데이터 변경 등 상호작용을 한다.

이 모든 것을 HTML 태그들을 이용해서 웹페이지를 만들 수 없다. 동적인 기능을 이용하기 위해서 우리는 JavaScript와 같은 스크립트 언어들을 사용하고 DOM 구조를 변경한다.

 

요약

DOM은 HTML을 위한 API이며 HTML을 탐색을 하거나 구조를 바꿀 수 있다.

 

'CS > 개념, 용어' 카테고리의 다른 글

CPU와 GPU, TPU 차이  (0) 2023.03.18

프로젝트를 하다보면 프로젝트 폴더에 여러 파일을 다운받거나 수정하게된다.

react 같은 경우 module 들을 하나 둘 씩 다운받다보면 새로운 파일들이 많이 생기고 "git status"에 항상 검색이 되서

필요한 파일만 github repo에 push하고 싶을 때 불편함이 있다.

이런 경우처럼 git repo에 업로드 하지 않을 파일들을 기록하는게 .gitignore이다.

 

파일 이름 앞에 .이 붙어있는 것으로 보아 이 파일은 숨김 파일로 되어 있다.

작성방법은 어렵지 않다. 보통 아래 상화에서 많이 사용한다.

 

1. 하나의 파일을 제외하고 싶을 때

[파일 이름].[파일 확장자]

2. 특정 폴더내의 파일 모두를 제외하고 싶을 때

[폴더 이름]/

3. 특정 확장자 파일 모두를 제외하고 싶을 때

*.[확장자]

4. 제외하고 싶은 폴더가 어디에 있던지 간에 제외하고 싶을 때

**/[폴더 이름]/

이제 작성을 했으면 적용을 시켜야한다.

새로 작성한 .gitignore를 git repo에 push한다

git add .gitignore
git commit -m "add .gitignore"
git push [remote 이름] [branch 이름]

이렇게 하면 끝!! 이면 좋겠으나 repo의 캐쉬를 제거하고 다시 업로드해야하는 절차를 걸쳐야한다.

git rm -r --cache .     (꼭 . 을 붙여야 오류가 안난다..)
git add .
git commit -m "apply .gitignore"
git push [remote 이름] [branch 이름]

 

이렇게 하면 .gitignore에 추가한 폴더나 파일이 push 되지 않은 것을 확인할 수 있다.

'CS > git' 카테고리의 다른 글

git 명령어 정리  (0) 2023.03.10
git과 github  (0) 2023.03.10

CPU

Central Processing Unit, 중앙처리장치라고 불리는 CPU는 컴퓨터의 두뇌를 담당하고 있다. CPU는 명령어 하나로 처리할 수 있는 기능이 많고 각종 제어처리를 위한 부분이 많다. 또한 다양한 작업을 빠르게 처리하기 위해서 복잡한 ALU 구조를 가지고 있다. 따라서 CPU는 직렬처리에 최적화 된 몇개의 코어로 구성되어 있다.

CPU는 코드 실행, 여러 디바이스(키보드, 하드디스크)들이랑 상호작용, 사용자들로 입력받은 명령어들을 해석, 연산 후 결과를 출력하는 역할을 한다.

 

GPU

Graphics Processing Unit, 그래픽처리장치라고 불리는 GPU는 픽셀로 이루어진 영상을 처리하는 용도로 탄생했다. GPU는 특화된 연산을 병렬적으로 나누어서 처리한다. 따라서 특화된 연산을 빠른 속도처리하기 위해 단순한 ALU 구조를 가지고 있다. 따라서 GPU는 병렬 처리용으로 설계된 수천 개의 작은 효율적인 코어로 구성되어 있다. 위에서 설명한 CPU가 GPU를 제어한다.

GPU는 AI 기계학습, 컴퓨터 그래픽 픽셀 연산, 3D 렌더링 등 에 사용된다.

 

CPU로는 GPU를 대체할 수 없는걸까?

기존 CPU는 1개의 코어로 1개의 작업밖에 할 수 없었다. 그래서 최근에는 MutiCore CPU라고해서 여러개의 코어를 가진 CPU가 등장하고 있다. intel core i9 extreme edition은 18개의 코어를 가지고 있으며 각 코어는 초당 30억 사이클을 실행할 수 있는 3.00GHZ의 속도를 가지고 있다. 그렇다면 더 이해를 할 수 없다... CPU에 코어를 많이 늘리면되지 않을까?? 라는 생각이 든다.

하지만 그 생각은 한계가 있다. CPU는 에너지 소모가 심하다. 이러한 CPU에 코어를 무작정 많이 늘린다면?? 우리의 전기세는 엄청나 질 것이다... GPU는 CPU보다 코어의 갯수가 많다고 했다. Nvidia Geforce RTX 3090을 예로 들면 해당 그래픽 카드는 10,496개의 코어를 가지고 있으며 각 코어 당 1.70GHZ의 속도를 가지고 있다. 코어의 갯수가 CPU랑 비교하면 어마무시하다. 이렇기 때문에 GPU가 인공지능 학습, 그래픽 픽셀 연산에 사용되는 이유이다. 이들은 간단한 계산들이지만 동시에 빠르게 연산되어야 할 필요가 있다. 쉽게 설명하면 여러분들이 게임을 할 때나 유튜브로 영상을 볼 때 화면이 부드럽게 넘어간다고 느끼는 것은 60fps 정도가 될 것이다. 이는 초당 60개의 프레임이 보여진다고 생각하면 된다. 초당 60개?? 별로 안되네 라고 생각하겠지만 여러분이 지금 이 글을 보고 있는 모니터를 생각해야한다. 요즘 보통 1920*1080 ~ 4096*2160 해상도를 가지고 있을 텐데 해당 숫자들이 하나의 픽셀이다. 여러분들이 부드럽게 이질감 없이 보이기 위해는 모든 픽셀들이 각 위치에 맞는 색깔들을 동시에 계산하고 화면에 보여져야한다. 만약에 여러분들의 4K(4096*2160) 모니터로 60fps 동영상을 보고있다면 초당 4096*2160*60 을 계산하면서 여러분들에게 보여주고 있는 것이다. 이런 동시에 빠르고 간단한 연산은 GPU가 최적일 수 밖에 없다.



TPU

Tensor Process Unit, 2016년 Google에서 발표한 장치이다. 기존 GPU보다 백터/행렬 연산의 병렬처리에 특화되어 있어 선형대수 연산 성능을 가속화하여 복잡합 대형 신경망 모델을 학습시킬 때 정확성 달성 시간을 최소화 시킬 수 있다. Google에서 적힌 설명으로는 GPU에서는 몇주가 걸리는 모델 학습이 몇 시간안에 학습이 된다고 적혀있기도 한다. 아직까지 특허를 내지 않고 정확하게 공개되지는 않았다.

 

용어정리

ALU : 산술 논리 장치, 산술연산(덧셈, 뺄셈 등등) 과 논리연산(논리합, 논리 곱)을 계산하는 디지털 회로

코어 : 이진법으로 표현된 정보의 저장을 위한 자성 물질

'CS > 개념, 용어' 카테고리의 다른 글

DOM이란?  (0) 2023.06.15

이번 글에서는 docker에 대해서 알아보고자 한다.

대학생 때 팀 프로젝트에서 docker를 사용해본적은 있지만.. 같은 팀원이 다 만들고 실행만해서 사용했어서 사실 사용했다고 하기엔 창피할 정도,,

대학교 때 docker에 대해서 공부해보려고 했지만 그때는 아무리 읽어도 왜 그렇게 이해가 안됐는지 모르겠다 ㅠㅠ

https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html 사이트 글을 읽고 이해한 내용을 작성한다.

글이 오래되서 버전이나 이런부분은 다르지만 docker에 대해서 개념을 잡을려고 한다면 이 글을 읽으면 많이 도움이 될 것으로 보인다.

docker에 대해서 알아보기 전에 docker를 하면 항상 따라오는 단어들을 먼저 이해하고 넘어가보고자 한다.

 

docker 이미지 출처 : Google

컨테이너

컨테이너는 docker의 로고에서도 표현되듯이 docker하면 가장 많이 따라오는 단어이다.

컨테이너란 라이브러리, 시스템 도구, 코드 등 소프트웨어 실행에 필요한 모든 것이 포함되어 있다. 컨테이너는 하나의 프로세스라고 볼 수 있다.

 

이미지

docker에서 이미지란 컨테이너를 만들고 실행시키는데 사용되는 읽기 전용 템플릿이라고 볼 수 있다.

 

linux container

리눅스 컨테이너란 리눅스에서 프로세스를 격리하는 방식이다. docker는 리눅스 컨테이너 방식을 인용해서 만들어졌다.

docker

이제 docker에 대해서 알아보자. docker는 컨테이너 환경에서 독랍적으로 애플리케이션을 실행할 수 있도록 컨테이너를 만들고 관리하는 것을 도와주는 도구, 즉 컨테이너를 관리하는 플랫폼이다. 이미지를 이용해서 컨테이너를 실행시키거나 만들고, git에서 github와 비슷한 docker에서는 dockerhub를 이용해서 다른 사용자에게 이미지를 배포할 수 있다.

 

docker의 장점

1. 하나의 서버에 여러개의 컨테이너를 실행해도 서로 영향을 미치지 않고 독립적으로 실행되어 가벼운 VM을 사용하는 느낌을 준다. 이는 실행중인 컨테이너에 접속하여 명령어를 입력할 수 있고 apt-get 이나 yum으로 패키지 설치가 가능하다

2. 새로운 컨테이너를 만드는데 1~2초 정도의 짧은 시간이 걸리며 이는 가상머신보다 훨씬 속도가 빠르다.

 

docker vs VM

대충 설명만 보면 docker랑 VM이랑 크게 달라 보이진 않아보인다. docker가 VM보다 빠르고 가벼운 장점은 있다는 건데 어떤게 크게 다를까?

VM 과 docker 차이

VM은 host OS위에 하나의 물지적 머신에서 여러 가상 머신을 실행하는데 사용하는 소프트웨어인 hypervisor를 이용해서 Guest OS를 가상화하여 사용한다. 여러가지 OS를 가상화하여 사용할 수 있고 비교적 사용법이 간단하지만 무겁고 느려서 운영환경에서는 사용하는데 제한이 된다.

하지만 docker은 host OS위에 docker engine으로 프로세스를 단순하게 격리하기 때문에 가볍고 빠르다. 프로세스(컨테이너)가 필요한 만큼만 CPU나 메모리를 사용하기 때문에 성능적인 손실이 적다.

 

군대에서 체계운용장교라는 보직으로 있으면서 여러 서버를 관리하고 유지했다. 군대에서는 서버 1대당 PC가 각각 1대씩 있었다. 이렇게 되면 하나의 서버를 만들기 위해서 PC 하나를 새로 만들어야하기 때문에 시간이나 자원, 비용이 많이 들었다.

'그냥 하나의 PC에서 여러개 설치하면 되잖아?' 생각할 수 있겠지만 군대인 만큼 호환이 잘 안된다.. 서버마다 사용하는 OS도 다르고 필요로 하는 프로그램 버전도 다르다. 회사에서도 마찬가지 일 것이다. 회사에서도 여러 서버를 관리할 일이 있을 것이고 서버당 필요로 하는 프로그램이나 OS 조건들이 많이 다를 것이다. VM은 위에서 설명했듯이 여러개의 Guest OS를 사용해서 관리하면 속도나 자원 문제가 발생하지만 docker를 이용해서 하나의 서버를 컨테이너로 관리하고 실행하면 프로세스로 쉽게 관리할 수 있다.

  1. git status : git 폴더에서 사용 가능, 브랜치 상태, 수정된 파일 등을 확인할 수 있음
  2. git log : log 확인하는 명령어
  3. git init : 작업 폴더를 git 폴더로 만들기 위해 사용
  4. git clone [http://~~] : git 저장소 복제 및 다운로드 
  5. git add [수정한 파일] : git 저장소에 저장할 파일 추가
  6. git commit -m ["작성할 커밋 메세지"] : 저장소에 추가된 파일을 커밋 & 커밋 메세지 작성
  7. git push origin [브랜치 이름] : 커밋한 파일을 [브랜치 이름]으로 전송
  8. git pull : 변경된 내용 가져오니
  9. git branch : 현재 브랜치 확인
  10. git branch [브랜치 이름] : [브랜치 이름] 생성
  11. git branch -d [브랜치 이름] : [브랜치 이름] 삭제
  12. git checkout [브랜치 이름] : [브랜치 이름]으로 브랜치 변경
  13. git merge [다른 브랜치 이름] : 현재 브랜치에서 [다른 브랜치 이름] 변경사항 병합
  14. git stash : commit 하고 싶지 않은 파일이 있을 때 stash 저장소로 따로 빼놓음
  15. git stash apply : stash 저장소에 있는 파일을 다시 가져옴
  16. git stash drop : stash 저장소에 있는 파일을 삭제

 

'CS > git' 카테고리의 다른 글

.gitignore에 대하여  (0) 2023.04.01
git과 github  (0) 2023.03.10

git과 github는 같은 의미일까?

보통 git을 사용하면 github도 같이 사용하지만 이 둘은 다른의미이다.

그렇다면 어떤 차이점이 있을까?

 

버전관리시스템

버전관리시스템이란 시간에 따라 파일의 변경사항을 추적하고 기록하여 필요에 따라 이전 버전으로 복구하거나 조회하는 기능을 말한다. 과제를 하거나 보고서를 작성할 때 보통 우리는 여러번의 수정 과정을 거친다. 분명 어떤 사람들은 하나의 파일을 계속 덮어쓰기 할 수도 있고, 누구는 다른이름저장 기능을 사용하여 "보고서 완성본.hwp", "보고서 찐막 완성본.hwp", "보고서 찐찐찐막 완성본.hwp" 이런식으로 저장하는 사람도 있을 것이다. 이렇게 저장을하면 단점이 있다. 첫번째 예시로는 계속 덮어쓰기 기능은 어느 지점으로 돌아가고 싶을 경우 돌아갈 수 없다.. 중간까지는 완벽한데,, 여기서부터 다시하고 싶은데 이미 덮어써버렸다.. 두번째 예시는 바탕화면이 많이 지저분하고 계속해서 그 파일을 저장하고 있어야한다. 지저분한거 감수할 수 있다고하더라도 우리는 언젠가 바탕화면에 많아진 파일들을 하나씩 보면서 최종 보고서 파일을 찾아야한다. 하지만 버전관리시스템은 이러한 단점들을 다 해결해준다.

필요하면 이전 버전으로 복구도할 수 있으며 기록만 잘 한다면 내가 어느버전에서 어떤 것을 수정했고 어디까지 진행했는지 알 수 있다.

 

git

git은 위에서 설명한 버전관리시스템 중 하나 이다. git은 로컬 시스템에 설치되고 관리된다. 계속 쌓이는 프로그래밍 버전을 스스로 관리할 수 있다. 로컬 시스템에 설치되고 관리되기 때문에 인터넷이 없는 상태에서도 관리할 수 있다. 또한 branch 기능은 또 다른 독립적인 로컬 시스템을 만들어 관리할 수 있으며, 필요에 따라 삭제, 병합이 가능하다.

 

github

그렇다면 github은 뭐야?

github은 git 저장소를 관리하는 클라우드 서비스이다. 즉 git은 로컬 시스템에서만 설치되고 관리되는데 이것을 github에 올려 다른사람이랑도 공유가 가능하도록 만든다. 본인이 github에 업로드한 코드나 파일들은 다른사람들이 git clone 기능을 사용하여 이어서 작업하거나 다운받을 수 있다. 따라서 다른 사람들과 프로젝트를 할 때 공유가 가능하여 쉽게 수정하고 개선할 수 있다.

'CS > git' 카테고리의 다른 글

.gitignore에 대하여  (0) 2023.04.01
git 명령어 정리  (0) 2023.03.10

1. 문제 파악하기

- orders 배열의 크기는 2 이상 20이하이다. & orders 배열의 각 원소의 크기는 2이상 10이하인 문자열이며 대문자로만 이루어져 있다.

- 정답은 오름차순으로 정렬해서 return해야함.

2. 문제 접근하기

- orders에 있는 원소들의 조합을 생각해야함. 이때 조합의 길이는 2이상 10이하의 자연수임 → itertools 라이브러리의 combinations를 사용할 것임

- 단품 메뉴 조합이 2번이상 나와야하며 가장 많이 나온 것들을 찾아야함.

 

3. 주의할 점

- orders의 원소들은 대문자로 되어있지만 사전순으로 정렬되어 있지 않음 → 먼저 정렬시킬 필요가 있음

- 언급은 되었더라도 2번 이상 언급이 된 코스요리여야함.

 

4. 정답 코드 및 해석

 

제가 작성한 코드는 아래와 같습니다.

from itertools import combinations

def solution(orders, course):
    answer = []
    for i in course :
        combination = []
        for j in orders :
            j = ''.join(sorted(list(j)))
            result = list(combinations(j,i))
            for k in result :
                combination.append((''.join(list(k))))
        result = []
        for j in combination :
            count = combination.count(j)
            result.append((j,count))
        result = list(set(result))
        result = sorted(result, key=lambda x: x[1], reverse=True)
        max_result = list(filter(lambda x: x[1] > 1 and x[1] == result[0][1], result))
        for j in max_result :
            answer.append(j[0])
    answer.sort()
    return answer

1. 우선 course의 원소를 기준으로 for문을 돕니다.

2. 그 안에 다른 for문을 작성하는데 이는 orders의 원소를 기준으로 돕니다. 이 for문의 용도는 orders 원소를 i길이로 combination하기 위함입니다. orders의 원소는 사전식으로 정렬되어 있지 않았습니다. 따라서 문자열을 리스트로 변형시키고 정렬한 다음 .join()을 이용해서 정렬된 문자열로 만듭니다.

3. result 변수 안에는 i길이로 조합된 원소들이 있습니다. 이때 result안에 원소들은 ("A","B")와 같이 집합 형태로 되어 있으므로 join()을 이용해서 combination이라는 변수에 조합된 문자열을 넣습니다. for문을 다 돌았을 때, combination 변수 안에는 orders안에 있는 원소가 i길이로 조합된 문자열이 들어 있을 것입니다. ex) i=2, orders = ["ABC", "EFQ"] 라면 combination의 최종 결과는 ["AB", "AC", "BC", "EF", "EQ", "FQ"]가 들어 있습니다.

4. 다시 for문을 만들어서 combination의 각 원소가 몇번 나왔는지 센다음 result에 (조합된 문자열, count) 형태로 저장합니다. 하지만 이때 result에는 중복된 값이 있을 수 있습니다. 그래서 result = list(set(result))를 이용해서 중복된 값을 제거한 다음 다시 리스트로 만듭니다.

5. result에 들어있는 원소들을 count를 기준으로 내림차순으로 정렬합니다. 그러면 가장 많이 count된 조합이 가장 앞에 있겠죠? count된 횟수가 같은 원소들이 있을테니 filter 함수를 이용해서 count가 2이상, 가장 많이 언급된 원소들만 골라냅니다. 골라낸 원소들은 max_result 변수에 저장됩니다.

6. filter된 원소들을 answer에 넣습니다.

7. 마지막 return하기전에 answer 리스트를 정렬한 다음 return합니다.

 

이렇게 코드를 작성하고 채점을 하면 다음과 같은 결과로 통과가 됩니다.

 

테스트 케이스 결과

 

5. 마치며

이번 문제는 level2치곤 쉬운 문제였습니다. 하지만 itertools의 combinations 기능을 몰랐다면 조합을 어떻게 만들지 조금 많이 고민했어야 했을거 같습니다. 이번 문제는 카카오 블라인드 채용에서 나온 문제인데 예전보다 카카오에서 나오는 문제들이 꽤 많이 까다롭고 복잡한 경우가 많은거 같습니다. 이번 문제는 코딩을 할줄 아냐 모르냐를 판별하는 정도인거 같은데 다른 문제들을 보면 꽤 어려운 문제들도 많더군요..ㅎ 더 노력해야겠습니다. 이번 문제는 조금 길어서 겁먹으신 분들도 있으실텐데 코딩테스트도 수능 문제처럼 문제가 길수록 힌트가 많은거 같습니다. 문제가 길수록 옆에 개인 노트에 잘 정리하면서 문제를 생각한다면 조금 더 수월하게 문제를 풀 수 있을거 같습니다.

1. 문제 파악하기

- prices의 각 가격은 1~10,000 이하인 자연수 & prices의 길이는 2이상 100,000 이하 → level 1에서보단 prices의 길이가 조금 긴편이지만 그래도 적당한 길이.

 

2. 문제 접근하기

- 초 단위로 기록된 주식 가격이 담긴 배열 prices가 매개변수로 주어지고, 가격이 떨어지지 않은 기간은 몇초인지 retrurn해야함. → 1초의 가격이 2이고 2초 가격이 1이면 return 배열에 들어가는 1초 가격이 떨어지지 않은 기간은 1초이다. 1초 가격이 2, 2초가격이 3, 3초 가격이 1이면 return 배열에 들어가는 1초 가격이 떨어지지 않은 기간은 2초이다.

 

3. 주의할 점

level 1 과 다르게 인자로 주어지는 값의 길이가 많이 커졌습니다. 이때 단순하게 level 1에서 생각한 방법으로 코드를 작성하시다간 시간초과가 일어날 가능성이 높습니다. 이번 문제에선 커트라인을 꽤 크게 주어진 듯하지만 개인적으로도 만족하지 않은 코드입니다. 다른 사람들 풀이의 댓글에보면 스택을 이용하면 O(n)로 문제를 풀 수 있다고 합니다. 저도 지금 당장은 생각이 나지도 않고 다른 사람들 풀이에도 O(n^2)으로 푼 방법 밖에 없어서 한번 생각해봐야겠습니다. ㅎㅎ

 

4. 정답 코드 및 해석

제가 문제를 푼 방법은 다음과 같습니다.

def solution(prices):
    answer = [0 for i in range(len(prices))]
    for i in range(len(prices)) :
        for j in range(i+1,len(prices)) :
            if prices[i] <= prices[j] :
                answer[i] += 1
            else :
                answer[i] += 1
                break
    return answer

시간 복잡도를 신경쓰지 않는다면 생각보다 간단하게 문제를 해결할 수 있습니다.

저는 우선 answer이라는 배열에 prices길이만큼 0이라는 숫자들을 담았습니다.

그런 다음 다들 보이시겠지만 2중 for문을 사용하여 O(n^2)으로 문제를 해결했습니다.

이 코드는 원소 하나씩 차례대로 비교하면서 값을 구하는 방법이죠.

이렇게 코드를 작성하면 아래와 같이 케이스를 해결할 수 있습니다.

테스트 케이스 결과

 

5. 마치며

오늘은 level 2의 문제를 보았지만 그 중에서도 가장 짧고 간단한 코드들을 보았습니다. level 2라고해서 level 1과 크게 다를 것은 없습니다. 다만 코드의 길이가 조금 늘어나고 level 2부터는 시간 복잡도를 생각하면서 문제를 해결하기 시작해야합니다. 이번 문제에서는 O(n^2)로도 문제가 해결됐지만 일반적으로 대기업 코딩테스트에서는 조금 힘들 가능성이 높겠죠. 문제를 해결했다고 해서 만족하고 넘어가는 것이 아니라, 조금 더 나은 코드들을 생각해보시고 그 방법으로 다시 문제를 풀어보시는 것이 좋겠습니다.

+ Recent posts