쿠키

클라이언트와 서버 간에 정보를 주고받는 수단이라고 보면 된다

사용자가 처음 웹 사이트에 접속할때 사이트로부터 쿠키를 받는다 (서버 → 클라이언트)

A 사이트에 로그인을 하면, A사이트의 DB에서 회원 정보를 확인 후 ‘회원 맞음’ 인증 정보를 담은 쿠키가 브라우저에 저장된다 (로그인 → 서버 DB 확인 → 사용자)

로그인 후 글을 쓰거나 댓글을 다는 등의 새로운 요청을 하거나 재접속하더라도 자동으로 브라우저에 저장된 쿠키가 서버로 전달되어 로그인 상태를 유지할 수있다

쿠키는 도메인에 종속 되는데, 무슨 말이냐면 A 도메인에서 발급된 쿠키는 A 도메인에만 사용할 수 있다

쿠키에 유효기간을 정해줄 수 있어, 만료된 후 자동으로 삭제할 수도 있다

예시로 은행처럼 보안상 일정시간 후에 세션이 만료되어 자동 로그아웃 되는 사이트들처럼 말이다

쿠키는 인증 뿐만 아니라 여러가지 정보를 저장할 수 있는데, 장바구니 정보나 언어 설정 같은 사용자 맞춤 데이터를 저장해두는 데도 많이 사용된다

보안 강화를 위해 HTTP-Only 속성을 부여할 수 있다 이 속성은 자바스크립트에서 쿠키에 접근하지 못하게 해 XSS 공격을 방지할 수 있다 토큰 방식에서 Access Token을 쿠키에 저장할 때 권장되는 속성이다

세션

HTTP 프로토콜은 stateless(상태를 기억하지 않는) 특성을 가진다

즉, 각 요청은 독립적으로 처리되며, 서버는 이전 요청의 상태를 기억하지 못하기 때문에

요청이 들어올때 마다 요청자가 누군지 확인해야 하므로 시간과 자원이 더 들게 되는데, 이를 보완하기 위해 세션을 사용한다

세션은 서버에서 관리하는 일시적인 저장 공간으로, 서버는 클라이언트로부터 받은 세션 ID를 기반으로 사용자 상태를 유지한다

사용자가 웹사이트를 방문하면 세션 ID가 담긴 쿠키가 브라우저에 저장되고, 이 쿠키를 통해 사용자는 이후 요청에서도 동일한 세션을 유지할 수 있다

서버는 이 세션 ID를 통해 사용자의 로그인 상태를 기억하거나 개인화된 데이터를 제공할 수 있다

다만, 세션은 주로 서버에 저장되며, 서버 리소스를 소모한

사용자가 많아지면 서버에 더 많은 리소스를 필요로 할 수 있어, 이를 보완하기 위해 Redis 같은 메모리형 데이터베이스를 많이 사용한다고 한다

토큰

토큰이란 서명 같은 것인데, 마치 서류나 카드 뒷면에 서명을 하는것만으로 어떠한 계약에 효력이 생기는 것과 같이 인증된 사용자를 식별하는 디지털 서명의 역할을 한다

세션과 달리, 토큰은 DB 필요없이 서버에서 유저를 인증하는데 필요한 정보 (이를테면 세션 ID)가 담긴 토큰을 저장해서 주면 클라이언트에서 자체적으로 저장하고 이후 페이지를 요청할때 클라이언트가 그때 받은 토큰을 HTTP 요청의 헤더에 담아 서버로 보내면, 서버는 토큰이 유효한지만 검증하면 된다

때문에 토큰 기반 인증에서는 서버가 매번 DB를 확인하지 않아도 되므로, 트래픽이 많은 애플리케이션에서 효율적으로 사용할 수 있지만, 토큰이 유효한지 확인하려면 누구나 열어 볼 수 있어야 하기 때문에 아주 중요한 정보가 있으면 위험할 수 있다

예시로는 코로나때의 QR 코드 인증이 있다

JWT

JSON Web Token

토큰 방식의 인증에서 많이 사용되는 형태이다

인코딩 또는 암호화된 3가지 데이터를 이어 붙인 것으로, 세션 ID보다 훨씬 길고 괴상한 문자들로 이루어져 있음에도 공간제약이 없다 (쿠키는 공간제약이 있다)

