먼저 Question 모델에 voter(추천인) 속성을 추가해 보자.

하나의 질문에 여러명이 추천할 수 있고 한명이 여러 개의 질문에 추천할 수 있으므로 다대다, N:N 관계를 의미하는 ManytoManyField 를 사용해야 한다.

projects\mysite\pybo\models.py 파일을 다음과 같이 수정하자.

voter 를 ManytoManyField 관계로 추가했다. 모델을 변경했기 때문에 makrmigrations, migrate 를 해야한다. 

하지만 makemigrations 를 하면 오류가 발생한다. Question 모델에서 사용한 author와 voter 모두 User 모델과 연결되어 있기 때문에 User.question_set 처럼 User 모델을 통해서 Question 데이터에 접근하려고 할 때 author를 기준으로 할지 voter 를 기준으로 해야 할 지 명확하지 않다는 오류이다. 오류의 HINT 에서도 알 수 있듯이 related_name 인수를 추가하여 해결할 수 있다.

projects\mysite\pybbo\models.py 를 수정하자.

author 에는 related_name='author_question' 라는 인수를 지정하고 voter 에는 related_name='voter_question' 라는 인수를 지정했다. 이렇게 하면 특정 사용자가 작성한 질문을 얻기 위해서는 some_user.author_question.all() 처럼 사용할 수 있다. 마찬가지로 특정 사용자가 추천한 질문을 얻기 위해서는 some_user.voter_question.all() 처럼 사용할 수 있다. some_user 는 특정 사용자를 의미한다. 

Answer 모델에도 voter 속성을 다음처럼 추가하자.

projects\mysite\pybo\models.py 를 수정하자.

Answre 모델에도 author, voter 속성에 related_name 인수를 추가했다. 다시 makemigrates 와 migrate 를 실행하자.

오류없이 잘 실행된다.

 

[질문 추천]

 

이제 질문 추천 기능을 만들어보자.

projects\mysite\templates\pybo\question_detail.html 를 수정하자.

질문의 추천 버튼을 질문의 수정 버튼 좌측에 추가했다. 그리고 버튼에는 추천수도 함께 보이도록 했다. 추천 버튼을 클릭하면 href의 속성이 javascript:void(0) 으로 되어 있기 때문에 아무런 동작도 하지 않는다. 하지만 class 속성에 recommend 를 추가하여 자바스크립트로 data-uri 에 정의된 URL이 호출되게 할 것이다. 이와 같은 방법을 사용하는 이유는 추천 버튼을 눌렀을때 확인창을 통해 사용자의 확인을 구하기 위함이다.

그 확인창을 만들어 보자.

projcets\mysite\templates\pybo\question_detail.html 을 수정하자.

오타가 안나게 잘 따라 작성하자

추천 버튼에 class="recommend" 가 적용되어 있으므로 recommend 라는 이름을 가진 클래스가 있으면 명령문이 실행되어 '정말로 추천하시겠습니까?' 라는 확인창이 나오고 확인을 누르면 data-uri 속성에 정의한 URL 이 호출된다.

question_detail.html 에 적은것 처럼 {% url 'pybo:question_vote' question.id %} URL이 추가되었으므로 pybo/urls.py 에 다음처럼 URL매핑 규칙을 추가해야 한다.

projects\mysite\pyob\urls.py 를 수정하자.

그리고 URL 매핑에 의해 실행되는 question_vote 함수도 작성해줘야 한다.

projects\mysite\pybo\views\question_views.py 에 다음과 같이 작성하자.

작성한 것을 보면 알 수 있듯이 로그인한 사용자와 추천하려는 질문의 글쓴이가 같은 유저일 경우 추천할 수 없게 했다. Question 모델의 voter 는 여러사람을 추가할 수 있는 ManyToManyField 이므로 question.voter.add(request.user) 처럼 add 함수를 사용하여 추천인을 추가한다. 동일한 사용자가 동일한 질문을 여러번 추천해도 추천수가 증가하지 않는다. 오류도 발생하지 않는다. 이는 ManyToManyField 내부에서 자체적으로 처리된다. 서버를 재시작해서 테스트를 해보자. 잘 작동되는지 확인하자.

 

[답변 추천]

 

답변 추천도 질문 추천과 동일하다. 먼저

projects\mysite\templates\pybo\question_detail.html 을 작성하자.

{% url 'pybbo:answer_vote' answer.id %} 이 추가 되어 URL 매핑규칙을 추가하자.

projects\mysite\pybo\urls.py 를 수정하자.

URL 매핑에 의해 실행되는 answer_vote 함수를 작성해준다.

projects\mysite\pybo\views\answer_views.py 에 작성해주자.

잘 작동되는지 테스트 해보자.

 

'Django > 따라하는 장고' 카테고리의 다른 글

27. 마크다운  (0) 2022.11.23
26. 앵커  (0) 2022.11.23
24. views.py 분리  (0) 2022.11.21
23. 답변 수정 및 삭제  (0) 2022.11.19
22. 질문 수정 및 삭제  (0) 2022.11.18

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 컴퓨터 시스템에서 메모리 계층 구조를 이루는 근본 이유는 무엇인가?

