실습 문제


연습 문제는 학습자가 지금까지 배운 개념을 활용하는 것을 목표로, 임의의 문제를 풀어 보도록 설계된 문제예요.

트랙에 첫 연습 문제를 추가하고 싶나요? 연습 문제 추가 문서를 확인하거나 안내 영상을 시청해 봐요 👇

Note

트랙의 루트 디렉터리에서 다음 명령어를 실행하면 새 연습 문제의 뼈대를 빠르게 만들 수 있어요:

bin/fetch-configlet
bin/configlet create --practice-exercise <slug>

자세한 내용은 configlet create 문서를 확인해 봐요.

메타데이터

연습 문제 메타데이터는 config.json 파일의 exercises.practice 키에 정의돼요. 메타데이터에는 연습 문제의 UUID, 슬러그 등이 담겨요.

예시

{
  "exercises": {
    "practice": [
      {
        "uuid": "8ba15933-29a2-49b1-a9ce-70474bad3007",
        "slug": "leap",
        "name": "Leap",
        "practices": ["if-statements", "numbers", "operator-precedence"],
        "prerequisites": ["if-statements", "numbers"],
        "difficulty": 1
      }
    ]
  }
}

practices

practices 키에는 이 연습 문제를 통해 학습자가 실제로 연습할 수 있는 개념의 슬러그를 나열해요.

  • 이 내용은 UI에 "이 개념을 연습할 수 있는 문제: TwoFer, Leap 등"으로 표시돼요.
  • 개념마다 연습 문제를 3~8개 정도 고르는 게 좋아요.
  • 또 각 개념의 기초를 연습할 수 있는 연습 문제를 최소 두 개는 고르는 게 좋아요.
  • 개념 중에는 아주 흔한 것도 있어요(예: strings). 이런 경우에는 그 개념을 흥미로운 방식으로 생각해 보게 만드는 좋은 연습 문제 몇 개를 고르는 걸 추천해요. 예를 들어 UTF-8, 문자열 연결, 문자 순회 등이 필요한 연습 문제라면 모두 좋은 예시예요.

prerequisites

prerequisites 키에는 이 연습 문제에 접근하려면 학습자가 반드시 완료해야 하는 개념이 나열돼요.

  • 이 내용은 UI에 "TwoFer를 잠금 해제하려면 Strings를 배우세요"처럼 표시돼요.
  • 적어도 한 가지 관용적인 방식으로 연습 문제를 완료하는 데 학습자가 알아야 할 개념을 모두 포함해야 해요. 예를 들어 Ruby의 TwoFer 연습 문제라면 선수 개념에 strings, optional-params, implicit-return 등이 포함될 수 있어요.
  • 다른 개념으로도 완료할 수 있는 연습 문제(예: loops나 recursion으로 풀 수 있는 문제)라면, 유지보수자는 학습자가 트랙을 따라가는 흐름을 고려해 그 연습 문제의 잠금을 해제할 한 가지 접근법을 골라야 해요. 예를 들어 루프/재귀 예시라면 이 연습 문제가 loops를 일찍 연습하기에 좋다고 생각할 수도 있고, 재귀를 가르치기 위해 나중으로 미루고 싶을 수도 있어요. 분석기를 활용해 학습자에게 다른 접근법을 시도해 보라고 안내할 수도 있어요: "루프로 잘 푸셨어요. 재귀를 사용해서 푸는 것도 시도해 보세요."

파일

연습 문제마다 트랙의 exercises/practice 디렉터리 안에 각자의 디렉터리가 있어요. 연습 문제 디렉터리 이름은 config.json 파일에 정의된 연습 문제의 slug 속성과 일치해야 해요.

연습 문제에는 네 가지 종류의 파일이 있어요:

문서 파일

이 파일들은 연습 문제를 설명하는 데 도움이 되도록 학습자에게 제공돼요.

  • .docs/introduction.md: 연습 문제의 상황과 배경을 소개해요(선택)
  • .docs/introduction.append.md: 기존 소개 뒤에 덧붙일 추가 소개 텍스트예요(선택)
  • .docs/instructions.md: 연습 문제의 지시문을 제공해요(필수)
  • .docs/instructions.append.md: 기존 지시문 뒤에 덧붙일 추가 텍스트예요(선택)
  • .docs/hints.md: 학습자가 연습 문제에서 막혔을 때 벗어날 수 있도록 힌트를 제공해요(선택)

