Coding/Today I Learned (148)

08
26

확실히 테이블로 정보를 적어 놓으니 관리는 편하겠네요. 전 안 입겠습니다.

1. SQL?

  • Structured Query Language를 줄인 말이다.
  • 관계형 데이터 베이스를 다룰 수 있게 되며, MySQL을 설계하며 이를 SQL로 수정하게 된다.

2. Database

  • in memory에 파일을 저장하게 되면 컴퓨터가 꺼지면 사라진다. 그래서 서버에 파일 자체에 저장을 해 놓는다면, 클라이언트가 원하는 정보만 받아 올 수 없고, 모든 정보를 싹 다 가져와야 한다. 그래서 그러한 데이터들을 한 곳에 저장하고 필터링을 해서 필요한 정보만 클라이언트에 주기 위해 만든 것이다.
  • 생긴 모습은 '엑셀'과 같다.

3. SQL과 NoSQL의 미묘한 관계

  • SQL은 관계형 데이터 베이스이다. 그래서 정보를 입력하기 전에 '테이블'에 저장할 데이터의 구조를 짜 놓는다. 그래서 알아보기 편하다.
  • NoSQL은 정보를 입력하기 전이 아닌, 정보를 읽어 올 때 정보에 생김새에 따라 맞는 방식으로 읽어 온다고 생각하면 편하다.
  • 둘 다 각자의 장, 단점이 있다. (속도 적인 측면에서는 NoSQL이 뛰어나기도 하지만, 데이터들의 크기가 크지 않은 경우, 읽어오고 사용하기 복잡한 NoSQL 보다 SQL을 사용한다.)
  • 각각의 상황과 데이터들에 따라 바꿔서 사용한다.

4. MySQL 설치하기.

  1. 우분투를 사용한다면, sudo apt-get update 와 sudo apt-get install mysql-server 로 설치 가능.
  2. 설치가 완료되면 sudo systemctl start mysql로 실행시킨다.
  3. 실행 이후, mysql -u root로 접속한다. 만약 안된다면, sudo mysql -u root로 관리자 권한으로 해보자.
  4. 처음 접속하면 조금 당황스럽다. 커서 앞으로 'mysql>' 이 보이고 엔터를 치면 아래줄로 내려가면서 아무 일도 일어나지 않는다. 잘 실행된 것이니 일단 로그인 비밀번호를 설정해 줄 것이다.
  5. ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourPassword'으로 비밀번호를 설정할 것이다. 'yourPassword' 부분에 설정할 비밀번호를 입력해 주자. 이제 이 비밀번호로 접속을 하게 될 것이다.
  6. '\(백 슬레쉬)q'로 접속을 종료할 수 있다. 설정된 비밀번호를 테스트하기 위해 한번 접속을 종료해 보자.
  7. 이제는 mysql -u root -p를 입력해서 접속하자.
  8. 비밀번호를 물어볼 것이다. 잘 입력해주면, 접속이 완료된다.

5. 뭐든지 해 보자!

  • 먼저, 가장 중요하게 알아 두어야 할 것은 ';'이다. 꼭 마지막에 세미콜론을 붙여주자. 안 그러면 계속 줄 바꿈을 하게 된다.
  • 모든 명령은 대문자로 적는다. 투철한 실험 정신으로 소문자로도 적어 보니 작동한다! 하지만 모두 대문자로 적고 있다. 왜 일까..?
  • SHOW DATABASES; 를 입력해 보면 지금 있는 데이터베이스의 목록이 뜬다.
  • 데이터베이스를 만들때는 CREATE DATABASE 데이터베이스 이름; 을 사용한다. 이후 SHOW DATABASES; 로 확인해 주면 되겠다.
  • USE 데이터베이스 이름;으로 데이터베이스를 선택해서 사용할 수 있다.
  • 삭제할 때는 DROP DATABASE 삭제할 데이터 베이스 이름 사용한다.

