기본적으로 내장 함수의 이름을 바꾸는 함수를 만드는 것은 바람직하지 않습니까?


40

특정 상황에서 최소 및 최대 기능에 대해 혼란스러워합니다.

한 가지 맥락에서 함수를 사용하여 두 값 중 더 크거나 작은 값을 사용하면 문제가 없습니다. 예를 들어

//how many autographed CD's can I give out?
int howManyAutographs(int CDs, int Cases, int Pens)
{
    //if no pens, then I cannot sign any autographs
    if (Pens == 0)
        return 0;

    //I cannot give away a CD without a case or a case without a CD
    return min(CDs, Cases);
}

쉬운. 그러나 다른 맥락에서, 나는 혼란스러워합니다. 최대 또는 최소를 설정하려고하면 뒤로 가져옵니다.

//return the sum, with a maximum of 255
int cappedSumWRONG(int x, int y)
{
    return max(x + y, 255); //nope, this is wrong
}

//return the sum, with a maximum of 255
int cappedSumCORRECT(int x, int y)
{
    return min(x + y, 255); //much better, but counter-intuitive to my mind
}

다음과 같이 내 기능을 만드는 것이 바람직하지 않습니까?

//return x, with a maximum of max
int maximize(int x, int max)
{
    return min(x, max);
}

//return x, with a minimum of min
int minimize(int x, int min)
{
    return max(x, min)
}

분명히, 내장을 사용하는 것이 더 빠를 것이지만 이것은 나에게 불필요 한 미세 최적화처럼 보입니다. 이것이 바람직하지 않은 다른 이유가 있습니까? 그룹 프로젝트는 어떻습니까?


72
min과 max가 가독성을 떨어 뜨리는 경우 일반 "if"로 바꾸고 교체하십시오. 가독성을 높이기 위해 약간 더 많은 코드를 작성해야 할 때가 있습니다.
T. Sar-복원 모니카

23
하나의 짧은 게시물로 "깨끗한 코딩"의 전체 개념을 파괴했습니다. 경례합니다!
Ewan

21
아마도 C ++ 11 std::clamp함수 또는 이와 유사한 것을 고려할 수 있습니다 .
rwong

15
아마도 더 좋은 이름은 up_to(for min)와 at_least(for max)일까요? 나는 그들이 minimize왜 정답인지 깨닫는 데 약간의 시간이 걸릴 수 있지만, 그보다 더 나은 의미를 전달 한다고 생각합니다.
Warbo 2016 년

59
min그리고 max또한 minimizemaximize당신이 쓰고 싶은 기능에 대한 완전히 잘못된 이름입니다. 기본값 min이며 max훨씬 더 의미가 있습니다. 실제로 ALMOST는 함수 이름을 올바르게 가지고 있습니다. 이 작업을 클램핑 또는 캡핑이라고하며 두 개의 캡핑 기능을 작성했습니다. 제안 capUpperBound하고 싶습니다 capLowBound. 어느 누구에게 어떤 일을하는지 설명 할 필요가 없습니다.
slebetman

답변:


120

다른 사람들이 이미 언급했듯이 : 내장 된 표준 라이브러리 또는 일반적으로 널리 사용되는 함수와 유사한 이름으로 함수를 만들지 말고 동작을 변경하십시오. 첫눈에 이해가되지 않더라도 명명 규칙에 익숙해 질 수는 있지만 동일한 기능을 수행하지만 그들의 이름이 바뀌었다.

표준 라이브러리에서 사용하는 이름을 "오버로드"하는 대신 정확하게 의미를 전달하는 새로운 이름을 사용하십시오. 귀하의 경우에는“최소한”에 관심이 없습니다. 오히려, 당신 은 가치 를 정하고 싶습니다 . 수학적으로 이것은 동일한 작업이지만 의미 적으로는 그렇지 않습니다. 왜 함수가 아닌가?

int cap(int value, int limit) { return (value > limit) ? limit : value; }

그것은 필요한 것을 수행하고 그 이름으로 알려줍니다. (당신은 또한 timster답변에 표시된 것과 같은 cap측면에서 구현할 수 있습니다 ).min

자주 사용되는 다른 기능 이름은 clamp입니다. 세 개의 인수를 사용하고 제공된 두 값을 다른 두 값으로 정의 된 간격으로 "클램프"합니다.