메타데이터 파일

이 파일들은 학습자에게 제공되지 않고, 연습 문제의 메타데이터를 정의하는 데 사용돼요.

  • .meta/config.json: 연습 문제에 대한 메타 정보를 담고 있어요(필수)
  • .meta/design.md: 연습 문제의 설계를 설명해요(선택)
  • .meta/tests.toml: 어떤 테스트가 구현됐는지에 대한 정보를 담고 있어요(선택)

접근법 파일

이 파일들은 연습 문제의 접근법을 설명해요.

  • .approaches/introduction.md: 연습 문제에서 가장 흔한 접근법을 소개해요(선택)
  • .approaches/config.json: 접근법의 메타데이터예요(선택)
  • .approaches/<approach-slug>/content.md: 접근법에 대한 설명이에요(선택)
  • .approaches/<approach-slug>/snippet.txt: 접근법을 보여 주는 스니펫이에요(선택)

아티클 파일

이 파일들은 연습 문제의 아티클을 설명해요.

  • .articles/config.json: 아티클의 메타데이터예요(선택)
  • .articles/<article-slug>/content.md: 아티클에 대한 설명이에요(선택)
  • .articles/<article-slug>/snippet.md: 아티클을 보여 주는 스니펫이에요(선택)

연습 문제 파일

구현 파일과 테스트 파일처럼 언어에 특화된 파일이에요. 이 파일들의 이름은 트랙마다 달라요.

  • 테스트 스위트: 풀이의 정확성을 검증해요.
  • 스텁 구현: 학습자에게 시작점을 제공해요.
  • 예시 구현: 모든 테스트를 통과하는 예시 구현을 제공해요.
  • 추가 파일: 테스트를 실행할 수 있게 해줘요.

예시

exercises
└── practice
    └── isogram
        ├── .approaches
        |   ├── for-loop
        |   |   ├── content.md
        |   |   └── snippet.txt
        |   ├── config.json
        |   └── introduction.md
        ├── .articles
        |   ├── performance
        |   |   ├── content.md
        |   |   └── snippet.md
        |   └── config.json
        ├── .docs
        |   ├── introduction.md
        |   ├── instructions.md
        |   └── hints.md
        ├── .meta
        |   ├── config.json
        |   ├── design.md
        |   ├── tests.toml
        |   └── Example.cs (example implementation)
        ├── Isogram.cs (stub implementation)
        └── IsogramTests.cs (tests)

파일: .docs/introduction.md

목적: 학습자에게 연습 문제의 상황과 배경을 소개해요.

포함 여부: 연습 문제가 introduction.md 파일을 가진 Problem Specifications 연습 문제를 구현하는 경우 필수

연습 문제가 Problem Specifications 연습 문제를 구현한다면, 이 파일의 내용은 Problem Specifications 연습 문제의 introduction.md 파일과 일치해야 해요. configlet에는 이 파일의 내용을 자동으로 동기화하는 기능이 있어요.

연습 문제가 Problem Specifications 연습 문제를 기반으로 하지 않는다면 다음을 고려해 봐요:

우리는 Exercism의 콘텐츠를 누구나 안전하게 접할 수 있도록 만드는 것을 중요하게 생각하기 때문에, 이야기가 적절한지 판단할 때 신중한 쪽을 택하는 편이에요. 무엇을 병합할지 살필 때도 조심하지만, 무엇이 문제로 보일지는 알아채기 어렵다는 점을 잘 알고 있어요. 그래서 항상 좋은 의도로 하고 있다고 믿고, 검토 과정에서 문제를 마주해도 대립하지 않는 방식으로 잡아내려고 노력해요. 어떤 이야기를 우리와 함께 확인하고 싶다면 @exercism/leadership을 언급해 주세요. 함께 살펴볼게요. 몇 가지 지침이 있어요:

  • 그 이야기가 누구에게나 친근하고 누구나 이해할 수 있는지 확인해 봐요. 내부 농담이나 지역 속어가 들어 있다면 다른 표현을 떠올려 봐요.
  • 모든 사람을 포용하는 예시를 쓰도록 해요. 예를 들어 다른 문화권의 이름이나 다양한 성별을 사용하는 것을 고려해 봐요.
  • 그 이야기 때문에 기분이 상할 만한 사람을 실제로 아는지 스스로에게 물어봐요. 그렇다면 그런 일이 없도록 이야기를 바꾸는 것을 고려해 봐요.

