반응형

흔히 객체 하면 다른 언어를 생각할 때 클래스를 떠오르기 쉽습니다.

하지만 javascript에서는 var 타입 이외에는 모두 객체 입니다. (js에서는 class 선언 없습니다.)

기본적인 예시들을 보고 JS의 객체 개념을 익히도록 하겠습니다.


객체 리터럴을 이용한 객체 생성 개념

var person = { name: "jun", age: "29"}

{...}을 객체 리터럴이라 하며 변수 people의 대입 하는 작업입니다.

내부의 데이터 각각을 하나의 프로퍼티(이름/키) 라고 부릅니다.

그럼 이제 하나의 객체가 선언 되었습니다.


person.hobby = "cook";

console.log(person.hobby);

delete person.hobby;


프로퍼티를 자유롭게 추가하고 지울 수 있습니다.


var person2 = person;

person2는 person 객체를 참조하게 됩니다.


함수 리터럴

함수도 객체리터럴과 같이 함수 리터럴로 정의를 할 수 있습니다.


var add_func = function(param) {return x+y}

위와 같은 선언어를 하면 add_func를 함수로 사용 할 수 있습니다.



객체 메서드

var cal = {

value: {x:3, y:5}

add: function() {

return x+y

}

}


cal.add()

객체 안에 메서드를 선언하고 이와 깉이 호출 할 수도 있습니다.

또한 객체 메서드를 추가 할 수도 있습니다.

cal.change_value= function(x, y) {

this.value.x = x;

this.value.y = y;

}


생성자로 객체 생성 개념

function Person(name, age) {

this.name = name;

this.age = age;

}


var person = new Person("jun", "29");

console.log(person);

자바스크립트는 생성자인 함수를 이용하여 new 연산자로 객체를 생성합니다.

(클래스 개념은 없으나 최근에 JS 문법은 다시 한번 살펴 봐야겠습니다.)


위의 내용은 다른 언어처럼 클래스 선언 없이 객체를 만들기 때문에 조금 생소 할 수 있습니다.

계속 보고 익숙 해지도록 해야겠습니다.

반응형
반응형



파트6에서는 스타일과 이미지를 더하는 방법을 배우게 됩니다.

웹 어플리케이션에서 웹페이지를 보여주기 위해서는 이미지, 자바스크립트 그리고 css와 같은 추가적인 파일들이 필요합니다. 이러한 파일들을 static file이라고 합니다. 작은 프로젝트에서는 static files을 웹서버 어딘가에 두어도 되기 때문에 큰 문제가 아닙니다. 하지만 큰 프로젝트에서는 static file을 각각의 어플리케이션에 잘 다룰 수 있도록 관리 해야겠습니다.


STATICFILES_FINDERS 세팅을 보게 되면 다양한 소스로 부터 static files을 찾을 수 있게 리스트를 관리 합니다.

static 디렉토리 안에는 다른 디렉토리들을 만들 수있습니다.

예) polls/static/polls/styles.css


polls/static/polls/style.css

li a {
    color: green;
}


polls/templates/polls/index.html

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">

{% static %} 템플릿 태그는 static files의 절대 url을 발생시킵니다.

반응형
반응형


파트 5에서는 장고의 테스트 작성에 대해서 소개를 해줍니다.

장고뿐만 아니라 모든 소프트웨어 작성 시 테스트케이스 작성은 필수 입니다.

테스트는 코드 동작을 위한 간단한 루틴입니다. 

함수의 대한 리턴 값이 기대 되어지는 값이 리턴이 되는지? 사용자 입력값의 따른 시퀀스가 제대로 만들어지는가? 이러한 테스트 케이스들을 작성하여 쉘에서 명령어 하나로 테스트를 자동적으로 진행합니다.

테스트 케이스를 한번 작성 해놓으면 코드 수정 이후에도 원래 의도대로 코드가 동작하는지를 손쉽게 테스트 할 수 있습니다.


테스트가 필요한 이유 4가지

1. 테스트는 당신의 시간을 절약해줍니다.

2. 문제들을 미리 방지 합니다.

3. 당신의 코드를 더욱 매력적으로 만들어 줍니다.

4. 팀 작업을 돕습니다.


테스트 케이스를 작성해봅시다.

polls/test.py

import datetime

from django.test import TestCase
from django.utils import timezone

from .models import Question


class QuestionModelTests(TestCase):

    def test_was_published_recently_with_future_question(self):
        """
        was_published_recently() returns False for questions whose pub_date
        is in the future.
        """
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)


django.test.TestCase의 서브클래스로 만들어 줍니다.

우리가 의도한 값은 최근 발행 게시물인 경우가 True가 나와야지 30일을 더한 미래 값을 만들어 주면 False가 나오길 원합니다.

원하는 값이 False 값이 나와야되는데 True값이 나오면 테스트 Fail이 발생합니다.


테스트 실행

python manage.py test polls

테스트가 실패 하였습니다.

아래와 같이 함수를 수정하고 테스를 실행하면 성공 할 것입니다.


polls/models.py

def was_published_recently(self):
    now = timezone.now()
    return now - datetime.timedelta(days=1) <= self.pub_date <= now