int clamp(int value, int lower, int upper) {
    assert(lower <= upper);  // precondition check
    if (value < lower) return lower;
    else if (value > upper) return upper;
    else return value;
}

일반적으로 알려진 함수 이름을 사용하는 경우 팀에 합류하는 새로운 사람 (잠깐 후에 코드로 돌아 오는 미래를 포함하여)은 자신을 혼란스럽게해서 혼란스러워서 저주하는 대신 무슨 일이 일어나고 있는지 빠르게 이해합니다. 그들이 알고 있다고 생각한 기능 명에 대한 기대.


2
getValueNotBiggerThan (x, limit)라는 이름을 지정할 수도 있습니다. 이것이 올바른 접근 방식이며, 알맞은 컴파일러를 사용하면 함수가 인라인되고 결과로 생성 된 기계 코드는 내장 기능을 사용하는 것과 정확히 동일합니다.
Falco

20
@Falco 저는“모자”가“보다 큰 가치를 얻지 말라”와 동의어라고 말하고 싶지만 오늘 그 자전거 창고를 그리지 않을 것입니다. ;-)
5gon12eder

1
clamp모든 종류의 신호 처리 및 유사한 작업 (이미지 처리 등)에서 광범위하게 사용되므로 분명히 그렇게 할 것입니다. 상한과 하한이 필요하다고 말하지는 않지만 한 방향으로 만 자주 볼 수 있습니다.
Voo

1
clamp에 대해서도 언급 할 예정이었습니다 . 그리고 올바르게 작성되면 한 방향으로 만 묶기를 원할 때 무한대 / 음의 무한대를 사용할 수 있습니다. 예를 들어, 숫자가 255보다 크지 않도록 (하한은 아님) 확인하려면을 사용 clamp(myNumber, -Infinity, 255)합니다.
Kat

115

where minimize(4, 10)return 10 과 같은 함수를 만들면 동료 프로그래머가 당신을 교살 할 수 있기 때문에 바람직하지 않다고 말하고 싶습니다.

(아마, 그들은 문자 그대로 당신을 교살시키지 않을 것이지만 진지하게 ... 그렇게하지 마십시오.)


2
또한 몇 년 안에이 코드 작업을 다시 시작할 때 최소화를 요청할 때 왜 수치가 틀렸는 지 알아 내기 위해 몇 시간을 소비 할 수도 있습니다.
Paddy

Aww ...이 답변은 정말 멋지고 투표가 많은 의견을 가지고있었습니다. (또한 답변에 대한 첫 번째 의견으로 유머 흐름을 도왔습니다.)
TOOGAM

나는 펀치 카드를 얻고 싶을 것이다 DO NOT( "스핀들, 폴드 또는 절단 금지"에서). 이와 같은 것을 구현 한 사람은 카드를 받게됩니다.
Clockwork-Muse

26

함수의 앨리어싱은 괜찮지 만 기존 용어의 의미를 변경하려고 시도하지 마십시오

그것은의 확인 함수의 별칭을 만들 수 있습니다 - 공통 라이브러리는 모든 시간을 .

그러나 최대 및 최소값을 바꾸어야하는 예와 같이 일반적인 사용법과 반대되는 방식으로 용어를 사용하는 것은 좋지 않습니다. 다른 프로그래머에게는 혼란스럽고, 이러한 용어를 비표준 방식으로 계속 해석하도록 스스로 훈련함으로써 장애를 겪게 될 것입니다.

따라서 귀하의 경우 혼란스럽고 이해하기 쉬운 코드를 작성하는 "최소 / 최대"용어를 포기하십시오.

예제 리팩토링 :

int apply_upper_bound(int x, int y)
{
    return min(x, y);
}


int apply_lower_bound(int x, int y)
{
    return max(x, y)
}

또한 보너스로이 코드를 볼 때마다 프로그래밍 언어에서 최소최대 가 어떻게 사용 되는지 상기시켜줍니다 . 결국, 그것은 당신의 머리에 이해가 될 것입니다.


4
난 당신의 응용 프로그램을 오해했다고 생각 min하고 max있는 영업을 혼란. 때의 min집합에 사용되는 고정 상단 경계 어떤 가치를. get_lower_value이 응용 프로그램에서와 마찬가지로 직관적입니다. 이 작업의 대체 이름을 선택하려면 supremum 이라고 부릅니다 .하지만 얼마나 많은 프로그래머가 즉시 이해할 수 있는지 잘 모르겠습니다.
leftaroundabout