예시

# Introduction

Bob is a lackadaisical teenager. In conversation, his responses are very limited.

파일: .docs/introduction.append.md

목적: 기존 소개 뒤에 덧붙일 추가 소개 텍스트예요.

포함 여부: 선택

드물게 연습 문제의 introduction.md 파일을 확장하고 싶을 때가 있어요. 예를 들어 기존 지시문이 다루지 않는 테스트를 연습 문제에 구현한 경우예요.

Bob이 ASCII가 아닌 메시지를 지원하지 않게 하고 싶은 트랙이라면 다음과 같이 추가할 수 있어요:

# Introduction append

## Note

As part of his teenage rebellion, Bob has decided to only communicate using ASCII.

덧붙임 파일은 H1 헤더로 시작해야 해요. 이 헤더는 화면에 표시되지 않지만 그래도 있어야 해요. H1 헤더 뒤에는 보통 H2 헤더가 오는데, 이는 일반적인 내용과 트랙에 특화된 내용을 구분하는 데 도움이 돼요.

파일: .docs/instructions.md

목적: 연습 문제의 지시문을 제공해요.

포함 여부: 필수

연습 문제가 Problem Specifications 연습 문제를 구현한다면, 이 파일의 내용은 Problem Specifications 연습 문제의 instructions.md 파일(instructions.md 파일이 없다면 description.md 파일)과 일치해야 해요. configlet에는 이 파일의 내용을 자동으로 동기화하는 기능이 있어요.

연습 문제가 Problem Specifications 연습 문제를 기반으로 하지 않는다면 다음을 고려해 봐요:

우리는 Exercism의 콘텐츠를 누구나 안전하게 접할 수 있도록 만드는 것을 중요하게 생각하기 때문에, 이야기가 적절한지 판단할 때 신중한 쪽을 택하는 편이에요. 무엇을 병합할지 살필 때도 조심하지만, 무엇이 문제로 보일지는 알아채기 어렵다는 점을 잘 알고 있어요. 그래서 항상 좋은 의도로 하고 있다고 믿고, 검토 과정에서 문제를 마주해도 대립하지 않는 방식으로 잡아내려고 노력해요. 어떤 이야기를 우리와 함께 확인하고 싶다면 @exercism/leadership을 언급해 주세요. 함께 살펴볼게요. 몇 가지 지침이 있어요:

  • 그 이야기가 누구에게나 친근하고 누구나 이해할 수 있는지 확인해 봐요. 내부 농담이나 지역 속어가 들어 있다면 다른 표현을 떠올려 봐요.
  • 모든 사람을 포용하는 예시를 쓰도록 해요. 예를 들어 다른 문화권의 이름이나 다양한 성별을 사용하는 것을 고려해 봐요.
  • 그 이야기 때문에 기분이 상할 만한 사람을 실제로 아는지 스스로에게 물어봐요. 그렇다면 그런 일이 없도록 이야기를 바꾸는 것을 고려해 봐요.

예시

# Instructions

Bob answers 'Sure.' if you ask him a question, such as "How are you?".

He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).

He answers 'Calm down, I know what I'm doing!' if you yell a question at him.

He says 'Fine. Be that way!' if you address him without actually saying anything.

He answers 'Whatever.' to anything else.

파일: .docs/instructions.append.md

목적: 기존 지시문 뒤에 덧붙일 추가 지시문 텍스트예요.

포함 여부: 선택

드물게 연습 문제의 instructions.md 파일을 확장하고 싶을 때가 있어요. 예를 들어 기존 지시문이 다루지 않는 테스트를 연습 문제에 구현한 경우예요.

# Instructions append

## Note

Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.