CPU의 메모리 액세스 속도를 높이기 위해

 

2. 메모리 계층화가 성공적인 이유는?

참조의 지역성 때문

 

3. 메모리 계층 구조에서 가장 빠른 메모리는?

CPU 레지스터

 

4. 메모리 계층 구조를 구성하는 기억 장치들의 특징으로 틀린 것은?

용량이 클수록 속도도 빠르다

 

5. 다음 문장의 빈 곳에 보기 중에서 적절한 단어를 삽입하여 문장을 완성하라.

( 논리 주소 )는 개발자나 프로그램에서 사용하는 주소로 0번지부터 시작되고 연속된다. CPU는 ( 논리 주소 )를 ( 물리 주소 )로 변환하는 ( MMU )를 내장하고 있다. CPU의 PC(Program Counter) 레지스터에 들어 있는 주소는 ( 논리 주소 )이다. 시스템 버스를 통해 전달되는 주소는 ( 물리 주소 )이고 그 범위는 CPU ( 주소버스 )의 크기에 달려있다. 개발자나 응용프로그램에서는 작성된 코드의 ( 논리 주소 )는 알 수 있으나 ( 물리 주소 )는 알 수 없다.

 

6. 운영체제의 메모리 관리 목표에 해당하지 않는 것은?

메모리를 연속적으로 할당함으로써 프로세스의 실행 성능 향상

 

7. 논리 주소에 대해 잘못 설명한 것은?

CPU의 PC 레지스터에는 다음에 액세스할 명령의 주소가 들어 있는데 이 주소는 물리 주소이다

 

8. 물리 주소에 대한 설명으로 잘못된 것은?

커널 코드는 물리 주소만 사용한다. 왜냐하면 커널 코드의 빠른 실행을 위해 논리 주소를 물리 주소로 바꾸는 시간을 없애기 위해서 이다

 

9. 다음 프로그램은 C 언어에서 100바이트의 메모리를 동적 할당 받는 코드이다. 포인터 변수 p에는 동적 할당받은 메모리의 주소가 들어 있다. 포인터 변수 p에 들어 있는 주소는 무슨 주소인가?

int *p = (int*)malloc(100);

논리 주소

 

10. 다음 중 절대 주소 300번지는?

②  CPU 패키지를 통해 출력된 주소 300이 주소 버스를 타고 메모리 장치에 도달하였다

 

11. 비주얼 스튜디오를 이용하여 C 응용프로그램을 작성하고 컴파일하였다. 응용프로그램 내에 선언된 변수 n의 절대주소를 알 수 있는 존재는?

위의 어떤 것도 알 수 없다

 

12. 연속 메모리 할당이 분할 메모리 할당보다 나은 면은?

논리 주소와 물리 주소 사이의 매핑 과정이 단순하여 상대적으로 빠른 프로세스의 실행

 

13. 분할 메모리 할당은 연속 메모리 할당의 어떤 면을 개선하기 위한 것인가?

메모리에 빈 영역이 많이 산재되어 있음에도 불구하고 프로세스를 적재할 수 없는 메모리 할당의 경직성을 극복하기 위해

 

14. 다음 중내부 단편화가 발생하는 것을 모두 골라라?

페이징

고정 크기 연속 메모리 할당

 

15. 세그먼테이션과 페이징에 대해 잘못 설명한 것은?

세그먼테이션이나 페이징 모두 세그먼트 테이블과 페이지 테이블이 프로세스마다 1개씩 존재한다

 

16. 홀 선택 알고리즘 중 요청하는 메모리 크기를 수용하는 홀 (비어 있는 메모리 공간) 중 가장 작은 홀을 선택하는 알고리즘은 무엇인가?

best-fit

 

17. 홀 선택 알고리즘은 메모리의 홀(비어 있는 메모리 공간) 중에서 선택하여 요청된 메모리를 할당한다. 요청 크기와 홀의 크기가 같지 않는 경우 할당된 홀에 새로운 홀이 생기게 된다. 이 때 가장 큰 홀을 만들게 되는 알고리즘은 무엇인가?

worst-fit

 

18. 세그먼테이션 메모리 관리 기법에서 세그먼트 테이블의 항목은 어떤 정보로 구성되는가?

세그먼트의 크기와 세그먼트의 물리 주소

 

19. 세그먼테이션 메모리 관리 기법에서 세그먼트 테이블의 항목에는 세그먼트의 크기 정보가 저장된다. 이것은 어떤 목적으로 사용되는가?

CPU에 의해 발생된 논리 주소가 세그먼트가 할당된 무리 메모리의 영역을 넘어섰는지 판단하기 위해

 

20. 현대의 컴퓨터에서 CPU 패키지 안에 들어 있지 않는 것은?