6. 아주 간단한 연습을 할 때 유용한 명령어

  1. SELECT 필드 이름 : 데이터를 선택한다.
  2. FROM 테이블 이름 : 테이블의 이름 앞에서 어떤 테이블을 받아올지를 정해준다.
  3. UPDATE 테이블 이름 SET 필드 = 값 : 데이터를 수정할 수 있다. 테이블 이름과 필드 이름을 입력해 주어 어떤 데이터를 어떻게 바꿀지 적을 수 있다.
  4. WHERE 필드 이름 조건 : 마치, 필터처럼 작동한다. UPDATE나 SELECT 뒤에 붙어서 특정 값을 만족시키는 데이터만 뽑아낸다.
  5. * : 모든 것. 예를 들어 SELECT * 한다면, 모든 필드를 다 선택하는 것이 된다. 주의해서 사용하자.

7. 필수로 알아야 할 다양한 명령어

https://www.w3schools.com/sql/exercise.asp

 

W3Schools SQL Exercise

I completed all the SQL exercises on w3schools.com

www.w3schools.com

  • 퀴즈를 직접 풀어보면서 자연스럽게 배울 수 있다. 이것이 가장 빠른 방법인 것 같다.
  • 만약 모르겠다면, 오른쪽 아래에 'Show Answer'을 눌러서 확인할 수도 있지만, 왼쪽 텝에 Tutorial 페이지로 연결해주는 링크가 있으니 그곳부터 천천히 읽어보고 오는 것을 추천한다.
  • 영어의 장벽이 무섭다면 번역을 번갈아 보면서 해도 충분하다. 오히려 영어로 보는 게 번역보다 매끄러울 수 있다.
  • 위의 문제들을 충분히 풀어본 후에 터미널 창에서 직접 해 보면 무엇보다 재미있다...!
COMMENT
 
08
25

왜 다이나믹 프로그래밍이 다이나믹 프로그래밍 인 줄 아십니까...?

1. 문제의 발단.

그렇다. 이유는 없다. 멋있어서 붙여진 이름이라고 한다. 그러니 나처럼 왜 다이내믹 이냐?라는 의문을 품고 이유를 찾게 되면 전혀 없으니 다른 방식으로 이해를 해 보려고 한다.

 

2. 기본 원리

  • 큰 하나의 문제를 위해 그 문제를 새부적인 문제들로 나눠서 이전에 작은 문제를 풀었던 답을 이용해 다음에 나올 문제를 풀고, 마지막에 그 결과들을 합쳐서 큰 문제 하나의 답을 도출 해 낸다.
  • 이때, 작은 문제들의 결과를 계속 이용하기 위해 따로 그들을 저장해 놓는다.
  • 이는 재귀함수를 이용할 때 사용했던 메모이제이션(Memoization)을 이용하는 것과 같다.

3. 언제 사용하나요?

  • 큰 문제를 작은 문제들로 나눠서 생각할 수 있는경우
  • 같은 문제를 구할 때, 계속 구할 때마다 답은 같은 경우

4. 다시 돌아온 피보나치

  • 피보나치수열을 이용해 알아보자
  • 피보나치수열의 경우 계속해서 자신이 구했던 값들을 다시 계산해서 그 자리 위치를 맞추어 계산하게 된다.
  • 하지만 이전에 이미 계산한 수를 저장했다가 다시 사용하면 효율을 굉장히 올릴 수 있다.
const fibo = (n, arr = [0]) => {
  // 처음 3 보다 작으면 무조건 1이다.
  if(n < 3) {
    arr[n] = 1;
  }
  // arr에 작게 나눈 문제들의 답(각각의 이전  fibo의 결과들)이 들어가 있다.
  // 만약 찾을 수 없다면?
  if(!arr[n]) {
  // 계산해서 arr에 넣어준다.
    arr[n] = fibo(n - 1) + fibo(n - 2)
  }
  return arr[n]
}
COMMENT
 
08
24

전 그래서 일단 주석 처리부터 해 보고 지웁니다. 물론, 풀 수 있다면 말이죠.