잘보면 xxxxxxx.zzzzzz.yyyyy이런식으로 세부분으로 나뉘는데, 각각 1. 헤더 header, 2. 페이로드 payload, 3. 서명 verify signature 순으로 구성되어 있다

  1. 헤더 (Header): 토큰의 타입(JWT)과 서명에 사용할 알고리즘 정보(예: HS256)를 담고 있다
    첫번째 헤더를 디코딩하면 두가지 정보가 담겨있는데, 
    1. 토큰의 type : 타입은 항상 JWT로 고정값이다
    2. alg : 알고리즘의 약자로 3번 서명값을 만드는데 사용될 알고리즘이 지정된다
    3. HS256 등 암호화 방식 중 하나를 지정할 수 있다
  2. 페이로드 (Payload): 토큰에 담을 실제 데이터가 포함된다.(이렇게 되면 누구든 다시 디코딩을 통해 악용이 가능하므로 첫번째와 세번째 부분이 존재한다)
    가운데 페이로드 부분을 base64로 디코딩해보면 JSON 형식으로 누가 누구에게 토큰을 발급했는지, 언제까지 유효한 토큰인지, 서비스가 사용자에게 토큰을 통해 공개하기 원하는 내용들 (사용자 ID, 권한 정보)이 있다
    토큰에 담기는 이러한 데이터를 Claim 이라고 한다
  3. 서명 (Signature): 헤더와 페이로드를 합친 후, 서버에 감춰놓은 비밀 값까지 암호화 알고리즘에 넣고 돌리면 비로소 세번째 서명 값이 된다

즉, 탈취를 당하더라도 서버에 감춰놓은 비밀값을 알지 못하므로 소용없다

다만 세션 방식처럼 모든 사용자들을 기억하지 못하기 때문에 관리의 어려움이 있어 이를 보완하기 위해 토큰 기한을 짧게하는 방법이 있다

로그인을 하면 두개의 토큰이 주어지고 하나는 유효기간이 한시간이나 몇분 이하로 짧은 access 토큰, 하나는 그에 비해 꽤 길게 보통 2주 정도로 잡혀있는 refresh 토큰을 함께 사용한다

로그인시 서버는 리프레시 토큰의 상응값을 데이터베이스에 저장한다

사용자가 엑세스 토큰이 만료되면 리프레시 토큰을 서버로 보내고, 서버는 값을 대조하여 새로운 엑세스 토큰을 발행한다

리프레시 토큰만 안전하게 관리된다면 엑세스 토큰이 만료되어도 로그인 할 필요없이 클라이언트가 서버에 매번 세션을 요청하지 않고도, 엑세스 토큰을 발급 받아 자체적으로 인증 정보를 관리할 수 있다

하지만, 그사이 액세스 토큰을 탈취당한다면 즉시 무효화시키기 어렵다는 헛점은 존재한다

차이점

  세션 JMT
관리와 보안성 서버에 저장되어 있어 사용자 관리가 용이하다
특정 사용자의 세션을 강제로 만료시키거나, 계정을 차단할 수 있다
토큰 탈취 시 토큰의 유효기간 동안 차단할 방법이 없다
보안이 취약할 수 있다
서버 서버 리소스가 많이 소모된다
요청이 있을 때마다 세션을 관리하기위해 DB나 메모리에 접근해야 한다
사용자 정보를 저장할 필요가 없다
요청마다 DB에 접근하지 않아도 된다
네트워크 트래픽을 줄일 수 있다

장단점이기도 한 차이점을 표를 정리해봤다

세션은 요청이 있을때마다 DB를 탐색해야하고 ,사람이 많으면 DB 또한 더 필요하다

(이를 보완하기 위해 빠르고 저렴한 redis 메모리형 데이터베이스 서버를 많이 쓴다고 한다)

토큰은 DB를 매번 확인하지 않아도 되며 JWT은 공간차지도 안한다

 

참고 자료

https://www.youtube.com/watch?v=tosLBcAX1vk

https://www.youtube.com/watch?v=1QiOXWEbqYQ

https://youtu.be/aU4bju5kB_Q?si=CUpPENp_Px2hMkYf

 

썸네일 글자수 제한으로 s가 빠졌다 (credentials:ture)

 

CORS 설정과 관련해 문제 해결 경험을 기록한다

하나의 프로젝트 레포 안에서 서버 폴더는 Express로 , 클라이언트 폴더는 React와 TypeScript를 사용했다

프로젝트 배포 전에는 postman으로 서버 기능을 테스트했고 npm start 명령어로 클라이언트 화면을 보면서 작업했다

그런데 문제는 클라이언트에서 서버에 요청을 보내면 서버와의 연결이 되지 않는 것이었다

원인은 CORS(Cross-Origin Resource Sharing) 설정이었다

CORS는 간단히 말하면 서로 다른 출처(예: 서로 다른 도메인, 포트) 간의 통신을 허용하거나 제한할 수 있게 해주는 보안 기능이다

기본적으로 출처가 다른 경우에는 쿠키나 인증 관련 헤더(예: Authorization 헤더)를 포함한 요청을 보낼 수 없다

때문에 클라이언트가 서버에 인증 정보를 담아 요청을 보내려면 프론트엔드와 서버 양측에서 CORS 설정을 해야한다

먼저 서버 코드에 이런식으로 추가해야 한다

app.use(
  cors({
    origin: "http://localhost:9000",
    credentials: true,
  })
);
app.use(express.json());

 