SSD

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 젓가락과 숟가락이 하나씩만 있는 식탁에서 두 사람이 식사를 한다고 하자. 숟가락과 젓가락을 동시에 들어야 한 입 식사가 가능하며, 숟가락이든 젓가락이든 한 번에 하나 씩 들어야 한다. 한 개만 가진 사람은 나머지 한 개가 준비될 때까지 기다려야 한다. 한 입 식사 후 들고 있던 숟가락과 젓가락은 모두 내려놓으며, 둘은 대화할 수 없다고 할 때, 두 사람이 식사하는 동안 교착 상태가 발생하는 상황을 사례를 들어 설명하라. 

정상적으로 식사가 이루어 지려면 한명이 젓가락과 숟가락을 둘다 들고 식사를 마친후 다음 사람이 먹어야 하지만, 한 사람이 젓가락을 드는 동안 다른 사람이 숟가락을 들면 둘다 숟가락과 젓가락을 무한정 기다린다.

 

2. 식사하는 철학자 문제를 잘못 기술한 것은?

식사하는 철학자 문제는 공유 자원에 대한 멀티스레드의 스케줄링 문제이다

 

3. 식사하는 철학자 문제를 해결하는 방법으로 적합한 것을 있는 대로 골라라. 

철학자가하나의 포크를 들고 다른 포크를 1분 이상 기다릴 때, 두 포크를 놓고 잠시 생각한 뒤 다시 식사를 하면 해결된다

식당에 지배인을 두고 지배인이 포크를 대기하고 있는 척학자가 있을 때, 기다리는 포크를 가지고 1분 이상 식사하고 있는 옆 철학자의 포크를 뺏어 주면 된다

③  포크마다 번호를 매기고 포크가 필요할 때 번호 순으로 포크를 들게 하면 해결된다

 

4. 식사하는 철학자 문제가 단일 CPU에서도 발생할 수 있는가, 없는가?

단일 CPU 에서도 발생할 수 있다

 

5. 다음 문장의 빈 곳에 적절한 단어를 선택하여 문장을 완성하라.

컴퓨터 시스템에서 ( 교착상태 )는 deadly embrace라고도 불리는 것으로 ( 교착상태 )가 유발되는 4가지 필요충분조건은 ( 코프만 )에 의해 증명되었다. 그럼에도 불구하고 현재 거의 모든 컴퓨터 시스테멩서는 이를 무시하는 방법을 사용하고 있는데 이것을 ( 타조 ) 알고리즘이라고 부른다.

 

6. 코프만의 4가지 조건에 해당하지 않는 것은?

① 우선순위 역전

 

7. 다음 자원할당 그래프에 대한 설명으로 맞는 것은?

④ 자원할당 그래프는 자원을 할당하는 과정에서 만들어진다

 

8. 다음 자원 할당 그래프에 대한 설명으로 틀린 것은?

③ 현재 이 시스템에서 T4와 T5 사이에 교착상태가 발생하고 있다

 

9. 다음 자원 할당 그래프 중 교착상태를 나타내는 것은 있는 대로 골라라.

 

10. 코프만 조건은 어떤 문제에 관한 것인가?

 

11. 교착상태 무시 전략이 나오게 된 배경이 아닌 것은?

교착상태가 발생한다고 피해가 발생하는 것은 아니다

 

12. 교착상태 예반 전략의 이론적 배경은?

코프만 조건

 

13. 자원할당 그래프를 전혀 사용할 필요가 없는 교착상태 해결 전략은?

④ 교착상태 무시

 

14. 교착상태 관련 알고리즘 중 타조 알고리즘에 대한 설명을 틀린 것은?

교착상태가 의심되면 부팅하거나 의심가능 스레드 중 하나를 종료시키는 단순한 방법이다

 

15. 교착상태 해결 방법중 타조 알고리즘이 적합한 상황은?

개인용 PC

 

16. 교착상태 감지 및 복구와 관련된 방법이 아닌 것은?

② 모든 자원에 번호를 붙이고 각 스레드는 자원을 할당받을 때 작은 번호의 자원부터 할당받도록 함

 

17. 교착상태 감지 및 복구 방법에 대한 설명으로 틀린 것은?

③ 사용자나 시스템 관리자가 교착상태가 발생하였다고 생각되면 시스템을 재시작 시킨다

 

18. 교착상태에 대한 설명으로 옳은 것은?

② 교착상태는 몇 몇 스레드들 사이에서 발생하므로 이들만의 문제이지 시스템 전체의 문제는 아니다

 

19. 교착상태는 주로 어디에서 발생하는가?

① 사용자가 작성한 멀티스레드 응용프로그램의 스레드들 사이에

점프 투 장고 튜토리얼을 계속 따라하고있는데 계속 하다보면 views.py 에 함수가 계속 늘어나서 불편함을 느끼는데 이를 해결해보자.

이를 해결하기 위해서는 2가지 방법이 있는데 2가지 방법을 다 해보자. 먼저 첫 번째 방법을 한 후에 두 번째 방법을 할 수 있기 때문에 먼저 첫번째 방법부터 따라해보자.

 

[첫 번째 방법]

 

첫 번째 방법은 views.py 파일만 여러 파일로 분리하고 나머지는 고치지 않아도 되는 변화가 적은 방법이다.

먼저 projects\mysite\pybo\views 디렉토리를 만들자.