1. 문제의 발단.

 알고리즘 문제들은 매우 어렵다. 처음 문제를 접하고 풀리지 않는 문제를 볼 때는 무섭기까지 했다. 하지만 결국, 우리는 피해 갈 수 없다. 아무리 실무에서 안 쓴다더라, 누구는 안 하고도 코딩 잘하더라 하지만 어떻게 보면 가장 쉽게 코딩 실력을 키우고 좋은 곳에 취직을 할 수 있는 방법이 알고리즘을 잘 푸는 것이 아닐까? 그래서 오늘도 이렇게 삽질을 하고 있다.

2. 알고리즘?

  • 문제를 가장 효율적으로(최단 시간과 연산 과정에서의 반복을 최선으로 줄인) 해결하는 방법이다. 일명, 극한의 이득충
  • 분명, 모든 경우의 수를 다 확인한다면 반드시 답에 접근이 가능하다. 하지만 문제에서 아주 다양한 방법으로 제한사항을 두고 일상생활과 같은 곳에서 볼 수 있는 상황을 코드로 만들 수 있는가? 와 같은 다양한 상황에 마주치게 된다.

3. 어떻게 접근할 것인가?

  • 문제를 이해한다. '이해'한다. 사실은 이것이 50%이다. 대부분의 알고리즘 문제들은 문제를 읽는 것도 길고, 문제가 원하는 의도를 찾는 것도 쉽지 않다. 그러므로 일단 어떤 식으로 입출력 예시들이 작동하고 있는지를 이해하고 문제의 의도를 파악한다.
  • 수도 코드를 적는다. 난의도가 어려워질수록 더욱 필요하다. 코드 자체가 길어지기 때문에 내가 무엇 때문에 지금 이 코드 한 줄을 이용해 무엇에 접근하려고 하는지를 까먹게 된다. 필요하다면 그림을 그리거나, 이해한 것을 타인에게 설명해 보아도 좋을 것이다.

4. 시간복잡도 (Time Complexity)

  • 간단하게 말해서 이 알고리즘이 연산될 때마다, 얼마나 시간이 걸리는가? 를 묻는 것이다.
  • 이것을 줄이는 것이 우리가 생각하는 알고리즘 문제가 될 것이다.
  • 주로 우리는 Big-O (빅-오) 표기법으로 시간 복잡도를 표현한다.
  • 최고의 효율인 Big-Ω(오메가), 평균적 효율인 Big-θ(세타) 표기법도 있지만, 평가가 어려워서 잘 사용하지 않는다고 한다.

5. Big-O

Big-O 표기법의 복잡도를 나타낸다.

  • O(1) : 입력과 상관없이 바로 출력이 가능한 복잡도. index를 받아서 바로 출력하듯이, 얼마나 많은 입력이 있는 것은 상관없이 바로 해당 index에 접근해서 출력하게 된다.
    • function O1(arr, index) {
      	return arr[index];
      }
      
      let arr = [1, 2, 3];
      let index = 1;
      let result = O1(arr, index);
      console.log(result); // 2
  • O(n) : 입력과 함께 시간 복잡도가 똑같은 비율로 증가한다. 반복문을 사용해 모든 요소를 돌면서 데이터를 조작할 때처럼, 입력이 많아지면 돌아야 할 요소가 많아지는 것처럼 말이다.
    • function On(n) {
      	let arr = [];
      	for (let i = 0; i < n; i++) {
      		arr.push(i)
      	}
          return arr;
      }
      
      On(3) // [0, 1, 2]
      On(5) // [0, 1, 2, 3, 4]
  • O(log n) : 한번 연산이 될 때마다, 연산해야 할 요소들이 절반으로 줄어든다. BST가 O(log n)에 속한다.
    • // target의 index를 리턴한다. 없으면 -1을 리턴하자.
      
      const binarySearch = function (arr, target) {
        let start = 0;
        let end = arr.length - 1;
      
        while(start <= end) {
          let mid = Math.floor((start + end) / 2);
          if(arr[mid] > target) {
            end = mid - 1;
          } else if(arr[mid] < target) {
            start = mid + 1;
          } else {
            return mid;
          }
        }
        return -1;
      };
      
      let output = binarySearch([0, 1, 2, 3, 4, 5, 6], 2);
      console.log(output); // --> 2
      
      
      output = binarySearch([4, 5, 6, 9], 100);
      console.log(output); // --> -1
  • O(n^2) : 입력값이 증가하면 시간이 제곱으로 증가한다. 매우 비효율적이다. 우리가 자주 사용하는 이중 반복문이 여기에 해당한다.
    • function O22(n) {
          let arr = [];
      	for (let i = 0; i < n; i++) {
      		for (let j = 0; j < n; j++) {
      		    arr.push([j, i])
      		}
      	}
          return arr;
      }
      
      O22(2) // [[0, 0], [1, 0], [0, 1], [1, 1]]
  • O(2^n) : 입력값이 증가할 때마다 시간 복잡도가 제곱으로 증가한다. 최악의 효율을 가지고 있다. 재귀 함수를 이용한 피보나치수열을 만들 때 이러한 시간 복잡도가 된다.
    • function fibonacci(n) {
      	if (n <= 1) {
      		return 1;
      	}
      	return fibonacci(n - 1) + fibonacci(n - 2);
      }
      
      // 계속해서 그 이전 숫자들 까지 전부 다시 계산을 해 줘야 하므로 매우 비효율 적이다.