테스트케이스는 많이 작성해도 부족합니다.

아래와 같이 was_published_recently()에 대한 테스트 케이스를 작성해 봅시다.

def test_was_published_recently_with_old_question(self):
    """
    was_published_recently() returns False for questions whose pub_date
    is older than 1 day.
    """
    time = timezone.now() - datetime.timedelta(days=1, seconds=1)
    old_question = Question(pub_date=time)
    self.assertIs(old_question.was_published_recently(), False)

def test_was_published_recently_with_recent_question(self):
    """
    was_published_recently() returns True for questions whose pub_date
    is within the last day.
    """
    time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
    recent_question = Question(pub_date=time)
    self.assertIs(recent_question.was_published_recently(), True)


뷰 테스트 작성해보기.

유틸기능을 보이는 함수 이외에도 뷰도 테스를 진행 할 수 있습니다.

이전에는 미래 날짜의 게시물은 보이면 안되는데 보이게 되는 문제가 발생 하고 있습니다.


수정을 필요로 합니다.

polls/views.py

def get_queryset(self):
    """
    Return the last five published questions (not including those set to be
    published in the future).
    """
    return Question.objects.filter(
        pub_date__lte=timezone.now()
    ).order_by('-pub_date')[:5]

필터를 사용하여 현재 시간 보다 작은 질문들을 가져 옵니다.


뷰에 대한 테스트 케이스를 추가 해줍니다.

polls/test.py

from django.urls import reverse
.....

def create_question(question_text, days):
    """
    Create a question with the given `question_text` and published the
    given number of `days` offset to now (negative for questions published
    in the past, positive for questions that have yet to be published).
    """
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)


class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        """
        If no questions exist, an appropriate message is displayed.
        """
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_past_question(self):
        """
        Questions with a pub_date in the past are displayed on the
        index page.
        """
        create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            ['']
        )

    def test_future_question(self):
        """
        Questions with a pub_date in the future aren't displayed on
        the index page.
        """
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_future_question_and_past_question(self):
        """
        Even if both past and future questions exist, only past questions
        are displayed.
        """
        create_question(question_text="Past question.", days=-30)
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            ['']
        )

    def test_two_past_questions(self):
        """
        The questions index page may display multiple questions.
        """
        create_question(question_text="Past question 1.", days=-30)
        create_question(question_text="Past question 2.", days=-5)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            ['', '']
        )

test_no_questions : No polls are available. 값을 확인 합니다.

test_past_question : 질문들이 리스트에 나오는지 확인합니다.

test_future_question : 미래질문을 만들고 값이 나오면 안되는 것을 확인합니다.


DetailView 테스트 하기.

polls/views.py

class DetailView(generic.DetailView):
    ...
    def get_queryset(self):
        """
        Excludes any questions that aren't published yet.
        """
        return Question.objects.filter(pub_date__lte=timezone.now())

polls/tests.py