views.py 파일에 정의된 함수를 기능별로 views 디렉토리에 다음의 파일로 저장하자.

파일명 기능 함수
base_views.py 기본관리 index, detail
question_views.py 질문관리 question_create, question_modify, question_delete
answer_views.py 답변관리 answer_create, answer_modify, answer_delete

projects\mysite\pybo\views\base_views.py 파일을 만들고 다음과 같이 작성하자.

pybo\views.py 에 있던 index 함수와 detail 함수의 내용을 그냥 복사 붙여넣기를 하면 된다. import 문맥만 수정해주면된다. pybo\views.py 에서는 from .models import Question 처럼 같은 디렉토리에 있는 models.py 모듈을 import 했지만 지금은 views 디렉토리 하위에 base_views.py 파일이 위치하므로 from ..models import Question 처럼 부모디렉토리의 models.py 모듈을 import 해야 한다.

 

projects\mysite\pybo\views\question_views.py 파일을 새로 만들고 작성하자.

views.py 파일에서 함수들을 복사해 붙여넣기하자.

 

projects\mysite\pybo\views\answer_views.py 파일을 새로 만들고 내용을 복사 붙여넣기하자.

 

그리고 projects\mysite\pybo\views\__init__.py 파일을 새로 만들고 다음과 같이 작성하자.

views 디렉토리의 __init__.py 파일에서 views 디렉토리에 있는 base_views.py 등의 모든 뷰 파일의 함수를 import 했기 때문에 pybo\urls.py 와 같은 다른 모듈에서 views.py 모듈의 함수를 사용하는 부분을 수정할 필요가 없다.

그리고 이제 pybo\views.py 파일을 삭제하자.

테스트해보면 아무런 문제가 없다.

 

[두 번째 방법]

 

첫 번째 방법에는 단점이 있다.

 

장고는 디버깅시 보통 urls.py 파일에서 URL 에 매핑된 함수를 찾는것으로 시작한다. 하지만 첫 번째 방법을 사용하면 urls.py 파일에 매핑된 함수명은 알 수 있지만 어떤 뷰 파일의 함수인지는 알 수가 없다. 이는 views 디렉토리의 모든 뷰 파일을 찾아봐야 하는 불편함을 초래하게 한다. 이러한 이유로 혼자가 아닌 여러명이 함께 하는 프로젝트라면 첫 번째 방법은 절대로 추천하지 않는다고 한다.

두 번째 방법은 views 디렉토리의 __init__.py 파일을 제거하고 pybo/urls.py 에서 views.index 대신 base_views.index 와 같이 전체 경로를 써주는 방법이다. 먼저 views 디렉토리의 __init__.py 파일을 제거하자.

그 후 projects\mysite\pybo\urls.py 파일을 다음과 같이 수정하자.

URL 매핑시 views.index 가 아닌 base_views.index 이런식으로 모듈명이 표시되도록 바꾸었다. 이제 어떤 뷰 파일의 함수인지 명확하게 인지할 수 있다.

 

projects\mysite\config\urls.py 파일도 다음과 같이 수정하자.

이 파일도 index 에 해당되는 URL 매핑을 좀 더 명확하게 수정했다.

두 번째 방법은 프로그램을 모두 하나하나 수정해 주어야하는 단점이 있지만 좀 더 명확해지는 장점이 있다.

'Django > 따라하는 장고' 카테고리의 다른 글

26. 앵커  (0) 2022.11.23
25. 추천 기능  (0) 2022.11.23
23. 답변 수정 및 삭제  (0) 2022.11.19
22. 질문 수정 및 삭제  (0) 2022.11.18
21. author 표시  (0) 2022.11.17

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 여러 스레드가 공유 변수를 접근하려고 경쟁할 때 공유 변수의 값이 훼손되는 상황이 발생할 수 있다. 공유 변수가 훼손되지 않도록 스레드 사이에 공유 변수에 대한 접근 시간과 방법 등을 조절하는 기법을 무엇이라고 하는가.

① 스레드 동기화

 

2. 멀티스레드가 동시에 공유 데이터를 접근할 때 데이터가 훼손되지 않도록 막는 기법의 핵심 정책은 무엇인가?

상호배제

 

3. 다음은 무엇에 대한 정의인가?

다수의 스레드로부터 공유 데이터의 훼손을 막기 위해 임계구역이 오직 한 스레드만 배타적 독점적으로 사용하도록 관리하는 기술

 상호배제

 

4. 원자명령(atomic instruction)이란?

① CPU 명령

 

5. Test and Set Lock 혹은 TSL 명령에 대한 설명이 틀린 것은?

스핀락

 

6. 다음 원자명령에 대한 설명으로 옳은 것은?

TSL ax, lock

 lock 변수 값을 ax 에 읽어오고 lock 변수에 1을 저장한다.

 

7. 원자명령과 가장 거리가 먼 것은?

④ 원자명령은 거의 모든 CPU에 있으며 CPU를 막론하고 이름이 동일하다

 

