프로그래밍 실습
프로그래밍 실습
AI 디지털교과서 플랫폼은 별도의 환경 설치 없이 학생들이 직접 코드를 작성하고 실행할 수 있는 프로그래밍 실습을 지원합니다.
특히 실행 버튼을 눌러 학생이 스스로 작성한 코드를 직접 실행해 볼 수 있고, 제출 버튼을 눌러 문제에서 원하는 대로 올바른 코드를 작성했는지 여부를 즉시 확인할 수 있습니다.
1️⃣ 프로그래밍 실습 문제의 구성
AI 디지털교과서 프로그래밍 실습은 크게 아래의 네 가지로 구성되어 있습니다.
- 실습 환경
- 문제 설명과 지시 사항
- 스켈레톤 코드(실습 문제)
- 채점 코드(실행/채점 파일)
위의 항목을 설정하고 작성하여 학생들에게 유익한 프로그래밍 실습을 만들어봅시다.
구성 항목 | 세부 설명 |
---|---|
실습 환경 | 실습 문제를 제작하기 위한 실습의 기반 환경입니다. |
문제 설명과 지시 사항 | 실습의 목표와 해당 실습에서 해결해야 할 문제에 대한 자세한 설명을 작성할 수 있습니다. |
스켈레톤 코드 (실습 문제) | 학생들이 코드를 입력할 때 도움을 줄 수 있는 기본 코드입니다. |
채점 코드 (실행/채점 파일) | 학생들이 작성한 코드를 실행하고 채점하기 위한 코드입니다. |
2️⃣ 프로그래밍 실습 추가하기
- 수업 목록에서 실습을 추가하려는 수업을 클릭합니다.
수업 자료 추가
버튼을 클릭합니다.
- 새로 만들기 선택 후, 추가할 자료 유형 중
프로그래밍 실습
과다음
버튼을 클릭합니다.
- *필수 항목인 자료 제목과 실습 유형, 제출 버튼 옵션을 아래 내용을 참고하여 설정 후 저장 버튼을 클릭합니다.
설정 | 세부 설명 |
---|---|
자료 제목 | 수업 목록 및 실습 하단에 보이는 자료 제목입니다. |
실습 유형 | 실습의 유형을 설정합니다.
|
제출 버튼 | 학생이 작성한 코드를 채점하기 위해 제출 버튼의 사용 여부를 설정합니다. |
자료 추가 시 설정한 내용은 실습을 만든 이후에도
수업 자료 수정
버튼을 클릭하여 탭에서 수정할 수 있습니다.
3️⃣ 실습 환경 설정하기
실습 유형에 따른 환경 설정 방법은 하단의 링크들을 통해 확인할 수 있습니다.
4️⃣ 문제 설명, 지시 사항 및 해설
프로그래밍 실습 문제에 대한 설명과 지시 사항 및 해설을 작성할 수 있습니다.
- 우측 상단에 있는 수업 자료 수정 아이콘을 클릭합니다.
- 왼쪽 패널의
설명
,지시 사항
항목의 에디터에 문제와 관련된 글을 작성하고 이미지를 삽입할 수 있습니다.
- 코드 블럭을 만들면 해당 내용을 복사할 수 있도록
Copy
버튼이 생겨 학생들이 쉽게 코드 블럭 안의 내용을 복사하여 이용할 수 있습니다. - 자주 사용하는 Markdown 문법은 아래의 내용을 참고하실 수 있습니다.
-
# 자주 사용하는 Markdown 문법
bold : **텍스트**
bullet point : -텍스트
글자 크기 : #텍스트 > ##텍스트 > ###텍스트
코드 블럭 : `텍스트`
여러 줄 코드 블럭 : ```enter 텍스트 enter```
- 해설 탭은 선생님들께만 보이는 기능으로 학생들에게는 표시되지 않습니다.
- 문제의
설명
,지시사항
및해설
을 작성한 후에는 우측 하단의저장
버튼을 클릭하여 내용을 저장합니다.
- 해당 화면은 CLI 프로그래밍을 기준으로 엔트리와 마이크로비트의 저장 방법은 해당 페이지에서 있습니다.
1) 스켈레톤 코드 작성하기
적절한 스켈레톤 코드는 학생들의 코딩을 더 쉽게 해줍니다.
학생들이 코드 작성을 쉽게 시작할 수 있도록 코드 에디터에 적절한 스켈레톤 코드를 미리 작성해 둘 수 있습니다.
- 우측 상단의
수업 자료 수정
버튼을 클릭합니다.
- 우측 상단의
실습 문제 작성
탭 실습 파일 목록에서main.*
파일을 선택합니다.
템플릿을 사용하실 경우 main.py
에 스켈레톤 코드가 작성되어 있습니다.
- 학생들의 코드 작성을 돕는 적절한 스켈레톤 코드를 작성합니다.
- 실습 페이지에 접속했을 때 기본적으로 학생에게 보여주고자 하는 스켈레톤 파일을 설정한 후
저장
버튼을 눌러 코드를 저장합니다.
▶️ 기본 스켈레톤 파일 설정하기
학생들이 해당 실습 페이지에 들어갔을 때 기본적으로 볼 수 있는 파일을 설정하기 위한 방법입니다.
- 우측 상단의
수업 자료 수정
버튼을 클릭합니다.
실습 문제 작성
탭에서 파일 목록 하단의스켈레톤 파일 설정
을 클릭합니다.
- 기본적으로 보이고 싶은 파일의 왼쪽 체크 박스를 순서대로 클릭한 후, 다시 하단
설정
버튼을 클릭합니다.
- 우측 하단
저장
버튼을 클릭합니다.
▶️ 기본 스켈레톤 파일 설정 더 알아보기
- 파일을 클릭하여 폴더 내부에 위치한 파일들을 확인하실 수 있습니다.
- 파일을 읽기 전용으로 만들려면 더 보기 옵션 클릭 후
읽기 전용
버튼을 눌러줍니다.
- 학생에게 해당 파일을 보이지 않게 설정하려면 체크박스 해제 후 더보기 옵션 클릭 ▶️ 파일숨기기를 클릭합니다.
2) 코드 파일 추가 및 삭제하기
스켈레톤 코드를 작성할 main. py 파일뿐만 아니라 다양한 코드 파일을 추가하고 삭제할 수 있습니다.
▶️ 코드 파일 추가하기
- 우측 상단 '실습 문제 작성' 탭에서 파일 목록 상단의 '+' 아이콘을 클릭합니다.
- 새롭게 생성된 코드 파일의 이름과 확장자를 설정합니다. 예시) model.py, model.R
- 우측 하단 '저장' 버튼을 클릭합니다.
▶️ 코드 파일 삭제하기
- 우측 상단에 있는
수업 자료 수정
아이콘을 클릭합니다.
- '실습 문제 작성' 탭에서 삭제하고자 하는 파일 우측의 더 보기(:) 클릭 후 나오는 옵션 중 삭제를 클릭합니다.
- 우측 하단 '저장' 버튼을 클릭합니다.
5️⃣ 프로그래밍 실습 삭제하기
- 삭제하고자 하는 실습 왼쪽의 체크 박스를 클릭합니다.
- 상단에 나타나는 '삭제' 버튼을 클릭합니다.
- 이후 나타나는 알림창의 '확인' 버튼을 클릭합니다.
삭제 이후에는 복원이 불가하기 때문에 삭제는 신중하게 결정해 주십시오.
6️⃣ 채점하기
AI 디지털교과서에서는 다양한 방식으로 상황에 맞게 채점을 진행할 수 있습니다.
아래 각 방법의 장단점을 보시고 가장 잘 맞는 방식을 사용하여 문제별로 사용하시면 됩니다.
1) STDIO 표준 입출력 기반 채점
장점: 알고리즘과 같은 입력과 출력이 있는 실습에 적절하며, 채점 기능을 설정하는 데 소요되는 시간이 짧습니다.
단점: 특정한 입력과 출력이 정해져 있는 문제에서만 사용할 수 있습니다.
간단한 채점을 위해 표준 입력/출력을 기반으로 한 채점 코드를 작성할 수 있습니다.
자동으로 코드가 생성됩니다.
입력/출력 채점은 입력값에 대해 특정 값이 출력되는지 여부를 채점하는 방법입니다.
- 우측 상단에 있는
수업 자료 수정
아이콘을 클릭합니다.
- 실습 수정 페이지 상단의
실행/채점 파일 작성
탭을 클릭합니다.
- 하단
STDIO 채점 코드 구성하기
버튼을 클릭합니다.
+
버튼을 눌러 원하는 입출력 채점 방식에 따라 테스트 케이스와 실행 제한 시간, 점수를 설정합니다.
- 아래 채점 메시지 작성을 클릭하여 정답/오답 시 출력되는 메시지를 작성합니다.
- 오른쪽 아래의
저장
버튼을 클릭합니다.
- STDOUT 출력값이 같음 : 설정한 문자열과 학생이 작성한 코드의 출력값이 완전히 동일한 경우 정답으로 채점
- STDOUT 출력값에 문자열이 포함 : 학생이 작성한 코드의 출력값에 설정한 문자열이 포함될 경우 정답으로 채점
- STDOUT 출력값에 문자열이 포함되지 않을 경우 : 학생이 작성한 코드의 출력값에 설정한 문자열이 포함되지 않을 경우 정답으로 채점
- STDOUT 출력값과 정규표현식이 일치: 학생이 작성한 코드 출력값에 설정한 정규표현식이 일치할 경우 정답으로 채점
- STDOUT 출력값과 정규표현식이 일치하지 않을 경우: 학생이 작성한 코드의 출력값에 설정한 정규표현식이 일치하지 않을 경우 정답으로 채점
이미 채점 코드가 존재한다면 입력/출력 채점 코드로 덮어 씌워집니다.
2) 채점 스크립트
장점: 다양한 케이스를 고려한 채점이 가능합니다.
단점: 실습 언어에 알맞은 채점 코드 작성이 필요합니다.
AI 디지털교과서에서는 코드를 채점할 때 grader.*를 사용합니다.
표준 입/출력 방식, 코드 비교를 이용한 채점 방식 등 다양한 채점 방법을 이용할 수 있습니다.
▶️ 채점 코드 작성하기
.elice 폴더의 grader.* 파일은 학생이 작성한 코드를 채점할 수 있는 답안 코드를 작성하는 곳입니다.
(.elice는 엘리스가 제공하는 예시로 교과서 마다 폴더명이 다를 수 있습니다.)
- 상단의 실행/채점 파일 작성을 클릭하십시오.
- 좌측 상단의 코드 뷰어로 전환을 클릭하십시오.
- .elice를 클릭하여 하위 폴더를 확인할 수 있습니다.
이곳에 채점을 위한 코드를 작성하세요. 각 파일의 구성은 다음과 같습니다.
- grader.py : 실제 채점 스크립트를 작성하는 파일
- grader.sh : 학생이 제출 버튼을 눌렀을 때 실행되는 bash shell script
- grader_aidt_utils.py : 제출 환경에서 동작 즉, 채점 시 사용할 aidt utils의 모음
- runner.sh : 학생이 실행 버튼을 눌렀을 때 실행되는 bash shell script
▶️ 채점하기
학생이 에디터에서 코드를 작성한 후 제출 버튼을 누르면 선생님이 grader.*에 작성해 놓은 답안 코드에 의해서 학생의 코드가 자동 채점됩니다.
3) 수동 채점
장점: 학생이 작성한 코드를 직접 확인하여 점수를 배부할 수 있습니다.
단점: 모든 학생의 코드를 살펴본 후 점수를 부여해 주어야 함으로 채점에 많은 시간 소요됩니다.
학생이 제출한 코드를 보고 수동으로 점수를 부여할 수 있습니다.
- 실습 화면 좌측 상단의 튜터링 아이콘을 클릭합니다.
- 점수를 줄 학생을 검색 및 선택하면 학생의 코드 에디터를 볼 수 있습니다.
- 우측 상단
최종 점수
칸의 📝버튼을 클릭합니다.
- 아래 화면에서 학생이 받은 점수에서 가감할 점수를 입력하여, 학생이 받을 점수를 설정한 후
적용
버튼을 누릅니다.
수동 점수를 주기 위해서는 학생이 한 번 이상 제출한 이력이 있어야 합니다.
*️⃣ Python 스크립트 기반 채점
grader.py 파일을 수정하여 채점 스크립트를 작성하는 방법에 대해 알아봅시다.
grader.sh은 학생이 제출 버튼을 눌렀을 때 실행되며,
grader.sh에서 grader.py를 실행하여 채점을 시작합니다.
grader.py를 작성하기 위해 자주 사용되는 aidt_utils.py의 함수들에 대해 일반적인 형식과 함께 안내해 드리겠습니다.
secure_send_grader()
: 터미널을 통해 사용자에게 메세지 출력secure_send_score()
: 실습의 최종 점수 설정
from grader_aidt_utils import AIDTUtils
aidt_utils = AIDTUtils()
# aidt_utils 가져오고 초기화합니다.
aidt_utils.secure_init()
# 채점을 진행합니다.
try:
# 학습자의 터미널 창에 문자열을 전송합니다.
aidt_utils.secure_send_grader('문자열')
# 학습자의 실습 점수를 전송합니다. 100점 획득 시, 정답으로 확인됩니다.
aidt_utils.secure_send_score(100)
# 채점 진행과정에서 오류가 발생하는 경우
except Exception:
# 실습 점수를 0점으로 설정
aidt_utils.secure_send_score(0)
sys.exit(1)
선생님은 grader.py를 수정하여 다양한 방식으로 학생의 코드를 채점할 수 있습니다.
아래 예시를 통해 grader.py 작성 방법에 대해 알아봅시다.
[예시 1] 입출력 기반 채점
기본 세팅된 파일 구조에서 아래 폴더 & 파일을 추가합니다.
-
input 폴더 / output 폴더 : 채점을 위한 테스트 케이스를 정의합니다.
-
testcases.py 파일 : 각 테스트 케이스별 부분 점수 및 정 오답 메시지를 설정합니다.
▶️ 1) 입출력 채점을 위한 테스트 케이스 작성
채점을 위한 입출력 값을 저장하기 위한 파일을 생성한 후, 각 테스트 케이스를 작성합니다.
input 폴더
- 테스트 케이스별 입력값을 txt 파일로 저장합니다.
- 케이스별로 1개의 입력값을 저장합니다.
output 폴더
- 테스트케이스 별 출력값을 txt 파일로 저장합니다.
- input 폴더 내에 작성한 각 입력값에 대응하는 출력값을 저장합니다.
▶️ 2) 채점 메시지 작성
테스트 케이스에서 설정한 항목별 정 오답 메시지를 정의합니다.
또한, 각 테스트 케이스별 부분 점수를 설정합니다.
# testcase 별 정답 메시지
correct_messages = [
"testcase 1. 정답입니다!",
"testcase 2. 정답입니다!"
]
# testcase 별 오답 메시지
wrong_message = [
"testcase 1. 오답입니다!",
"testcase 2. 오답입니다!"
]
# testcase 별 부분 점수
scores = [50, 50]
▶️ 3) grader.py 채점코드 작성
테스트 케이스의 개수만큼 학생의 코드를 실행하여, 학생이 작성한 코드의 출력 결과를 확인합니다.
이후, 예측한 정답 출력값(output 파일)과 비교하여 실습의 정.오답을 판단합니다.
각 테스트 케이스 별로 부분 점수를 제공할 수 있으며, 최종 채점 결과는
aidt_utils.secure_send_score(total_score)
를 통해 플랫폼(LXP) 내에 전송합니다.
예시 코드는 다음과 같습니다.
import os
import subprocess
import sys
from testcases import *
sys.path.append(os.getcwd())
from grader_aidt_utils import AIDTUtils # isort:skip
aidt_utils = AIDTUtils()
aidt_utils.secure_init()
SUM_TESTCASE_SCORES = 100
INPUT_DIR = '.aidt/input/'
OUTPUT_DIR = '.aidt/output/'
try:
total_score = 0
# 0. input, output 파일 불러오기
input_data = [
x for x in os.listdir(INPUT_DIR)
if x.endswith('.txt')
]
output_data = [
x for x in os.listdir(OUTPUT_DIR)
if x.endswith('.txt')
]
# 1. 테스트케이스 갯수 확인하기
if len(input_data) != len(output_data):
sys.exit(1)
NUM_TESTCASES = len(input_data)
# 2. 파일명 확인하기
matching = True
for i in range(1, NUM_TESTCASES + 1):
input_file = '%d.txt' % i
output_file = '%d.txt' % i
if input_file not in input_data:
matching = False
if output_file not in output_data:
matching = False
if not matching:
sys.exit(1)
# 3. 테스트케이스 별 채점 진행
for i in range(0, NUM_TESTCASES):
testcase_score = scores[i]
input_file = '%d.txt' % (i + 1)
input_text = subprocess.run(
['cat', '%s%s' % (INPUT_DIR, input_file)],
stdout=subprocess.PIPE
).stdout
result = subprocess.run(
['/bin/bash', '.aidt/runner.sh'],
input=input_text,
stdout=subprocess.PIPE
)
student_result = result.stdout.decode('utf-8').strip()
answer = ''.join(
open('%s%s' % (OUTPUT_DIR, input_file)).readlines()
).strip()
# 테스트케이스 별 정 오답 판단
if answer == student_result:
total_score += testcase_score # 테스트케이스 부분점수 추가
aidt_utils.secure_send_grader(
'✅ {} \n'.format(correct_messages[i])
)
else:
aidt_utils.secure_send_grader(
'❌ {} \n'.format(wrong_message[i])
)
# 5. 실습 최종 점수 계산
total_score = int(total_score)
aidt_utils.secure_send_score(total_score)
except Exception as err:
aidt_utils.secure_send_grader(
'채점 도중 오류가 발생했어요. 코드가 정상적으로 실행되는지 확인해 보세요.\n'
)
aidt_utils.secure_send_score(0)
sys.exit(1)
[예시 2] 특정 조건 확인
학생이 작성한 코드 파일을 불러온 후, 특정 조건이 성립하는지를 기준으로 채점을 진행할 수 있습니다.
아래 예시는print()
함수를 3번 사용하여 3행시를 짓는 실습에 대한 정답 채점 코드입니다.학생이 작성한 파일(main.py)을 불러온 후,
print()
함수가 총 3번 작성되었는지를 기준으로 실습을 채점합니다.
import os
import subprocess
import sys
from testcases import *
sys.path.append(os.getcwd())
from grader_aidt_utils import AIDTUtils # isort:skip
aidt_utils = AIDTUtils()
aidt_utils.secure_init()
try:
total_score = 0
# print() 함수를 3번 이상 사용했는지 확인하는 코드
count = 0
with open("main.py") as ans:
datafile = ans.readlines()
for line in datafile:
if 'print' in line:
count += 1
if count >= 3:
total_score += 100
aidt_utils.secure_send_grader(
'✅ 정답이에요! print()를 사용하여 멋진 삼행시를 지었군요! \n'
)
else:
aidt_utils.secure_send_grader(
'❌ 오답이에요! print()를 3번 사용해서 삼행시를 만들어 보세요.\n'
)
# 실습 최종 점수 전송
total_score = int(total_score)
aidt_utils.secure_send_score(total_score)
except Exception as err:
aidt_utils.secure_send_grader(
'채점 도중 오류가 발생했어요. 코드가 정상적으로 실행되는지 확인해보세요.\n'
)
aidt_utils.secure_send_score(0)
sys.exit(1)
grader.py를 작성하는 과정에서 유의할 점은 다음과 같습니다.
유의 사항 1
간혹 if문을 사용해 값을 비교할 때 형식과 형태가 맞지 않는 값을 비교할 경우 TypeError, RangeError 등의 오류가 발생할 수 있습니다. 이럴 경우, Grader는 즉시 동작을 멈추고 정상적인 채점이 이루어지지 않게 됩니다. 따라서 if문을 사용할 땐 다음의 코드와 같은 형식을 취하는 것을 권장합니다.
try:
if (
submission.drink_relfreq
== drink[drink['Attend'] == 1]['Name']
.value_counts(normalize=True)
).all():
total_score += 100
aidt_utils.secure_send_grader(
'상대도수를 올바르게 계산하셨습니다!\n'
)
except Exception:
aidt_utils.secure_send_grader(
'상대도수가 제대로 계산되지 않았어요. 다시 한번 계산해 볼까요?\n'
)
유의 사항 2
상황에 따라 세부적인 오류 내용을 구체적으로 명시해 주어야 하는 case가 발생할 수 있습니다.
이때는 내부 예외를 활용해 메시시지를 작성해 주세요.
Python 내부 예외에 대해서는 아래 링크를 참고해 주세요. https://docs.python.org/ko/3/library/exceptions.html#concrete-exceptions
import student_codes
try:
if student_codes.answer == 12:
total_score += 100
aidt_utils.secure_send_grader('정답!\n')
# index range error
except IndexError:
aidt_utils.secure_send_grader('인덱스가 지정된 범위를 벗어났어요.\n')
# name error
except NameError:
aidt_utils.secure_send_grader('선언하지 않은 변수를 사용했어요.\n')
# zero division error
except ZeroDivisionError:
aidt_utils.secure_send_grader('0으로는 나눌 수 없어요.\n')
유의 사항 3
채점 시 발생한 RuntimeError 메시지를 학생에게 제공한다면,
역으로 학생이 메시지 내용을 기반으로 테스트케이스를 유출할 수 있습니다.따라서 다음과 같은 형태로 에러 메시시지를 작성하는 것을 권장합니다.
# 권장하지 않는 경우
try:
# 채점 코드 작성
except Exception as err:
aidt_utils.secure_send_grader(
'Internal Error:\n%s\n' % str(err)
)
aidt_utils.secure_send_score(0)
sys.exit(1)
# 권장하는 방법
try:
# 채점 코드 작성
except Exception:
aidt_utils.secure_send_grader(
'채점 도중 오류가 발생했어요. 코드가 정상적으로 실행되는지 확인해 보세요.\n'
)
aidt_utils.secure_send_score(0)
sys.exit(1)
"""
만약 권장하지 않는 경우로 채점 코드를 작성했을 경우?
"""
# grader.py 전문 출력 가능
raise Exception(
open('.aidt/grader.py').read()
)
7️⃣ 수업자료 지도서
선생님들께서 원하시는 바를 AI에 학습시켜 헬피에 즉각적으로 반영할 수 있습니다.
- 화면 상단의
수업자료 지도서
를 클릭합니다.
- AI 모델 학습 참고 내용에 원하는 프롬프트를 입력할 수 있습니다.
- 우측 하단의 저장 버튼을 클릭하여 입력 내용을 저장합니다.
- 하단의 이미지처럼 선생님께서 입력하신 내용에 따라 헬피의 답변이 달라지는 것을 확인할 수 있습니다.
- 수업자료 지도서 저장 전
- 수업자료 지도서 저장 후