6. Greedy Algorithm

  • 말 그대로 욕망에 따라 움직이는 알고리즘을 말한다. (이 말 자체가 이상하게 보이긴 하다;;)
  • 지금 선택할 수 있는 가장 큰 경우의 선택을 고르고, 이후 점점 줄어들면서 결국 정답에 다다르기 때문에 이렇게 말한다.
  • 하지만 이러한 선택이 표면적으로는 빠르게 정답에 가까워 질지 몰라도 최고의 효율을 낸다고 볼 수는 없다.
  • 거스름돈을 거슬러 줄 때, 가장 큰 단위 (ex: 5460원을 거슬러 줄 때, 5천 원 지폐 하나, 100짜리 4개, 10원짜리 6개를 준비한다)부터 거슬러 주는 상황을 생각하면 된다.
COMMENT
 
08
23

처음 우분투를 사용할때 내 머리도 터지고 컴퓨터도 한번 터졌었습니다. 하루에 포멧을 수십번 했었죠.

1. 사용권한

  • 터미널에서 'ls -l'을 입력하면 각 파일들의 사용권한을 알 수 있다. 가장 앞에 적혀있는 drw 어쩌고... 이것이다.
  • 가장 첫 번째 'd'는 directory 즉, 폴더인지 아닌지를 나타낸다.
  • 나머지는 'rwx'가 3번 반복되는 형태로 나타난다.

2. rwx?

  • 먼저 rwx들은 3등분으로 나눌 수 있다.
  • 첫 번째 rwx는 '소유주' 이것을 소유한 본인이 직접 가지는 권한이고, 두 번째 rwx는 '소유 그룹' 마지막 rwx는 '타인'이 가지는 권한이다.
  • ls -l을 사용하면 가장 앞에 권한들이 적혀 있고, 숫자 권한 이후에 나오는 것이 '소유주', 그다음이 '소유 그룹'이다.
  • 권한이 없다면 '-'로 표현한다.

3. 권한을 바꿔보기

  • 명령어 'chmod'를 사용한다. 
  • 'chmod + '권한을 바꿔줄 u(user, 소유주) 혹은, g(group, 소유 그룹) 혹은, o(other, 타인) + 권한을 줄 때 '+' 혹은, 권한을 없앨 때 '-' + '줄 권한(r, w, x)'  ' 형식으로 입력한다.
    • ex) -rw-rw-r-- Hello.txt
    • chmod u-w Hello
    • -r--rw-r-- Hello.txt => 유저도 쓸 수 없는 txt 파일을 만들었다;;
  • whoami 는 지금 유저가 누구인지 알 수 있다.

4. 숫자로 보는 권한

  • 4 : read (2의 2승)
  • 2 : write(생성, 삭제, 수정)
  • 1 : execute
  • 그래서 u, g, o에 따라 3개씩 끊어서 읽는다.

 

COMMENT