8. 임계구역에 대한 설명으로 틀린 것은?

 대부분의 운영체제는 임계구역에 진입할 때 다른 스레드가 진입하지 못하도록 인터럽트를 금지시키고, 나올 때 인터럽트를 허용하는 방법을 사용한다(오늘날에는 원자명령을 활용한다)

 

9. 멀티스레드의 동기화 기법 중 멀티코어 CPU를 가진 현대의 시스템에 적합한 것은?

스핀락

 

10. 멀티스레드의 동기화 기법 중 요청한 자원을 사용할 수 있을 때 까지 대기하는 큐를 사용하지 않는 방법은?

 스핀락

 

11. 임계구역의 실행 시간이 매우 짧을 경우에 적합한 멀티스레드의 동기화 기법은?

 스핀락

 

12. 커널 코드나 인터럽트 서비스 루틴 등에서 임계 구역에 접근할 때 멀티스레드 동기화를 위해 사용되는 기법은?

 스핀락

 

13. 멀티스레드 동기화 기법 중 오랜 시간 동안 공유 자원을 접근하지 못하는 기아가 발생할 수 있는 것은?

 스핀락

 

14. 멀티스레드의 동기화는 왜 필요한가?

② 여러 스레드가 동시에 동일한 변수를 읽고 쓸 때 발생하는 문제를 해결하기 위해

 

15. 다음 중 CPU 사용 시간을 심하게 낭비하는 것이 아닌 것은?

② sleep-waiting

 

16. 다음 중 동기화가 발생하는 공간에 대한 것 중 옳은 것은?

사용자 공간과 커널 공간 모두 동기화 필요

 

17. 우선순위 역전에 대한 설명 중 틀린 것은?

우선순위 역전은 낮은 순위의 스레드가 기아 상태에 빠지는 것을 막기 위한 매우 효율적인 방법이다

 

18. 공유 자원과 가장 거리가 먼 단어는?

N:1 매핑

 

19. 생산자 소비자 문제에 대해 잘 설명한 것은?

공유 버퍼를 사이에 두고 공유 버퍼에 데이터를 저장하는 스레드와 공유 버퍼로부터 데이터를 읽어가는 스레드 사이에 공유 버퍼에 대한 동시 접근 문제이다

 

20. 생산자 소비자 문제인 것은 모두 골라라.

① 마이크로부터 연속하여 들어오는 오디오 샘플을 큐에 넣는 스레드와 큐의 오디오 샘플을 스피커로 출력하는 스레드

③ 프린트할 파일이 생길 때 마다 큐에 넣은 스레드와 큐에 있는 파일을 프린터로 출력하는 스레드

 

21. pthread 라이브러리를 이용하여 작성된 다음 4개의 보기에 대해 물음에 답하라. 보기에서 worker() 함수는 스레드가 실행하는 코드이다.

(1) 보기 (1)에서 임계구역의 코드를 적어라. 

sum = sum + 10;

(2) worker()를 실행하는 10개의 스레드가 동시에 실행될 때 4개의 보기 중 가장 실행 속도가 느린 코드는? 

 

(3) worker()를 실행하는 10개의 스레드가 동시에 실행될 때 4개의 보기 중 가장 실행 속도가 빠른 코드는? 

(4) worker()를 10개의 스레드가 동시에 실행될 때 스레드 동기화가 실패할 가능성이 있는 코드는? 

 

22. 다음은 비디오 플레이어 응용프로그램의 구조를 간략히 묘사한 것이다. 물음에 답하라.

(1) 이 응용프로그램을 개발하기 위해서는 생산자 소비자 문제를 해결해야 한다. 생산자 소비자 문제는 생산자 스레드, 소비자 스레드, 스리고 공유 버퍼로 구성되는데 이들이 각각 그림의 어느 부분에 해당하는지 밝혀라.

생산자 스레드 = 입력스레드

소비자 스레드 = 재생스레드

공유버퍼 = 비디오 버퍼

(2) 이 응용프로그램에서 입력스레드와 재생스레드가 생산자와 소비자로서 비디오를 재생하는 과정을 간단히 설명하라.

입력스레드는 네트워크로 부터 한 프레임씩 읽어 비디오 버퍼에 저장하는 일을 반복하고, 재생스레드는 비디오 버퍼에 도착하는 프레임을 읽고 디코딩하여 디스플레이에 출력하는 작업을 반복한다.

 

[복합 문제]

 

1. 응용프로그램 개발자는 어떤 코드를 임계구역으로 설정해야 하는가?

공유 데이터를 액세스하는 코드 블록을 임계구역으로 묶고, 임계구역에 대한 상호배제가 이루어지도록 작성해야 한다.

 

2. 다음 코드는 lock 변수를 이용하여 임계구역에 멀티스레드의 상호배제를 이루려고 한다. lock은 0이나 1 값을 가지는 변수이다. 질문에 답하라.

1       loop:
2                mov ax, lock
3                mov lock, 1
4                cmp ax, 0
5                jne loop
6                --------------
---             임계구역
100            --------------
101            mov lock, 0

(1) lock 변수의 역할은 무엇인가? 임계구역에 들어갈때 변수에 1을 쓰고 나올때 0을 쓴다. 1일때는 임계구역에 들어갈수 없다.