덧붙임 파일은 H1 헤더로 시작해야 해요. 이 헤더는 화면에 표시되지 않지만 그래도 있어야 해요. H1 헤더 뒤에는 보통 H2 헤더가 오는데, 이는 일반적인 내용과 트랙에 특화된 내용을 구분하는 데 도움이 돼요.

파일: .docs/hints.md

목적: 학습자가 연습 문제에서 막혔을 때 벗어날 수 있도록 힌트를 제공해요.

포함 여부: 선택

  • 학습자가 막히면 힌트를 요청하는 버튼을 눌러서 파일의 관련 부분을 볼 수 있게 해줘요.
  • 힌트는 제목 아래에 글머리 기호로 나열해야 해요.
  • 힌트는 거의 모든 학습자가 막힘을 풀 수 있을 만큼 충분해야 해요.
  • 힌트는 풀이를 그대로 알려 주지 않고, 풀이를 설명하는 자료를 가리켜야 해요(예: 사용할 함수의 문서로 연결).
  • 힌트는 개념을 설명하기 위해 코드 예시를 쓸 수 있지만, 풀이의 개요를 드러내는 데는 쓰면 안 돼요. 예를 들어 배열 연습 문제라면 특정 배열 함수가 어떻게 동작하는지 보여 주는 코드 조각은 괜찮지만, 그대로 복사해서 풀이에 붙여 넣을 수 있는 형태여서는 안 돼요.
  • 힌트는 ## General 제목 아래에 Markdown 목록으로 나타나야 해요.
  • 힌트가 없으면 이 제목은 생략해요.

힌트 보기는 "권장" 경로가 아니며, 학습자가 힌트 없이는 진행할 수 없을 때를 빼고는 (가볍게) 사용을 말리는 편이에요. 그러니 힌트를 읽는 학습자는 다소 혼란스럽거나 벅차하고 어쩌면 답답함을 느낄 수 있다는 점을 염두에 두면 좋아요.

예시

## General

- There are many [built-in methods][integers] to simplify working with integers.

[integers]: https://ruby-doc.org/core-2.7.0/Integer.html

파일: .meta/design.md

목적: 연습 문제의 설계를 설명해요.

포함 여부: 선택

이 파일에는 연습 문제의 설계에 대한 정보가 담겨 있어요. 목표, 교육 목표, 가르치지 말아야 할 것 등이 포함돼요.

이 파일은 나중에 이 연습 문제를 맡을 유지보수자나 기여자에게 연습 문제의 범위와 한계를 알려 주기 위해 있어요. 시간이 지나면서 연습 문제가 점점 복잡해지는 자연스러운 흐름을 막기 위해서예요.

예시

# Design

## Goal

The goal of this exercise is help students practice how to work with strings.

## Notes

This exercise does not contain any error handling tests.

파일: .meta/config.json

목적: 연습 문제에 대한 메타 정보를 담고 있어요.

포함 여부: 필수

이 파일에는 연습 문제에 대한 메타 정보가 담겨 있어요:

  • authors: 연습 문제 작성자의 GitHub 사용자 이름이에요(선택)
    • 리뷰가 연습 문제를 실질적으로 바꿔서 "함께 만들어 낸" 느낌이 들 정도라면 리뷰어도 포함해요.
  • contributors: 연습 문제 기여자의 GitHub 사용자 이름이에요(선택)
    • 리뷰가 의미 있거나 실행에 옮길 만하거나 실제로 반영된 경우에는 리뷰어도 포함해요.
  • files: 이 연습 문제에서 사용하는 파일의 위치를 연습 문제 디렉터리 기준으로 나타내요(필수)
    • solution: 스텁 구현 파일이에요(필수)
    • test: 테스트 파일이에요(필수)
    • example: 예시 구현 파일이에요(필수)
    • editor: 편집기에 읽기 전용으로 표시되는 추가 파일이에요(선택)
    • invalidator: 변경되면 풀이가 최신 상태가 아니게 되는 파일이에요(선택)
  • language_versions 언어 버전 요구 사항이에요(선택)
  • blurb: 이 연습 문제에 대한 짧은 설명이에요. 길이는 350 이하여야 해요. Markdown은 지원하지 않아요(필수)
  • source: 이 연습 문제가 기반으로 한 출처예요(선택)
  • source_url: 이 연습 문제가 기반으로 한 출처의 URL이에요(선택)
  • test_runner: 이 연습 문제의 풀이를 테스트 러너에서 테스트해야 하는지를 나타내요. 지정하지 않으면 true가 기본값이에요. (선택)
  • representer: 리프리젠터가 이 파일을 처리하는 방식과 관련된 메타 정보예요(선택)
    • version: 연습 문제에 사용할 리프리젠터의 버전을 나타내는 정수예요(상위 키가 있으면 필수)
  • icon: 아이콘의 슬러그예요(전체 아이콘 목록 참고). 지정하지 않으면 연습 문제의 슬러그가 사용돼요(선택)
  • custom: 연습 문제에 특화된 비표준 데이터예요. 연습 문제별로 트랙 도구의 동작을 사용자 정의하는 데 쓸 수 있어요(선택)