origin 옵션에는 작업중인 클라이언트의 URL을 적어주면 된다

(물론 배포후에는 배포한 클라이언트의 URL로 바꿔줘야한다)

여기서 credentials이 나오는데, credentials 옵션은 인증 정보를 포함한 요청에 관한 옵션이다

true로 설정해주면 요청을 허용해 클라이언트에서 서버로 인증 정보를 담아 요청을 보낼 수 있게된다

 

다음으로, 클라이언트 코드는 fetch API로 이렇게 수정했다

export const loginUser = async (username: string, password: string) => {
  const response = await fetch(`${baseURL}/auth/login`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ username, password }),
    credentials: "include",
  });

  if (!response.ok) {
    throw new Error("Failed to login");
  }
  return await response.json();
};

export const logoutUser = async () => {
  const response = await fetch(`${baseURL}/auth/logout`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    credentials: "include",
  });

  if (!response.ok) {
    throw new Error("Failed to logout");
  }
};

 

credentials: "include",로 설정해주면 모든 요청에 인증 정보를 담아간다

이 옵션은 총 3가지 값을 사용할 수 있다

  • same-origin (기본값) : 같은 출처 간 요청에만 인증 정보를 담는다.
  • include : 모든 요청에 인증 정보를 담는다.
  • omit : 모든 요청에 인증 정보를 담지 않는다.

참조 : https://velog.io/@garcon/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-CORS%EC%99%80-credentials

오늘도 이악물고 쓰는 맥북

 

npm ERR! code EACCES

 

파일 또는 디렉토리에 대한 권한이 없다는 뜻이다

주로 -g 글로벌 설치시 나타나는 에러이다

 

해결법

sudo 를 앞에 붙여준다

sudo npm install 설치할 파일 -g

이때 password 를 묻는데, 사용하는 맥의 비밀번호를 입력하면 된다

java runtime could not be located

 

맥으로 컴퓨터를 바꾸고 종종 나타나는 이 메세지...

Get Java Platform (JDK) 를 클릭하면 자바 플랫폼 사이트가 나온다

 

 

대뜸 자바를 설치;

 

 

구글링을 해보자..

 

https://salesforce.stackexchange.com/questions/212840/java-runtime-could-not-be-located-when-starting-vscode-with-the-salesforce-ext

 

"Java runtime could not be located" when starting VSCode with the Salesforce Extensions

When starting VS Code (v1.21.1) with the VS Code extensions installed (v40.4) I'm getting the error message: Java runtime could not be located. Set one using the salesforcedx-vscode-apex.java.ho...

salesforce.stackexchange.com

 

스택오버플로우의 답변에 따르면 자바 런타임을 VS Code가 찾지 못해 생기는 오류인데,

경로를 올바르게 지정하면 오류가 수정되는것 같았다

 

하지만 현재 자바를 사용하지 않아 내 경우엔 별 도움이 되지 않았고

아마도 원인은 이전 윈도우 노트북으로 자바를 설치한적이 있어서

그 실행에 대한 데이터가 남아있어 저러는 듯 하다

 

그래서 자바를 설치하기로 했다

저 사이트에서 설치해도 되지만 나는 VSCode를 사용중이므로

 

Java in vscode 로 구글링하면 나오는 사이트로 들어가

 

https://code.visualstudio.com/docs/languages/java

 

Java in Visual Studio Code

Learn about Visual Studio Code editor features (code completion, debugging, snippets, linting) for Java.

code.visualstudio.com

 

하단을 살펴보면 비주얼 스튜디오의 자바 설치가 보인다

 

 

맥과 윈도우 중 사용하는 운영체제에 맞추어 클릭하고 인스톨하면 설치가 완료된다

 

하단의 익스텐션 또한 상위 운영체제들의 코딩팩에 포함되어 있으며,

 

VSCode부터 한번에 설치가 가능하다 이미 설치되었다면 설치하지 않은 프로그램만 알아서 설치가 된다

 

자바를 제대로 설치해줘서 인지 그 후로는 메세지가 뜨지않는다 :)

모두를 위한 컴퓨터 과학 CS50 데이비드 J. 말란 (David J. Malan)

2. C언어

4) 자료형, 형식 지정자, 연산자

 

변수의 자료형(데이터 타입)들은 어떤 것들이 있을까

 

  • bool : boolean 불리언 표현 ex) True, False, 1, 0, yes, no
  • char : 문자 하나
  • string : 문자열
  • int : 특정 크기 또는 특정 비트까지의 정수 (대략 40억 개)
  • long : 더 큰 크기의 정수
  • float : 부동소수점을 갖는 실수 ex) 3.14
  • double : 부동소수점을 포함한 더 큰 실수

 

이 데이터 타입들 마다 printf 함수에서 사용할 형식 지정자들도 있다

 

  • % c : char
  • % f : float, double
  • % i : int
  • % li : long
  • % s : string