3
@leftaroundabout : {1, 2} 집합의 최상위 값은 2이므로 위에서 정의 된 supremum함수 의 이름 을 사용하여 get_lower_value호출 하지 마십시오 min. 다음 프로그래머가 호출하는 것과 정확히 같은 문제가 발생합니다 maximise. 나는 그것을 부르는 것이 apply_upper_bound좋지만 그것이 완벽하다는 것을 확신하지 못한다. 매개 변수를 넣는 것과 똑같은 방식으로 작동하기 때문에 여전히 이상하지만, 이름은 매개 변수 중 하나가 "값"이고 다른 하나는 "바운드"이며 어떤 식 으로든 다릅니다.
Steve Jessop

1
나는 당신이 본질적으로 독자에 의존하여 최상이라는 단어에 너무 익숙하지 않기 때문에 영어의 의미보다는 당신의 의미를 취한다고 생각합니다. 전문 용어를 코드에 로컬로 정의하는 것이 좋지만 문제의 요점은 원하는 용어가 이미 익숙한 의미와 직접 모순 될 때 어떻게 해야하는지, 여전히 그렇게하고 있다고 생각합니다. STEM 과목을 공부 한 사람에게만 해당되는 "영어"의 일부 버전)
Steve Jessop

3
이 정책은 "함수의 앨리어싱은 괜찮지 만 기존 용어의 의미를 바꾸려고하지는 않는다" 는 완벽하고 아름답게 표현되었습니다. 둘째, 당신은 기능의 내장과 관련하여 혼동하는 방법으로 이름을 변경하지 말아야한다는 생각 (과 : 경우에도 기능 내장이 제대로 명명 / 바보 / 혼동하는) 완벽한 생각이다. 이 페이지에 나온 최대 / 최소 를 보면 총 혼란입니다.
Fattie

1
좋아, 나는 OP의 추론에 맞고 과부하 용어를 피하는 "apply_upper_bound"를 사용하도록 답을 편집했다. 자세한 정보는 문제가 아닙니다. 여기에 완벽한 메소드 이름을 작성하지 않고 별칭 이름을 지정하기위한 기본 규칙을 설정하십시오. OP는 가장 명확하고 간결한 것으로 편집 할 수 있습니다.
Tim Grant

12

나는이 질문을 좋아한다. 그래도 세분화합시다.

1 : 한 줄의 코드를 포장해야합니까?

예, 당신이 이것을 할 수있는 많은 예를 생각할 수 있습니다. 아마도 형식화 된 매개 변수를 시행하거나 인터페이스 뒤에 구체적인 구현을 숨길 수 있습니다. 귀하의 예에서는 본질적으로 정적 메소드 호출을 숨기고 있습니다.

또한 요즘 한 줄로 많은 일을 할 수 있습니다.

2 : 이름이 '최소'및 '최대'

예! 그들은 완전히 있습니다! 깨끗한 코딩 전문가는 이름을 "FunctionWhichReturnsTheLargestOfItsParameters"또는 다른 이름으로 바꿉니다. 다행히도 우리는 문서와 (운이 좋으면) IntelliSense 와 의견을 통해 이름에 혼란스러워하는 사람이해야 할 일을 읽을 수 있도록 도와줍니다.

3 : 이름을 다른 것으로 바꾸어야합니다.

예,가요 예를 들어, 다음을 가질 수 있습니다.

class Employee
{
    int NumberOfHolidayDaysIShouldHave(int daysInLue, int maxAllowableHolidayDays)
    {
         // Return the number of days in lue, but keep the value under the max allowable holiday days!
         // Don't use max, you fool!!
         return Math.Max(daysInLue, maxAllowableHolidayDays)
    }
}

의미를 추가하고 호출자는 값을 계산하는 방법을 알 필요가 없습니다.

4 : "최소"로 이름을 바꾸어야합니다

아니!! 너 미쳤어?! 그러나 그렇습니다. 문제는 다른 사람들이 다른 의미를 기능과 객체 이름으로 읽는다는 점을 강조합니다. 한 사람이 명확하고 기존의 것을 발견하면 다른 사람은 불투명하고 혼란을 찾습니다. 그렇기 때문에 의견이 있습니다. 대신 다음과 같이 작성해야합니다.