class QuestionDetailViewTests(TestCase):
    def test_future_question(self):
        """
        The detail view of a question with a pub_date in the future
        returns a 404 not found.
        """
        future_question = create_question(question_text='Future question.', days=5)
        url = reverse('polls:detail', args=(future_question.id,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

    def test_past_question(self):
        """
        The detail view of a question with a pub_date in the past
        displays the question's text.
        """
        past_question = create_question(question_text='Past Question.', days=-5)
        url = reverse('polls:detail', args=(past_question.id,))
        response = self.client.get(url)
        self.assertContains(response, past_question.question_text)

이외에도 여러 경우에 대해서 테스트를 작성 해야겠습니다.



테스트 작성은 많이 할 수록 더욱 좋다.


테스트 작성 시 아래 3가지를 명심하자.

- 각각의 모델 및 뷰를 기준으로 테스트 클래스의 분리

- 당신이 원하는 테스트의 상태 값을 위해서 테스트 함수의 분리

- 함수 설명을 위한 테스트 함수 이름


튜토리얼 습득 뿐만 아니라 배울점

1. 테스트 케이스 작성 (test-driven development)

2. TDD

3. pytest

반응형
반응형

컴퓨터가 전원이 켜질 때 BIOS에서 각종 하드웨어의 상태를 체크하고 BIOS의 마지막 임무는 부팅에 사용되는 디스크의 512바이트를 램으로 읽어서 실행합니다. 512바이트 영역을 MBR영역이라고 불리며 BIOS는 롬에 새겨져 있습니다. 이런 과정을 부트스트랩이라고 합니다.
이번 과정에서는 위에서 설명한 512바이트를 만들어 보는 과정을 갖게 됩니다. 512바이트만 만들어도 부팅이 되어 화면에 무언가 문자를 적거나 화면의 색깍을 변경 할 수 있습니다.


바이오스는 MBR을 읽어들여 램의 0x7C00번지에 복사 후 점프합니다. 그렇기 때문에 처음 소스를 작성할 때 0x7C00 부분부터 시작한다는 것을 인지 하셔야 겠습니다.


[org 0]
[bits 16]
jmp 0x07c0:start				; offset is start:

start:
	mov ax, cs				; 0x07c0 in cs
	mov ds, ax

	mov ax, 0xB800
	mov es, ax
	mov di, 0
	mov ax, word [msgBack]			; [DS:msgBack] / ax = msgBack value
	mov cx, 0x7FF

org 0은 offset을 얼마나 줄지 결정 하는 값입니다.

위에서 설명한 내용과 같이 0x7C00 부분부터 시작하니 jmp명령어를 통해서 0x7C00 이동 및 start offset부분으로 이동하여 소스를 실행합니다.


0x07c0:start --> 0x7c00+0x5 = 0x7c05 부분으로 이동

jmp 0x07c0:start 구문 실행 시 0x07c0은 코드 세그먼트(cs)에 offset인 start의 값은 프로그램 카운터(ip)에 저장됩니다.


start: 레이블

현재 cs에는 0x07c0의 값이 들어 있고 데이터 세그먼트(ds)에도 같은 값으로 초기화 시켜줍니다. 이유는 word[msgBack] 부분의 암묵적으로 [DS:msgBack]와 같이 선언 되기 때문에 cs와 ds의 값을 같게 만들어 줘서 제대로 된 값(msgBack에 위치한 값)을 갖고 오도록 해줘야 됩니다.


es에 0xB800 값을 넣는데 이 값이 어디서 나온 것이냐면 pc의 메모리 맵을 확인하면 알 수 있습니다.

0xB800:0000 ~ 0xB800:FFFF 값 까지는 컬러텍스트 모드 비디오 메모리 부분입니다.

이 메모리 위치의 값을 변경하여 화면에 컬러 텍스트를 변경 할 수 있습니다. 그렇기 때문에 이 비디오 메모리 부분의 값을 es에 저장해놓고 차례차례 값을 넣어 화면의 색과 텍스트를 변경 할 것입니다.


word [msgBack]에는 2바이트로 각각 1바이트씩 '.', 0x67 값이 각각 들어 있습니다. (전체 소스 확인)

ax 값(위의 값 대입 용도)과 cx 값(0x7FF 값 만큼 for문 용도)을 초기화 해줍니다.


paint:
	mov word [es:di], ax			; [0XB800:0] = ax
	add di, 2
	dec cx
	jnz paint				; zero flag check

paint: 레이블

1. word [es:di] ( [0xB800:0] )에 가리는 위치에 ax('.', 0x67) 값을 입력 해줍니다.

2. di를 2바이트 만큼 증가 시켜줍니다.

3. cx의 값을 1 줄입니다.

4. cx의 값이 0이 아니라면 paint:  레이블로 점프 합니다.

4-1. cx의 값이 0이라면 내려 갑니다.


위아 같이 for문이 다 돌고 나면 아래 소스에는 값을 1바이트씩 각각 입력해줍니다.


	mov edi, 0				; Video memory format is 2Byte
	mov byte [es:edi], 'A'			; [0XB800:0] = 'A' <- ascii value
	inc edi
	mov byte [es:edi], 0x06			; [0XB800:1] = 0x06 <- 0000(bg color is black ) / 0110(letter color is brown)
	inc edi
	mov byte [es:edi], 'B'
	inc edi
	mov byte [es:edi], 0x06
	inc edi
	mov byte [es:edi], 'C'
	inc edi
	mov byte [es:edi], 0x06
	inc edi
	mov byte [es:edi], '1'
	inc edi
	mov byte [es:edi], 0x06
	inc edi
	mov byte [es:edi], '2'
	inc edi
	mov byte [es:edi], 0x06
	inc edi
	mov byte [es:edi], '3'
	inc edi
	mov byte [es:edi], 0x06

	jmp $

jmp $ 명령어는 무한루프를 뜻합니다.


msgBack db '.', 0x67				; letter('.'), color(bg-brown / letter-white)

times 510-($-$$) db 0
dw 0xAA55					; MBR check

마지막으로 현재 위치 부터 509번지까지 0으로 채우고 510번지 0x55, 511번지에는 0xAA 값을 넣어줍니다.

이 작업은 바이오스가 510, 511번지를 0xAA55 값이 있는지를 확인 하고 있다면 MBR을 확인하는 작업입니다.


실행모습

아직 OS의 기능이 있지는 않으나 부팅이 되는 모습 확인 가능


전체 소스

반응형
반응형

#3 파트에서는 현재 사용중인 css 를 넘어 진보적이고 프로그래밍 언어로써 사용을 하기 위한 과정들을 보여주십니다.

PostCSS를 사용하면 css를 우아하게 그리고 숙달된다면 편하게 사용 할 수 있습니다.

하지만 PostCSS는 현재 사용중인 웹브라우저에서는 호환이 안 될 수도 있어 사용에 주의를 하셔야 됩니다.


설치

npm install postcss-preset-env

package.json 추가 내용

"postcss": {

"plugins": {

"postcss-preset-env": {

"stage": 0

}

}

}

참고사이트



이론 부분은 모두 들었습니다.

이제는 강의 내용 기반으로 연습만이 필요로 하겠습니다.

반응형

+ Recent posts