% f는 f 앞에. 원하는 자릿수를 넣어 소수점을 원하는 자리까지 나오게 할 수 있다

 

ex) 물건의 가격을 물어보고 세금을 포함한 값을 계산해 출력하는 코드이다.

부가세가 6.25%, 가격이 100이라고 했을 때 코드는 다음과 같다

 

# include <cs50.h>
# include <stdio.h>

int main(void)
{
    float price = get_float("What's the price?\n");
	printf("Your total is %.2f \n", price*1.0625);
}

 

get_float는 cs50의 함수이다

가격이 얼마인지 물어보고 가격을 받아 price에 저장한다

총액이 실수이므로 float를 사용해 % f를 사용한다

% f로만 계산하게 된다면 값은 105.250000까지 나타내기 때문에

%. 2f로 소수점 2번째 자리까지만 나오게 할 수 있다

 

./float
what's the price?
100
Your total is 106.25

 

이외에도 아래와 같이 다양한 수학 연산자, 논리 연산자, 주석 등이 기호로 정의되어 있다

 

  • +, - : 더하기, 빼기
  • *, / : 곱하기, 나누기
  • % : 나머지
  • && : 그리고
  • || : 또는
  • // : 주석

 

주석은 코드가 어떤 일을 하는지 설명한다

처음 보는 사람도 이해하기 쉽게 잘 설명해 두는 습관이 중요하다

 

5) 사용자 정의 함수, 중첩 루프

 

c언어로 나만의 함수를 만들고 싶다면?

 

사용자 정의 함수를 만드는 법

 

#include <stdio.h>

void cough(void)
{
    printf("cough\n")
}

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        cough();
    }
}

 

void를 입력하고 원하는 함수명을 적고 (void)를 적어준다

그리고 실행될 코드를 작성한다

 

다만 이렇게 했을 때 문제는 함수를 여러 개 만들 경우

main 함수가 밑으로 내려가기 때문에 가독성이 떨어진다

 

그렇다고 main 함수를 무턱대고 위로 올리면 main 함수를 실행할 때

만들어둔 함수는 인식하지 못하기 때문에 오류가 발생하므로 이렇게 하는 것이 좋다

 

#include <stdio.h>

void cough(void);

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        cough();
    }
}

void cough(void)
{
    printf("cough\n");
}

 

void cough(void); 만 위로 올리면

C에게 내가 만든 함수를 인식시켜 속일(?) 수 있다

 

함수를 원하는 횟수만큼 출력하는 법

 

#include <stdio.h>

void cough(int n);

int main(void)
{
    cough(3);
}

void cough(int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("cough\n");
    }
}

 

int n 은 함수에서 int 정수 형식을 갖는 입력값을 받아 변수명 n에 저장한다는 의미이다

 

중첩루프

 

가로가 n개, 세로가 n 개인 "#"을 출력하려면?

 

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int n;

    do
    {
        n = get_int("Size: ");
    }
    while (n < 1);

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            printf("#");
        }
        printf("\n");
    }
}

 

int n으로 정수값을 받는 변수 n을 정의하고,

do {... } while()을 이용해 while()의 조건이 만족할 때까지

get_int cs50 라이브러리 함수로 입력값을 받아 n에 저장한다

 

do while을 사용하면 조건과 상관없이 최소 한 번은 { } 안의 내용을 실행할 수 있다

 

그리고 for 루프를 두 번 중첩하며 # 을 출력하는 데,

첫 번째 루프는 변수 i를 기준으로 n번 반복하고,

그 안의 내부 루프에서 변수 j를 기준으로 n번 반복한다

 

내부 루프에서 #을 출력하고, 내부 루프가 끝날 때마다 줄 바꿈이 실행되어,

최종적으로 가로, 세로가 n 개인 #이 출력된다

 

이렇게 사용자 정의 함수를 사용했을 때의 장점은?

 

  • 모듈화
    반복적으로 작성하지 않아 작업시간을 단축할 수 있어 재사용성을 높인다
    함수 내부의 코드 구조를 이해 못 해도 사용이 가능하다
  • 구조화, 단순화
    main 함수의 길이를 줄여 간결한 코드로 복잡성을 낮추고 가독성을 높인다
    협업(코드리뷰)에 수월해지고 유지보수(수정)하기도 좋다

모두를 위한 컴퓨터 과학 CS50 데이비드 J. 말란 (David J. Malan)

 

앞 파트인 1. 컴퓨팅 사고에서Scratch 스크래치라는 그래픽 프로그래밍 언어를 통해

간단한 알고리즘을 구현하고 원리를 깨우쳤다

텍스트 기반의 프로그래밍 언어를 이용하여 컴퓨터에게 일을 시켜보자

 

2. C언어

1) C기초

 