어떤 사람이 작성자이면서 동시에 기여자라면, 그 사람은 작성자로만 적어요.

예시

{
  "authors": ["FSharpForever"],
  "files": {
    "solution": ["Bob.fs"],
    "test": ["BobTests.fs"],
    "example": [".meta/Example.fs"]
  },
  "blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited"
}

참고하세요:

  • 작성자와 기여자의 순서는 중요하지 않고 아무 의미도 없어요.
  • language_versions는 자유 형식의 문자열로, 트랙에서 자유롭게 사용하고 해석할 수 있어요.

파일: .meta/tests.toml

목적: 어떤 테스트가 구현됐는지에 대한 정보를 담고 있어요.

포함 여부: 선택

이 파일에는 어떤 테스트가 구현되는지에 대한 정보가 담겨 있어요. 단, 연습 문제가 problem-specifications 저장소의 canonical-data.json 파일에 테스트를 정의한 경우에만 해당해요.

이 파일은 유지보수자가 어떤 테스트가 구현됐는지 추적하고, (선택적으로) 특정 테스트를 구현하지 않은 이유를 기록하는 데 도움이 돼요. 아직 구현되지 않은 테스트를 찾아내는 데도 쓸 수 있어요.

configlet 도구는 configlet sync 명령을 통해 problem-specifications 저장소의 데이터와 이 파일을 업데이트/동기화해요. 동기화할 때 configlet은 구현되지 않은 테스트마다 그 테스트를 포함할지 물어봐요.

예시

# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[3e5c30a8-87e2-4845-a815-a49671ade970]
description = "empty strand"

[a0ea42a6-06d9-4ac6-828c-7ccaccf98fec]
description = "can count one nucleotide in single-character input"

[eca0d565-ed8c-43e7-9033-6cefbf5115b5]
description = "strand with repeated nucleotide"

[40a45eac-c83f-4740-901a-20b22d15a39f]
description = "strand with multiple nucleotides"

[b4c47851-ee9e-4b0a-be70-a86e343bd851]
description = "strand with invalid nucleotides"
include = false
comment = "error handling omitted on purpose"

파일: .approaches/introduction.md

목적: 연습 문제에서 가장 흔한 접근법을 소개해요

포함 여부: 선택

이 파일은 연습 문제에서 가장 흔한 접근법을 설명해요. 이 파일에 무엇을 담아야 하는지 자세히 알고 싶다면 문서를 확인해 봐요.

예시

# Introduction

The key to this exercise is to deal with C# strings being immutable, which means that a `string`'s value cannot be changed.
Therefore, to reverse a string you'll need to create a _new_ `string`.

## Using LINQ

```csharp
public static string Reverse(string input)
{
    return new string(input.Reverse().ToArray());
}
```

For more information, check the [LINQ approach][approach-linq].

## Which approach to use?

If readability is your primary concern (and it usually should be), the LINQ-based approach is hard to beat.

파일: .approaches/config.json

목적: 접근법의 메타데이터예요

포함 여부: 선택(접근법 소개나 접근법이 있으면 필수)