(2) 스레드 A가 임계구역의 코드를 실행하다 중단된 경우, 스레드 B가 1번 라인부터 실행하게 되면 스레드 B는 어떤 코드를 실행하게 되는가? lock 변수가 1이라 임계구역으로 들어가지 못하고 loop으로 돌아가 lock 이 0이 될 때까지 lock 변수를 읽고 0과 비교하는 코드를 반복 실행한다. 

(3) 이 코드는 임계구역에 대한 상호배제를 이룰 수 있는 코드인가? 상호배제에 실패하는 코드인가? 실패하는 코드이다.

(4) 질문 (3)의 이유를 설명하라. 만약 스레드 A 가 먼저 lock 변수 값 0을 ax로 읽은 후 스레드 B 로 컨텍스트 스위칭이 되고, 스레드 B 가 lock 변수를 읽고 lock변수를 1로 변경하고 임계구역에 진입후 임계구역 내에서 스레드 A 로 컨텍스트 스위칭이 일어난다면 스레드 A 와 B 둘다 임계구역에 있는 충돌 상황이 발생한다.

(5) 만일 질문 (3) 에서 상호배제가 실패하는 코드라면, 상호배제가 성공하도록 해결 방법을 제시하라. 상호배제가 실패하게 만드는 원인인 mov ax, lock 와 mov lock, 1 을 두개로 합치면 된다.

 

 

 

[답변 수정]

 

질문 수정 및 삭제를 만들었으니 답변 수정및 삭제도 만들어줘야 한다. 질문 수정 및 삭제 방법과 유사하게 진행된다. 답변 수정은 답변 등록 템플릿이 따로 없으므로 답변 수정에 사용할 템플릿이 추가로 필요하다. 답변 등록은 질문 상세 화면 아래쪽에 텍스트 입력창을 추가해 만든것 이므로 질문 상세 템플릿은 답변 수정용으로는 적합하지 않다.

먼저 답변수정버튼을 추가하자.

projects\mysite\templates\pybo\question_detail.html 을 수정하자.

위에서 {% url 'pybo:answer_modify' answer.id %}가 추가되었기 때문에 pybo/urls.py 에 URL 매핑을추가하면 된다.

projects\mysite\pybo\urls.py 에 추가하자.

views.answer_modify 함수를 참조한다고 했으니 함수를 새로 만들어주자.

projects\mysite\pybbo\views.py 에 만들자.

내용은 질문 수정 함수와 유사하다.

 

answer_form.html 을 참조한다고 적었지만 아직 그 폼이 없으므로 새로 작성해주자.

projects\mysite\templates\pybo\answer_form.html 을 새로 만들고 작성해주자.

답변 수정도 질문 수정과 삭제 처럼 로그인한 사용자와 답변을 작성한 사용자가 같을 경우에만 수정 버튼이 나타난다.

작동도 잘 되는지 테스트 해보자.

 

[답변 삭제]

 

답변 삭제버튼을 추가하기위해 

projects\mysite\templates\pybo\question_detail.html 을 수정하자.

수정 버튼 옆에 삭제 버튼을 만들었고, 삭제 버튼에 delete 클래스를 적용했으므로 삭제 버튼을 누르면 data-uri 속성에 설정한 url 이 실행될 것이다. {% url 'pybo:answer_delete' answer.id %} 이 추가 되었기 때문에 pybo/urls.py 에 URL 매핑 규칙을 추가하자.

projects\mysite\pybbo\urls.py 를 수정하자.

views.answer_delete 함수를 참조한다고 했기때문에 새로 작성해주자.

projects\mysite\pybo\views.py 에 추가하자.

이제 로그인한 사용자와 답변 작성자가 같으면 삭제 버튼이 나온다.

잘 작동하는지 테스트도 해보자.

 

[수정일시 표시]

 

이제 마지막으로 수정일시를 표시해보자.

projects\mysite\templates\pybo\question_detail.html 파일을 다음과 같이 수정하자.

질문에 해당하는 수정일시 표시
답변에 해당하는 수정일시 표시

잘 나오는지 확인해보자.

질문 과 답변의 수정일시도 잘 나온다.

'Django > 따라하는 장고' 카테고리의 다른 글

25. 추천 기능  (0) 2022.11.23
24. views.py 분리  (0) 2022.11.21
22. 질문 수정 및 삭제  (0) 2022.11.18
21. author 표시  (0) 2022.11.17
20. author 속성  (0) 2022.11.16

[수정 일시]

 

먼저 질문 및 답변이 수정된 날짜를 확인할수있는 modify_date 속성을 추가하자.

projects\mysite\pybo\models.py 를 수정하자.

 

null=True 는 데이터베이스에서 modify_date 칼럼에서 null을 허용한다는 의미이며, blank=True 는 form.is_valid()를 통한 입력 데이터 검증시 값이 없어도 된다는 의미이다. 즉, 아직 modify_date 값이 없다 = 아직 수정을 하지 않았을 경우 값을 비워둘 수 있다는것을 의미한다. 모델이 변경되었으므로 makemigrations, migrate 명령을 수행하자.

 