가장 널리 쓰이는 프로그래밍 언어 중 하나이다

 

#include <stdio.h>

int main(void) {
    printf("Hello World!\n");
}

 

 

{ 중괄호 사이에 앞으로 코드를 작성하여 실행; } 하면 된다

 

스크래치에서 say 함수로 쓰이던 부분은 printf 함수로 사용한다

\n 은 줄 바꿈이다

 

#include <stdio.h>는 stdio.h 라이브러리를 사용함을 뜻한다

stdio.h 는 C언어의 표준 라이브러리 (Standard Input/Output library)라고 한다

이 코드에서 printf 함수를 사용할 수 있게 해 준다

 

코드를 작성했으면 "파일명. c"이렇게 확장자명을 C로 저장한다

 

이렇게 작성한 코드는 "소스 코드 Source code"라 불린다

컴퓨터에게 코드를 실행시키려면 컴퓨터가 이해할 수 있는 언어로 변환시켜야 한다

2진수로 변환된 코드는 "머신 코드 Machine code"라 한다

 

변환은 누가?

컴파일러 Compiler라는 프로그램이 수행한다

 

컴파일은 어떻게?

 

clang 파일명.c

 

clang 컴파일러로 파일명. c라는 코드를 컴파일하는 명령어이다

 

2) 문자열

 

string answer = get_string("what's your favorite animals?");

프로그래밍 언어에서 = 은 오른쪽에서 왼쪽으로 가는 화살표와 같이

오른쪽에 있는 것을 왼쪽에 지정하는 할당 연산자라고 한다

 

answer는 변수명이며 C언어에서 중요한 점은 변수가 저장할 오른쪽 데이터 종류를 정확하게 명시해야 한다는 점이다

 

<cs50.h> 라이브러리에 있는 함수를 활용해 스크래치의 ask 함수와 같은 문자열을 받는 get_string을 사용했다

string 을 바로 형식지정자 라고 한다

 

 printf("hello, %s\n", answer);

 

printf 함수로 출력할 때 변수 answer에 저장된 데이터 값을 사용하고 싶다면

answer 앞에 변수임을 나타내기 위한 % 를 붙여줘야 하고,

마찬가지로 어떤 종류의 인자인지 알려주기 위해 sting의s를 % 뒤에 붙여준다

 

상위 예시의 get_string 함수는 cs50 라이브러리에서 사용할 수 있고,

cs50.h 파일이 포함되어야 컴파일이 가능하다

 

이 파일명이 string이라고 가정했을 때 컴파일 명령어는

 

clang -o string string.c -lcs50

 

-o는 string.c 를 string.out이라는 머신코드로 저장할 수 있게 하는 명령어이고,

-lcs50에서 l은 link의 의미를 가진 인자이다

이를 통해 컴파일 시 cs50 파일을 연결하여 진행이 가능하다

 

이러한 복잡한 명령어보다 간단한 명령어로는 make 가 있다

 

make string

 

3) 조건문과 루프

 

counter라는 변수에 숫자를 저장하고 싶을 때는?

 

int counter = 0;

 

int는 변수가 정수 integer 임을 알려주고,

counter라는 이름의 변수에 0 값을 저장(초기화)한다

 

변수의 값을 1씩 증가시키고 싶을 때는?

 

counter = counter + 1;

 

counter에 1을 더한 값을 다시 counter에 저장(할당)한다는 의미이다

 

좀 더 간결한 표현도 가능하다

 

counter += 1;
counter++;

 

조건문을 만들고 싶을 때는?

 

if (x < y)
{
	printf("x is less than y\n");
}

 

if (괄호 안에 검사하고자 하는 조건을 입력한다)

{

 안에 조건을 만족할 때 수행하고자 하는 작업을 입력한다

}

 

else를 이용해 위의 조건이 만족하지 않을 경우의 조건을 추가할 수 있다

 

if (x < y)
{
	printf("x is less than y\n");
}
else
{
	printf("x is not less than y\n");
}

 

조건을 더 추가하려면 else if를 통해 나타낼 수 있다

 

if (x < y)
{
	printf("x is less than y\n");
}
else if (x > y)
{
	printf("x is not less than y\n");
}
else if (x == y)
{
	printf("x is equal to y\n");
}

 

하단의 == 는 = 표시가 이미 할당연산자로 지정되어 있어,

같다는 것을 표현하기 위해 사용하는 일치 연산자이다

 

위의 예시에서는 사실 (x == y)라는 조건을 명시하지 않아도 되므로

 

if (x < y)
{
	printf("x is less than y\n");
}
else if (x > y)
{
	printf("x is not less than y\n");
}
else
{
	printf("x is equal to y\n");
}

 

이렇게 좀 더 간결한 코드로 만들 수 있다

 

반복문(루프)을(를) 만들고 싶을 때는?

 

while (true)
{
	printf("hello, world\n");
}

 