이 파일에는 연습 문제의 접근법에 대한 메타 정보가 담겨 있어요:

  • introduction: 연습 문제 접근법 소개의 작성자 GitHub 사용자 이름이에요(선택)

    • authors: 연습 문제 접근법 소개 작성자의 GitHub 사용자 이름이에요(필수)
      • 리뷰가 연습 문제 접근법 소개를 실질적으로 바꿔서 "함께 만들어 낸" 느낌이 들 정도라면 리뷰어도 포함해요.
    • contributors: 연습 문제 접근법 소개의 기여자 GitHub 사용자 이름이에요(선택)
      • 리뷰가 의미 있거나 실행에 옮길 만하거나 실제로 반영된 경우에는 리뷰어도 포함해요.
  • approaches: 자세한 접근법을 나열하는 배열이에요(선택)

    • uuid: 접근법을 고유하게 식별하는 V4 UUID예요. UUID는 트랙 안에서도, 모든 트랙을 통틀어서도 고유해야 하며 절대 바뀌면 안 돼요.
    • slug: 접근법의 슬러그로, 소문자 케밥 케이스 문자열이에요. 슬러그는 트랙 안의 모든 접근법 슬러그 중에서 고유해야 해요. 길이는 255 이하여야 해요.
    • title: 접근법의 제목이에요. 길이는 255 이하여야 해요.
    • blurb: 이 접근법에 대한 짧은 설명이에요. 길이는 350 이하여야 해요. Markdown은 지원하지 않아요(필수)
    • authors: 연습 문제 접근법 작성자의 GitHub 사용자 이름이에요(필수)
      • 리뷰가 연습 문제 접근법을 실질적으로 바꿔서 "함께 만들어 낸" 느낌이 들 정도라면 리뷰어도 포함해요.
    • contributors: 연습 문제 접근법 기여자의 GitHub 사용자 이름이에요(선택)
      • 리뷰가 의미 있거나 실행에 옮길 만하거나 실제로 반영된 경우에는 리뷰어도 포함해요.
    • tags: 제출물이 언제 접근법에 연결되는지 조건을 지정해요. (선택)
      • all: 제출물에 모두 있어야 하는 태그의 배열이에요(any에 요소가 없는 경우를 제외하면 선택).
      • any: 제출물에 최소 하나는 있어야 하는 태그의 배열이에요(all에 요소가 없는 경우를 제외하면 선택).
      • not: 제출물에 이 태그가 하나도 없어야 해요(선택).

예시

{
  "introduction": {
    "authors": ["erikschierboom"]
  },
  "approaches": [
    {
      "uuid": "448fb2b4-18ab-4e55-aa54-ad4ed6d5f7f6",
      "slug": "span",
      "title": "Use Span<T>",
      "blurb": "Use Span<T> to efficiently reverse a string.",
      "authors": ["erikschierboom"]
    }
  ]
}

파일: .approaches/<approach-slug>/content.md

목적: 접근법에 대한 자세한 설명이에요

포함 여부: 선택(접근법에는 필수)

이 파일에는 접근법에 대한 자세한 설명이 담겨 있어요. 이 파일에 무엇을 담아야 하는지 자세히 알고 싶다면 문서를 확인해 봐요.

예시

# Span

```csharp
Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
    chars[input.Length - 1 - i] = input[i];
}
return new string(chars);
```

This `Span<T>` approach uses a `for` loop.

파일: .approaches/<approach-slug>/snippet.txt

목적: 접근법을 보여 주는 스니펫이에요

포함 여부: 선택(접근법에는 필수)

이 파일에는 접근법을 보여 주는 작은 스니펫이 담겨 있어요. 스니펫은 연습 문제의 더 깊이 알아보기 페이지에 표시돼요.

줄 수는 8 이하여야 해요.

이 파일에 무엇을 담아야 하는지 자세히 알고 싶다면 문서를 확인해 봐요.

예시

Span<char> chars = stackalloc char[input.Length];
for (var i = 0; i < input.Length; i++)
{
    chars[input.Length - 1 - i] = input[i];
}
return new string(chars);

파일: .article/config.json

목적: 아티클의 메타데이터예요

포함 여부: 선택(아티클이 있으면 필수)