[질문 수정]

 

먼저 질문 수정 버튼을 만들어주자.

projects\mysite\templates\pybo\question_detail.html 를 수정하자.

해석하면 수정 버튼은 로그인한 사용자와 글쓴이가 동일한 경우에만 노출되도록 {% if request.user == question.author %} 을 적용했다. 그 아래는 버튼을 구성한 것이다. 그리고 {% url 'pybo:question_modify' question.id %} URL이 추가되었으므로 pybo/urls.py 에 URL 매핑규칙을 추가해야한다.

projects\mysite\pybo\urls.py 를 수정하자.

 보면 알겠지만 views.question_modify 함수를 참조한다고 적어놨다. 아직 우리는 저 함수가 없기 때문에 새로 만들어주자,

projects\mysite\pybo\views.py 에 추가하자.

question_modify 함수는 로그인한 사용자(request.user)와 수정하려는 질문의 글쓴이(question.author)가 다르면 '수정권한이 없습니다' 오류를 발생한다. 이 오류를 발생시키기 위해 messages 모듈을 이용했다. messages 는 장고가 제공하는 모듈로 넌필드 오류를 발생시킬때 사용한다.

'수정' 버튼을 클릭하면 http://localhost:8000/pybo/question/modify/2/ 페이지가 GET 방식으로 호출되어 질문수정 화면이 보여진다. 질문 수정화면에서 사용한 템플릿은 질문 등록시 사용했던 pybo/question_form.html 파일과 동일하다. 질문 수정화면에서 저장하기 버튼을 클릭하면 http://localhost:8000/pybo/question/modify/2/ 페이지가 POST 방식으로 호출되어 데이터가 수정된다. form 태그에 action 속성이 없는 경우 디폴트 action 은 현재 페이지가 되기 때문이다.

GET 요청인 경우 질문수정 화면에 조회된 질문의 제목과 내용이반영될 수 있도록  form = QuestionForm(instance=question) 을 추가했다. 폼 생성시 이처럼 instance 값을 지정하면 폼의 속성 값이 instance 값으로 채워진다. 따라서 질문을 수정하는 화면에서 제목과 내용이 채워진 채로 보일 것이다.

POST 요청인 경우 수정된 내용을 반영해야 하는 케이스 이므로 form = QuestionForm(request.POST, instance=question) 을 추가해주었다. 이 코드의 의미는 instance 를 기준으로 QuestionForm 을 생성하지만 request.POST 의 값으로 덮어쓰라는 의미이다. 따라서 질문 수정화면에서 제목 또는 내용을 변경하여 POST 로 요청하면 변경된 내용이 QuestionForm 에 저장된다. 

질문 수정일시는 question.modify_date = timezone.now() 로 현재일시를 저장한다.

 

길게 적혀있어 어렵지만 내가 이해한 바로 설명해보자면, 질문 수정버튼을 누르면 GET 방식으로 된다는 것을 의미하고. GET 방식으로 요청된 경우에는 질문수정 화면이 나오는데 이 때 양식은 질문생성할때의 question_form.html 과 동일하고, 안의 내용들은 수정하려던 질문의 제목 과 내용이 자동으로 채워져있다. 이 상태에서 내용이나 제목을 수정해 수정하기 버튼을 누르는 것은 POST 방식으로 요청한다는 것같다. POST 방식으로 요청한 경우 수정한 내용들로 원래 있던 내용과 제목에 덮어쓰라는 것을 의미한다. 그리고 수정했기 때문에 값이 비어있던 수정일시도 현재시간으로 추가해 저장한다. 이러한 의미인것같다.

 

messages 모듈에 의해 발생되는 '수정권한이 없습니다' 오류가 표시될 수 있도록 질문 상세 화면 위쪽에 오류 영역을 추가해야한다.

projects\mysite\templates\pybo\question_detail.html 을 수정하자.

수정은 로그인 한 사용자와 글 작성자가 동일한 경우에만 가능하기 때문에 오류는 표시되지 않지만. 비 정상적인 방법으로 질문을 수정할 경우에 이 오류를 보여주어야 한다.

테스트해보자.

로그인 사용자와 작성자가 같을경우 수정 버튼이 보이고, 아닐경우 보이지 않는다. 수정 버튼을 눌렀을 경우에도 잘 작동되는지 확인해보자. 잘 작동되지만 아직은 수정일시가 표시되지는 않는다.

 

[질문 삭제]

 

질문삭제 버튼을 추가하기위해

projects\mysite\templates\pybo\question_detail.html 을 수정하자.

data-url 이 아니고 data-uri 이다. 스펠링을 잘 확인해보자.