while (괄호 안에 조건을 입력한다)

{

 안에 수행할 작업을 입력한다

}

 

루프를 구현하고 싶다면 괄호 안의 조건이 네 yes, 참 true, 1 이 나오면 된다

 

예시처럼 true를 적게 되면 while 루프가 영원히 수행된다

 

특정 횟수만큼 작업을 수행하고 싶다면?

 

int i = 0;
while (i < 50)
{
	printf("hello, world\n");
	i = i +1;
}

 

정수 i를 선언하고 값을 0으로 할당했다

 

while 문이 돌면서

 

i는 0으로 설정 -> i는 50보다 작은가? -> 작다 -> hello world를 출력한다 -> i를 1 증가시킨다 -> i가 50보다 작은가?-> (반복) -> i가 50보다 작은가? -> 작지 않다 -> 종료

 

순으로 진행된다

 

for 문을 사용하면 위 예시처럼 따로 변수를 선언하지 않고

 

for (int i = 0; i < 50; i= i+1)
{
	printf("hello, world\n");
}

 

for (변수 초기화; 변수 조건; 변수 증가)

 

이렇게 while문에 비해 간단한 표현이 가능하다

CS50으로 C언어를 처음 접하는 나로서는 처음 헤맸던 부분들 중 하나가

 

바로 첫 줄의 #include <stdio.h>였다

첫 줄부터 자꾸 오류가 뜨니 난감하기 그지없었는데,

 

includePath오류는 구글링 하면 나오는 방식대로 따라 하면

오류가 뜨지 않는데 <cs50.h>은 여전히 찾지 못하더라

 

왜냐!?

CS50 Sandbox 샌드박스가 아닌 VSCode 비주얼스튜디오 코드에서 실습을 했기 때문

 

CS50 공식 홈페이지에 들어가 보면

따로 CS50 라이브러리를 작업하는 폴더에 설치해 주면 된다고 한다

 

나는 맥 유저라 하위 내용 그대로 따라 하였다

From Source (Linux and Mac)

Download the latest release from https://github.com/cs50/libcs50/releases

  1. Extract libcs50-*.*
  2. cd libcs50-*
  3. sudo make install

 

1번 링크에서 소스 코드 폴더를 다운로드한다

 

 

다운로드한 폴더를 압축 풀고 작업하는 폴더에 넣어준다

 

터미널에서 해당 폴더 위치인지 확인 후

 

sudo make install

 

명령어를 입력하면 설치가 완료된다

 

 

이제 원활하게 C언어를 실습할 수 있다!

모두를 위한 컴퓨터 과학 CS50 데이비드 J. 말란 (David J. Malan)

C언어로 1 나누기 10을 했을 때, 소수점 값은?

#include <cs50.h>
#include <stdio.h>

int main (void)
{
  float x = get_float("x: ");
  float y = get_float("y: ");

  printf("x / y =%f\n", x / y);
}

 

C 언어의 float를 활용해 x를 y로 나눠보자

 

 

x: 1
y: 10
x / y =0.100000

 

우리가 알고 있듯 값은 0.1이다

뒤에 있는 0000... 들은 필요가 없으므로 깔끔하게 보이게 하려면

 

#include <cs50.h>
#include <stdio.h>

int main (void)
{
  float x = get_float("x: ");
  float y = get_float("y: ");

  printf("x / y =%.1f\n", x / y);
}

 

f 앞에. 1을 입력해 주면 된다

 

x: 1
y: 10
x / y =0.1

 

그럼 이렇게 깔끔하게 출력된다

 

그런데 말입니다, 소수점을 50자리까지 보이게 하면 어떨까요?

 

#include <cs50.h>
#include <stdio.h>

int main (void)
{
  float x = get_float("x: ");
  float y = get_float("y: ");

  printf("x / y =%.50f\n", x / y);
}

 

. 50으로 코드를 수정했다

결과는?!

 

x: 1
y: 10
x / y =0.10000000149011611938476562500000000000000000000000

 

으잉? 50자리까지는 출력되는데 중간 숫자가 이상하다

왜 그럴까?

 

float에서 저장가능한 비트의 수가 32비트로 유한하기 때문이다

( double 은 64비트를 사용한다.

고로, double을 사용하면 좀 더 정확하게 계산할 수 있다 )

 

컴퓨터의 저장 공간(메모리)에는 한계가 있고 특정 지점 뒤에는 한계에 부딪혀

결국 저장할 수 있는 값들 중 1 / 10에 가까운 값을 저장하게 된다

 

정수 오버플로우

비슷한 오류로, 1부터 시작해 2를 계속해서 곱하는 코드를 실행했을 때

 

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    for (int i = 1; ; i *= 2)
    {
        printf("%i\n", i);
        sleep(1);
    }
}
...
1073741824
overflow.c:6:25: runtime error: signed integer overflow: 1073741824 * 2 cannot be represented in type 'int'
-2147483648
0
0
...

 