이 파일에는 연습 문제의 아티클에 대한 메타 정보가 담겨 있어요:

  • articles: 자세한 아티클을 나열하는 배열이에요(선택)
    • uuid: 아티클을 고유하게 식별하는 V4 UUID예요. UUID는 트랙 안에서도, 모든 트랙을 통틀어서도 고유해야 하며 절대 바뀌면 안 돼요.
    • slug: 아티클의 슬러그로, 소문자 케밥 케이스 문자열이에요. 슬러그는 트랙 안의 모든 아티클 슬러그 중에서 고유해야 해요. 길이는 255 이하여야 해요.
    • title: 아티클의 제목이에요. 길이는 255 이하여야 해요.
    • blurb: 이 아티클에 대한 짧은 설명이에요. 길이는 350 이하여야 해요. Markdown은 지원하지 않아요(필수)
    • authors: 연습 문제 아티클 작성자의 GitHub 사용자 이름이에요(필수)
      • 리뷰가 연습 문제 아티클을 실질적으로 바꿔서 "함께 만들어 낸" 느낌이 들 정도라면 리뷰어도 포함해요.
    • contributors: 연습 문제 아티클 기여자의 GitHub 사용자 이름이에요(선택)
      • 리뷰가 의미 있거나 실행에 옮길 만하거나 실제로 반영된 경우에는 리뷰어도 포함해요.

예시

{
  "articles": [
    {
      "uuid": "6db71962-62d5-448b-a980-c20ae41013ed",
      "slug": "performance",
      "title": "Optimizing performance",
      "blurb": "Explore how to most efficiently reverse a string and what the trade-offs are.",
      "authors": ["erikschierboom"]
    }
  ]
}

파일: .articles/<article-slug>/content.md

목적: 아티클에 대한 자세한 설명이에요

포함 여부: 선택(아티클에는 필수)

이 파일에는 아티클에 대한 자세한 설명이 담겨 있어요. 이 파일에 무엇을 담아야 하는지 자세히 알고 싶다면 문서를 확인해 봐요.

예시

# Performance

In this document, we'll find out which approach is the most performant one.

## Benchmark results

| Method |      Mean |     Error |    StdDev |    Median | Allocated |
| -----: | --------: | --------: | --------: | --------: | --------: |
|   Linq | 29.133 ns | 0.5865 ns | 0.5486 ns | 28.984 ns |      80 B |
|  Array |  4.806 ns | 0.4999 ns | 1.4739 ns |  3.967 ns |         - |

파일: .articles/<article-slug>/snippet.txt

목적: 아티클을 보여 주는 스니펫이에요

포함 여부: 선택(아티클에는 필수)

이 파일에는 아티클을 보여 주는 작은 스니펫이 담겨 있어요. 스니펫은 연습 문제의 더 깊이 알아보기 페이지에 표시돼요.

줄 수는 8 이하여야 해요.

이 파일에 무엇을 담아야 하는지 자세히 알고 싶다면 문서를 확인해 봐요.

예시

| Method |      Mean | Allocated |
| -----: | --------: | --------: |
|   Linq | 29.133 ns |      80 B |
|  Array |  4.806 ns |         - |

파일: 스텁 구현

목적: 학습자에게 시작점을 제공해요.

포함 여부: 필수

  • 학습자가 어디에 코드를 추가해야 할지 알 수 있도록 스텁을 설계해요.
  • 컴파일 언어라면 컴파일되는 코드를 두는 것을 고려해 봐요. 그 언어를 처음 접하는 학습자에게는 컴파일러 메시지가 때때로 이해하기 어려울 수 있어요.
  • 코드는 가능한 한 단순해야 해요.
  • 선수 개념(그리고 그 선수 개념의 선수 개념 등)에서 소개된 언어 기능만 사용해요.
  • 스텁 파일은 브라우저에서 코딩할 때 학습자에게 표시되고, CLI를 사용할 때는 학습자의 파일 시스템으로 내려받아져요.
  • 스텁 구현 파일의 상대 경로는 .meta/config.json 파일의 "files.solution" 키에 지정해야 해요.

예시

using System;

public static class Isogram
{
    public static bool IsIsogram(string word)
    {
        throw new NotImplementedException("You need to implement this function.");
    }
}