// Add x and y, but don't let it go over 255
s = min(x + y, 255);

그런 다음 누군가가 읽을 때

// Add x and y, but don't let it go over 255
s = max(x + y, 255);

그들은 당신이 실수를했다는 것을 알고 있습니다.


6
이상한! 귀하의 예에서 op와 관련된 정확한 오류를 만들었습니다. 공휴일 수가 maxHolidaysAllowed보다 크지 않기를 원합니다. 따라서 min (a, b)
Falco

14
깨끗한 코드가 진정으로 성가신 이름 FunctionWhichReturnsTheLargestOfItsParameters이 좋은 것을 암시한다면 , 나는 그 일부를 원하지 않습니다.
David Hammen

1
@Falco lol 죄송합니다 !!!
Ewan

4
@DavidHammen : 실제 프로그래밍 스타일이 FunctionWhichReturns모든 함수 앞에 예외를 두지 않기 때문에 실제로는 그렇지 않습니다 (예외를 던지거나 종료하지 않음). 당신은 끝낼 수있다 getMinimum, getLarger(또는 getLargest(가) 순수한 기능 및 / 또는 "게터"는 사마귀를 사용할 필요가있는 라인을 따라 실제 조언에 따라, 2 개 이상의 입력을)하지만 get, (b)는 영어 단어로 축약하지 않아야을 이름. 분명히 그러한 함수를 호출하기로 결정한 사람들에게는 너무 장황합니다 max.
Steve Jessop

1
예, @falco의 의견을 참조하십시오. 나는 그 후에 그것을 정말로 교정 할 수 없었다!
Ewan

4

없음 . 내장 함수와 이름이 비슷한 함수를 만들지 마십시오. 그러나 실제로 는 반대 입니다. 직관적 인 것처럼 보일지 모르지만 다른 개발자, 심지어는 더 많은 경험이있는 사용자에게는 혼란 스러울 것입니다.

의 의미 max는 "최대"이지만 "직관적 인"이해는 "최대"와 같습니다. 그러나 이것은 단순히 잘못된 기능의 이해,에서 이름을 변경입니다 maxmaximum당신의 다른 해석을 전달하지 않습니다. 언어 디자이너들이 실수를했다는 것을 강하게 믿더라도 이런 식으로 행동하지 마십시오.

그러나 cap(x, limit)제안 된대로 이름을 바꾸면 괜찮을 것 min입니다. 포장 된 경우에도 의도를 분명히 전달하기 때문 입니다.


3

혼란 스러울 수있는 것은 함수 이름에 Capped를 사용하거나 캡 배치의 의미를 이해하는 것입니다. 리미터이며 최대 값을 요구하지 않습니다.

가장 낮거나 가장 작거나 가장 빠른 것을 요청받은 경우 Max가 적절한 기능인 것 같습니까?

최소값과 최대 값을 그대로 두십시오. 테스트를 작성하면 최소한 두 번째로 정확 해집니다.

프로젝트에서 이러한 기능을 너무 많이 사용해야하는 경우 사용할 기능을 명확히하는 데 도움이되는 몇 가지 힌트가 제공됩니다. <또는>와 같이 입의 넓은 부분이 더 큰 값을 향합니다.


1
근본적인 문제로 용어 혼동 가능성이 +1입니다. 혼란은 " 최대 255 의 합계를 반환"이라는 주석에서 시작한다고 생각합니다 . 그래서 그는 max함수가 더 적절 하다고 생각 하지만, 논리 min는 그가 실제로 찾고있는 것입니다.
Revenant

2

귀하의 질문에 대답하기 위해 : 이것이 바람직하지 않은 다른 이유가 있습니까? 그룹 프로젝트는 어떻습니까? 자신 만의 기능을 원한다는 것은 당연한 일이지만 문제 없습니다. 그들이 당신의 헬퍼 클래스에 있는지 확인하고 그들이 가져 오지 않으면 다른 사람들이 쉽게 호출 할 수 없도록하십시오. (Joes.Utilities)

그러나 문제를 다시 살펴 보려면 기본적으로 생각하고 있습니다.