int 타입이 저장할 수 있는 32비트의 크기를 넘은 이후에는 더 이상 넘어갈 1의 자리가 없기 때문에

그 이상의 숫자를 저장하지 못하고 에러와 함께 0이 출력된다

 

실생활에서 발견되었던 오버플로우 문제는 Y2K, 보잉 787 사례가 있다

1999년에 큰 이슈가 되었던 Y2K 문제는 연도를 마지막 두 자리수로 저장했던 관습 때문에 새해가 오면 ‘99’에서 ‘00’으로 정수 오버플로우가 발생하고, 새해가 2000년이 아닌 1900년으로 인식된다는 문제였습니다.
그리고 세계는 수백만 달러를 투자해서 프로그래머들에게 더 많은 메모리를 활용해서 이를 해결하도록 하였습니다.
이는 통찰력 부족으로 발생한 아주 현실적이고 값비싼 문제였습니다.
또한 다른 사례로 비행기 보잉 787에서 구동 후 248일이 지나면 모든 전력을 잃는 문제가 있었습니다.
왜냐하면 강제로 안전 모드로 진입하였기 때문입니다.
이는 소프트웨어의 변수가 248일이 지난 뒤에 오버플로우가되어 발생하였기 때문이었습니다.
248일을 1/100초로 계산하면 대략 2의 32제곱이 나옵니다.
보잉을 설계할때 사용한 변수보다 너무 커졌던 것입니다.
이를 해결하기 위해 주기적으로 재가동을 하여 변수를 다시 0으로 리셋했습니다. 

 

따라서 다루고자 하는 데이터 값의 범위를 유의하며 프로그램을 작성하는 것이 중요하다

1. 컴퓨팅 사고 computational Thinking, Scratch

1) 2진법

컴퓨터 과학문제 해결에 대한 학문이다

문제해결입력(input)을 전달받아 출력(output)을 만들어내는 과정이다

그 중간 과정이 컴퓨터 과학이다

 

입력과 출력을 표현하기 위해선 모두가 동의한 약속(표준)이 필요하다

 

2진법

0,1,2,3,4,5,6,7,8,9,10 총 10개의 기호로 표현하는 방법은 10진법

하지만 컴퓨터는 오직 0과 1로만 데이터를 표현하는 2진법을 사용한다

 

전기를 통해 연산하는, 즉 전기를 켜고 끄는 방식으로 작동하는 컴퓨터에게 적합한 방법이다

컴퓨터 안에는 많은 스위치(트랜지스터)가 있고 on/off 상태를 통해 0과 1을 표현한다

 

2진법에서 하나의 자릿수를 표현하는 단위를 비트(bit)라고 한다

 

비트 Bit

이진 숫자라는 뜻의 binary digit의 줄임말이다

0과 1, 두 가지 값만 가질 수 있는 측정 단위이다

컴퓨터 내부에서 물리적으로 표현하자면 켜고 끌 수 있는 스위치라고 생각할 수 있다 (켜기=1, 끄기=0)

디지털 데이터를 여러 비트들로 나타냄으로써 두 가지 값만을 가지고도 많은 양의 정보를 저장할 수 있다

또한 저장되어 있는 데이터를 수정하기 위해 비트에 수학적 연산을 수행할 수 있다

 

비트열

비트 한 개로는 많은 양의 데이터를 나타내기에 턱없이 부족하므로 여러 숫자 조합을 컴퓨터에 나타내기 위해 비트열을 사용한다

바이트(byte)여덟 개의 비트가 모여 만들어진 것이고 2^8 = 256 개의 서로 다른 바이트가 존재할 수 있다

바이트가 모이면 더 큰 단위가 될 수 있다
(비트 bit > 바이트 byte > 킬로바이트 KB > 메가바이트 MB > 기가바이트 GB > 테라바이트 TB)

출처: 부스트코드 모두를 위한 컴퓨터 과학 CS50

 

2) 정보의 표현

문자의 표현

 

문자를 숫자로 표현 할 수 있는 약속(표준) 중 하나는 설명미국정보교환표준부호

ASCII (아스키코드/American Standard Code For Information Interchange)이다

총 128개의 부호로 정의되어 있다

출처: 부스트코드 모두를 위한 컴퓨터 과학 CS50

ex) A를 2진법으로 표현하려면

  1. 아스키코드를 참고하여 A를 10진법으로 표현하면 65이다
  2. 2^5x1 + 2^5x0 + 2^4x0 + 2^3x0 2^2x0 + 2x0 + 1x1 (64+1)
  3. 2진법으로 표현하면 1000001 

 

이 외에도 Unicode 유니코드로 더 많은 비트를 사용해 다양한 문자들도 표현가능하다

 

😂(기쁨의 눈물)과