삭제버튼은 수정버튼과 달리 href 속성 값을 javascript:void(0) 으로 설정했다. href 속성값을 이렇게 설정하면 해당 링크를 클릭해도 아무런 동작도 하지 않는다. 그리고 삭제를 실행할 URL을 얻기 위해 data-url 속성을 추가하고, 삭제 버튼이 눌리는 이벤트를 확인할 수 있도록 class 속성에 'delete' 항목을 추가했다. data-uri 속성은 자바스크립트에서 클릭 이벤트 발생시 this.dataset.uri와 같이 사용하여 그 값을 얻을 수 있다. href 에 삭제 URL을 직접 사용하지 않고 이러한 방식을 사용하는 이유는 삭제 버튼을 클릭했을때 '정말 삭제 하시겠습니까?' 같은확인창이 필요하기 때문이다.

삭제 버튼을 눌렀을 때 확인창을 나오게 하기 위해서는 다음과 같은 자바스크립트가 필요하다. 일단 눈으로만 보며 뜻을 알아보자.

<script type = 'text/javascript'>
const delete_elements = document.getElementsByClassName("delete");
Array.form(delete_elements).forEach(function(element)
{
    element.addEventListener('click', function() {
        if(confirm("정말로 삭제하시겠습니까?")){
            location.href = this.dataset.uri;
        };
    });
});
</script>

이 자바스크립트의 의미는 delete 라는 클래스를 포함하는 컴포넌트(버튼이나 링크) 를 클릭하면 "정말로 삭제하시겠습니까?" 라는 질문을 하고 "확인" 버튼을 선택했을때 해당 컴포넌트의 data-uri 값으로 URL 호출을 하라는 의미이다. "확인" 대신 "취소"를 선택하며 아무런 일도 발생하지 않는다. 이와 같은 스크립트를 추가하면 "삭제" 버튼을 클릭하고 "확인" 버튼을 선택하면 data-uri 속성에 해당하는 {% url 'pybo:question_delete' question.id %} 이 호출된다. 

자바스크립트는 HTML 구조에서 </body> 태그 바로 위에 삽입하는 것을 추천한다. 왜냐하면 이렇게 해야 화면 렌더링이 완료된 후에 자바스크립트가 실행되기 때문이다. 화면 렌더링이 완료되지 않은 상태에서 자바스크립트를 실행하면 화면의 값을 읽지 못하는 오류가 발생할수도 있고 화면 로딩이 지연되는 문제가 발생할 수 도 있다. 

projects\mysite\templates\base.html 을 다음과 같이 수정하자.

 

base.html 을 상속하는 템플릿들에서 content 블록을 구성했던것 처럼 script 를 구현한다.</body> 태그 바로 위에 {% block script %}, {% endblock %} 블록을 추가했다. 이렇게하면 base.html 을 상속하는 템플릿은 자바스크림트의 삽입위치를 신경쓸 필요없이 저 블록을 사용해 자바스크립트를 작성하면 된다.

이를 이용해

projects\mysite\templates\pybo\question_detail.html 을 다음과 같이 수정하자.

그리고 data-uri 에 {% url 'pybo:question_delete' question.id %} URL이 추가되었으므로 pybo/urls.py 에 매핑규칙을 추가해야한다.

proejcts\mysite\pybo\urls.py 를 수정하자.

그리고 위에서 정의한 views.question_delete 함수도 작성해야한다.

projects\mysite\pybo\views.py 를 다음과 같이 수정하자.

로그인이 필요하므로 @login_required 에너테이션을 적용한다. 로그인한 사용자와 글쓴이가 같을 경우에만 삭제할수 있다.

테스트 해보자

잘 작동하는지도 테스트해보자.

'Django > 따라하는 장고' 카테고리의 다른 글

24. views.py 분리  (0) 2022.11.21
23. 답변 수정 및 삭제  (0) 2022.11.19
21. author 표시  (0) 2022.11.17
20. author 속성  (0) 2022.11.16
19. 회원가입  (0) 2022.11.10

앞서 추가한 author 속성을 이용해 질문목록 에서 author 를 볼수있게 하자.

projects\mysite\templates\pybo\question_list.html

<th>글쓴이</th>로 항목을 추가하고 th 엘리먼트를 가운데 정렬하도록 tr 엘리먼트에 text-center 클래스를 추가하고, 제목의 너비가 전체의 50%가 되도록 style="width:50%" 를 지정했다. <td>{{ question.author.username }}</td> 를 추가해 질문의 글쓴이를 표시했다. 테이블 내용을 가운데 정렬하도록 tr 엘리먼트에 text-center 를 추가하고, 제목을 왼쪽 정하도록 td 엘리먼트에 text-start 클래스를 추가했다. 테이블 항목도 3개에서 글쓴이를 추가해 4개가 되었으므로 colspan 을 4로 수정했다. 테스트 해보자.

 

이제 질문상세템플릿에도 author 를 추가해 질문과 답변에 글쓴이와 작성일시가 같이 보이도록 수정하자.

projects\mysite\templates\pybo\question_detail.html 을 수정하자.

 테스트 해보자

잘 수정되었다.

'Django > 따라하는 장고' 카테고리의 다른 글

23. 답변 수정 및 삭제  (0) 2022.11.19
22. 질문 수정 및 삭제  (0) 2022.11.18
20. author 속성  (0) 2022.11.16
19. 회원가입  (0) 2022.11.10
18. 로그인 기능  (0) 2022.11.09

+ Recent posts