파일: 테스트

목적: 풀이의 정확성을 검증해요.

포함 여부: 필수

  • 코드는 가능한 한 단순해야 해요.
  • 연습 문제의 선수 개념(그리고 그 선수 개념의 선수 개념 등)에서 소개된 언어 기능만 사용해요.
  • 테스트 파일은 브라우저에서 코딩할 때 학습자에게 표시되고, CLI를 사용할 때는 학습자의 파일 시스템으로 내려받아져요.
  • Exercism은 연습 문제를 테스트 주도 개발로 완성하는 방식을 선호해요. 이를 위해 두 가지 방법이 있어요:
    • 테스트 러너가 파일에 정의된 순서대로 테스트를 실행해야 하고, 테스트 스위트가 첫 실패에서 중단해야 해요. 또는
    • 첫 번째 테스트를 제외한 나머지는 기본적으로 건너뛰어야 해요.
  • 테스트 파일의 상대 경로는 .meta/config.json 파일의 "files.test" 키에 지정해야 해요.

예시

using Xunit;

public class IsogramTest
{
    [Fact]
    public void Empty_string() =>
        Assert.True(Isogram.IsIsogram(""));

    [Fact(Skip = "Remove this Skip property to run this test")]
    public void Isogram_with_only_lower_case_characters() =>
        Assert.True(Isogram.IsIsogram("isogram"));

    [Fact(Skip = "Remove this Skip property to run this test")]
    public void Word_with_one_duplicated_character() =>
        Assert.False(Isogram.IsIsogram("eleven"));
}

파일: 예시 구현

목적: 모든 테스트를 통과하는 예시 구현을 제공해요.

포함 여부: 필수

  • 이 구현은 테스트를 통과하는 구현이 존재하는지 확인하는 데 쓰여요. 학습자가 목표로 삼기를 바라는 코드가 아니라는 점은 의도된 거예요.
  • 각 트랙은 자신의 지속적 통합 환경에서 예시 구현이 테스트를 통과하는지 확인해야 해요.
  • 멘토에게는 이 코드가 표시되지 않아요.
  • 예시 파일은 브라우저에서 코딩할 때 학습자에게 표시되지 않고, CLI를 사용할 때 학습자의 파일 시스템으로 내려받아지지도 않아요.
  • 예시 구현 파일의 상대 경로는 .meta/config.json 파일의 "files.example" 키에 지정해야 해요.

예시

using System.Linq;

public static class Isogram
{
    public static bool IsIsogram(string word)
    {
        var lowerCaseLetters = word.ToLower().Where(char.IsLetter).ToList();
        return lowerCaseLetters.Distinct().Count() == lowerCaseLetters.Count;
    }
}

파일: 추가 파일

목적: 테스트를 실행하는 데 필요한 추가 프로젝트, 빌드 또는 지원 파일이에요.

포함 여부: 기본 파일만으로는 테스트를 실행할 수 없을 때 필수

일부 언어는 테스트를 실행하려면 추가 파일이 필요해요. C#의 프로젝트 파일이나 Node의 package.json 파일이 그 예인데, 이런 파일이 없으면 테스트를 실행할 수 없어요.

공유 파일

일부 파일은 개별 연습 문제에만 해당하지 않고 모든 연습 문제에 적용돼요. 자세한 내용은 문서를 확인해 봐요.

표시 방식

브라우저 편집기를 사용할 때와 CLI를 사용할 때 연습 문제 문서가 학습자에게 표시되는 방식에는 차이가 있어요. 자세한 내용은 이 문서를 참고해요.

아이콘

연습 문제마다 함께 제공되는 아이콘이 있어요. 기본적으로는 이름이 연습 문제의 슬러그와 일치하는 아이콘이 표시돼요. 연습 문제의 .meta/config.json 파일에 icon 속성을 지정하면 이를 바꿀 수 있어요.

problem-specifications 메타데이터에서 가져온 연습 문제를 구현하고 있다면, 그 연습 문제에 쓸 아이콘이 이미 있을 가능성이 높아요. 없다면 website-icons 저장소에 이슈를 열어 주세요.