스마트폰으로 이모티콘을 보내면 안드로이드 혹은 IOS는 0과 1의 패턴을 받아 노란 얼굴에 눈물을 흘리는 사진으로 보여준다

 

그림, 영상, 음악의 표현

 

문자와 마찬가지로 그림도 숫자로 표현할 수 있다

스크린의 그림을 자세히 보면 수많은 작은 점들이 빨간색, 초록색, 파란색을 띠고 있는데

이러한 작은 점을 픽셀 Pixel이라고 한다

 

픽셀은 세 가지 색을 서로 다른 비율로 조합해 특정한 색을 나타낸다

 

ex) 빨간색 72 , 초록색 72 , 파란색 33 = 노란색

 

위의 숫자들을 표현하는 방식을 RGB (Red, Green, Blue)라고 한다

 

영상 또한 수많은 그림을 빠르게 연속적으로 이어 붙여놓은 것이기 때문에 숫자로 표현이 가능하다

음악도 마찬가지로 각 음표를 숫자로 표현할 수 있다

 

3) 알고리즘

알고리즘 Algorithms

입력 input에서 받은 자료를 출력 output 형태로 만드는 처리과정

입력값을 출력값의 형태로 바꾸기 위해 어떤 명령들이 수행되어야 하는지에 대한 규칙들의 순서적 나열이다

알고리즘을 평가할 때는 정확성도 중요하지만 효율성도 중요하다

효율성은 작업을 완료하기까지 시간과 노력이 얼마나 덜 들이는지에 대한 것이다

 

의사코드 Pseudocode

컴퓨터가 수행해야 할 행동이나 조건의 절차를 명료하게 정리한 것

 

함수 Function

조건

불리언 Boolean

값(답)이 예 Yes, 아니오 No, 참 True, 거짓 False 2진법에선 0 또는 1로 나온다

루프 Loop (반복)

3번째 라인코드로 돌아가라는 반복

 

https://youtu.be/6hfOvs8pY1k

 

 

비전공자와 전공자의 차이정말 단순하게 따져보자면 전공한 수업이 다르다는 것

그렇다면 비전공자들도 전부는 아니더라도 똑같이 대학교 강의를 수강하면 되는것 아닌가?

찾아보고 내가 공부할 사이트들만 찝어왔다 (전부 무료)

 

부스트코스

네이버 커넥트재단에서 기획하고 운영하는 사이트이다

 

모두를 위한 컴퓨터 과학 (CS50 2019)

https://www.boostcourse.org/cs112

 

모두를 위한 컴퓨터 과학 (CS50 2019)

부스트코스 무료 강의

www.boostcourse.org

하버드대학의 최고 인기강좌, 데이비드 말란 교수님의 CS50입니다.
프로그래밍을 처음 공부하는 비전공자 분들도 쉽고 재미있게 학습하실 수 있습니다.-출처: 강의 상세 페이지

여기서 내가 수강할 강의는 무려 하버드대 강의이다

1강 들어본 바로는 정말 재밌고 현장감이 느껴지며 말이 무척 빠르시다

부스트코스 사이트에서 영상 하단에 강의 내용도 잘 정리 해줘 공부하기 좋은 것 같다

 

KOCW (Korea OpenCourseWare)

대학 공개 강의 서비스이다

고등교육 교수학습자료 공동활용 체제, KOCW(Korea OpenCourseWare)

KOCW는 국내.외 대학 및 기관에서 자발적으로 공개한 강의 동영상, 강의자료를 무료로 제공하는 서비스로, 대학생, 교수자는 물론 배움을 필요로 하는 누구든지 언제 어디서나 이용 가능합니다.-출처: KOCW 소개 페이지

여기서 소프트웨어 교육은 하위 링크에 있다

http://www.kocw.net/home/special/themeCourses.do#subject/04

 

KOCW - 테마

이전 다음

www.kocw.net

카테고리가 다양하니 골라 들으면 된다

 

K-MOOC (Massive, Open, Online, Course)

무크(MOOC)란 Massive, Open, Online, Course의 줄임말로 오픈형 온라인 학습 과정을 뜻합니다.
이 것은 강의실에 수용된 학생만이 강의를 들을 수 있었던 것에서 청강만 가능한 온라인 학습동영상으로 변화하고
현재는 질의응답, 토론, 퀴즈, 과제 제출 등 양방향 학습을 할 수 있는 모습으로 완성되었습니다.

이 사이트를 추천하는 블로그는 많은데, 솔직히 강의의 종류가 많지 않아서 가장 아쉬운 사이트이다

공학, 컴퓨터.통신, 이공계 기초과학 카테고리는 하위 링크이다

http://www.kmooc.kr/courses#

 

분야별 강좌 | K-MOOC

 

www.kmooc.kr

취지는 좋으나 강의가 많지 않음 (오른쪽에서 갯수 확인 가능)

+ Recent posts