return (input >= 255) ? 255 : input;

두뇌 로직을 이러한 최소 / 최대 기능에 적용하려고하기 때문에 혼란스러워합니다. 대신 영어로 말하십시오. ifinput이다 greater than or equal to 255 then return 255, 그렇지 않으면 returninput.

어느 것이 :

if (input >= 255) {
   255 
} else {
   input
}

내 의견 잘못된 이유로 max \ min 함수를 사용하는 경우 이러한 속도는 무시할 수 있습니다. 말이되는 것을하십시오.


1
저의 선임 동료 중 한 사람은 항상 "컴퓨터가 당신을 위해 생각하게하십시오"라고 말하곤했습니다.

1

귀하의 문제를 이해하는 동안이 작업을 꺼려합니다. min ()과 max ()가하는 일을 단순히 두개골에 뚫는 것이 좋습니다.

대부분의 프로그래머는 min () 및 max () 함수의 기능을 알고 있습니다. 심지어 여러분과 마찬가지로 때때로 주어진 시간에 사용할 직관에 어려움을 겪고 있습니다. 프로그램을 읽고 max (x, y)를 보면 즉시 그 기능을 알 수 있습니다. 자신 만의 "별칭"함수를 생성하면 코드를 읽는 다른 사람이이 별칭이 무엇을하는지 알 수 없습니다. 그들은 당신의 기능을 찾아야합니다. 불필요하게 독서의 흐름을 깨뜨리고 독자가 프로그램을 이해하기 위해 추가로 생각하도록 강요합니다.

어느 시점에서 어떤 것을 사용할지 알아내는 데 어려움이 있다면 설명을 추가하십시오. 그런 다음 장래 독자가 비슷하게 혼란 스러울 경우 의견을 정리해야합니다. 또는 당신이 그것을 잘못하지만 주석이 당신이하려는 일을 설명한다면, 그것을 디버깅하려는 사람은 실마리를 가질 것입니다.

이름이 직관과 충돌하기 때문에 함수의 별칭을 지정하면 ... 이것이 유일한 문제입니까? 아니면 다른 기능을 별칭으로 사용 하시겠습니까? "읽기"에 혼란스러워서 "수락"으로 생각하기가 더 쉽다는 것을 발견하고, "첨부"를 "StringTogether"로, "라운드"를 "DropDecimals"로 바꾸는 등의 말을 엄청나게 극단적으로 만듭니다. 그리고 당신의 프로그램은 이해할 수 없을 것입니다.

사실, 몇 년 전에 저는 C의 구두점을 모두 좋아하지 않는 프로그래머와 함께 일했습니다. 그래서 그는 "{"대신 "THEN"과 "}"대신 "THEN"을 쓸 수 있도록 많은 매크로를 작성했습니다. 그리고 다른 수십 개의 다른 치환. 그래서 그의 프로그램을 읽으려고 할 때 더 이상 C처럼 보이지 않았고 완전히 새로운 언어를 배우는 것과 같았습니다. "AND"가 "&"또는 "&&"로 번역되었는지 기억이 나지 않습니다. 그게 요점입니다. 당신은 사람들이 언어와 도서관을 배우기 위해 투자 한 것을 훼손합니다.

즉, 표준 라이브러리 함수를 호출하는 것 외에 다른 기능은 반드시 나쁘다고 말할 수는 없습니다. 함수의 요점이 별칭을 만드는 것이 아니라 단일 함수로 발생하는 동작을 캡슐화하는 것이 좋고 적절할 수 있습니다. 논리적이고 불가피하게 프로그램의이 시점에서 최대 값을 수행해야하는 경우 최대 값을 직접 호출하면됩니다. 그러나 오늘 max를 요구하는 계산을 수행해야하지만 나중에 다른 것을 수행하도록 수정 될 수 있다면 중간 함수가 적합합니다.


0

새로운 이름으로 코드를 명확하게하고 다른 사람이 이해하지 못하는 경우 내장 함수의 이름을 바꾸는 것이 좋습니다. (C / C ++를 사용하는 경우 #define을 사용하면 무슨 일이 일어나고 있는지 알기 어렵습니다.) 함수의 이름은 호출 코드가 수행하는 작업과 수행하는 이유를 설명하는 주석처럼 작동해야합니다. .

당신은 min과 max 에서이 문제를 겪은 유일한 사람은 아니지만 모든 도메인에서 작동하는 좋은 일반적인 솔루션을 아직 보지 못했습니다. 이 함수의 이름을 지정할 때 한 가지 문제는 두 가지 인수가 서로 다른 논리적 의미를 갖지만 동일한 의미로 제시된다는 것입니다.

당신의 언어가 그것을 허용한다면 당신은 시도 할 수 있습니다

return  calculatedDiscount.ButNoMoreThen(maxAllowedDiscount)

return  CDsInStocked.ButNoMoreThen(CasesInStock)

0

아니.

랩퍼를 작성하지 마십시오. 이러한 랩퍼의 이름은 그다지 중요하지 않습니다.

당신이하려는 것은 친절한 코드 난독 화입니다. 2 가지 용도로 사용되는 추가 레이어를 발명했습니다.

  1. 다른 사람들이 귀하의 코드를 이해할 수 없습니다.
  2. 다른 사람의 코드를 이해하는 법을 배우지 않습니다.

편안하지 않은 것을 숨겨두면 현재와 미래의 코드 만 손상시킬 수 있습니다. 당신은 당신의 안락 지대에 머물면서 성장할 수 없습니다. 필요한 것은 방법 minmax작동법 을 배우는 것입니다.


-1

오버, 언더 슈트를 위해 Min, Max를 사용하는 것은 실제로 직관적이지 않습니다. 이것은 또한 다음을 사용하여 수행됩니다.

  • floor ()와 ceil ()
  • 클램프, 한계, 경계
  • 물론 순서 잘림이있는 모드입니다.

펌웨어에서는 MMX보다 오래되었으며,이 확장성에 의존하는 최신 3D 그래픽보다 오래되었습니다.

로컬에서도 산업 표준 기능을 교체하면 걱정할 것입니다. 파생 이름이 더 나을 수 있습니다. C ++ 학생들은 모호한 수업에 과부하가 걸릴 수 있습니다.


죄송합니다. MMX는 무엇입니까?
Tobia Tesan

결과가 한계에 도달하는 "포화 값"을 생각하고있었습니다. 경계 및 오버플로 테스트를 포함 할 필요가없는 경우 코드가 더 간단 할 수 있습니다 (그래픽에서는 과거의 음수 한계를 넘어서 사이클링을 피하거나 긍정적 인 결과를 얻지 못함). PSUBSB / PSUBSW. 나는 메커니즘이 같지 않을 수도 있지만 기능의 효과와 의도는 동일하다고 생각합니다.
mckenzm 2016 년

-1

그것은 어떤 경우에는 괜찮지 만 하지 : 그 단어를 훨씬 더 나은 방법이 있기 때문에, 당신의 예에서
saturate, clamp, clip, 등


-1

차라리 'bounded'라는 일반 함수를 만들고 싶습니다.

//Assumes lower_bound <= upper_bound
template <typename T>
T bounded(T value, T lower_bound, T upper_bound){
    if (value < lower_bound)
        return lower_bound;
    if (value > upper_bound)
        return upper_bound;
    return value;
}

//Checks an upper (by default) or lower bound
template <typename T>
T bounded(T value, T bound, bool is_upper_bound = true){
    if (is_upper_bound){
        if (value > bound)
            return bound;
    }
    else {
        if (value < bound)
            return bound;
    }
    return value;
}

또는 'min'및 'max'를 사용하는 경우

//Assumes lower_bound <= upper_bound
template <typename T>
T bounded(T value, T lower_bound, T upper_bound){
    return max(min(value, upper_bound), lower_bound);
}

//Checks an upper (by default) or lower bound
template <typename T>
T bounded(T value, T bound, bool is_upper_bound = true){
    if (is_upper_bound)
        return min(value, bound);
    else
        return max(value, bound);
}

-1

함수 호출은 어떻습니까 :

atmost(x,255): x 또는 255 이하를 최대한 반환합니다.

atleast(10,x): x보다 높은 값 또는 최소 10을 반환합니다.


-1

min(x+y, MAX_VALUE); 보다 더 많은 의미를 지니고 myCustomFunction(x, y);

따라서 대답은 그렇습니다, 그것은 바람직하지 않습니다 . 그것은 당신의 두뇌 언어의 별명으로 만 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.