객체 지향과 알고리즘의 관계


9

일부 알고리즘 교과서를 읽으면 일부 문제 (정렬, 최단 경로) 또는 일반적인 방법 (재귀 알고리즘, 나누기 및 정복, 동적 프로그래밍 ...)에 대한 영리한 절차로 가득합니다. 나는 객체 지향 프로그래밍의 흔적을 거의 발견하지 못했습니다. (왜 더 절차 지향적입니까?).

그때 나는 생각하고 있었다 :

  • 알고리즘과 OOP의 관계는 무엇입니까? 두 개의 독립적 인 주제입니까?
  • OOP에 의해서만 제시되고 해결 될 수있는 문제가 있습니까?
  • OOP는 알고리즘을 어떻게 도울 수 있습니까? 아니면 어떤 방향으로 영향을 줄 수 있습니까?

4
중복되지는 않지만 관련 프로그래머 인
Doc Brown

@DocBrown 감사합니다. 매우 도움이되었지만 여기서 상속, 다형성과 같은 OO 관련 개념을 고려할 수 있습니다.
Ahmad

1
"알고리즘 교과서가 더 절차 지향적 인 이유는 무엇입니까?" Java는 또한 절차 지향적입니다. Java는 객체 지향 절차 언어입니다.
Pieter B


1
@ gnat 내 질문을 수정했습니다. 그 설명이 필요한지 아닌지 모르겠습니다. 그러나 Doc Brown이 제기 한 질문에 내 관심사와 관련된 더 많은 답변이 있음을 인정합니다.
Ahmad

답변:


10

먼저 OOP의 의미를 정의 해 보겠습니다. OOP는 주로 다음을 의미합니다.

  • 수업 내 세부 사항의 캡슐화 및 숨기기.
  • 상속 및 가상 방법을 통한 행동의 다형성.

이제 질문에 대답하십시오.

알고리즘과 OOP의 관계는 무엇입니까? 두 개의 독립적 인 주제입니까?

예.

OOP에 의해서만 제시되고 해결 될 수있는 문제가 있습니까?

아니요. OOP primary는 프로그래머를위한 코드에 대한 편리 성과 추론 능력을 제공합니다. 그것은 당신의 표현력을 높이 지 않습니다.

OOP가 알고리즘을 어떻게 도울 수 있습니까? 아니면 어떤 방향으로 영향을 줄 수 있습니까?

내가 위에서 말했듯이 내가 OOP를 여기에 적용한 것으로 설명했다. 알고리즘과 데이터 구조의 세부 사항을 숨길 수 있으면 전체에 대한 추론에 도움이 될 수 있습니다. 많은 알고리즘에는 해당 알고리즘 사용자가 원하지 않는 세부 정보가 포함되어 있습니다. 이러한 세부 사항을 숨기면 많은 도움이됩니다.

다형성 행동 능력도 훌륭합니다. List컬렉션의 어느 위치에서나 항목을 추가 / 제거 / 삭제할 수있는 것으로 정의됩니다. 그러나 크기 조정이 가능한 배열, 이중 연결 또는 단일 연결 등으로 구현할 수 있습니다. 여러 구현에 단일 API를 사용하면 재사용에 도움이 될 수 있습니다.

알고리즘 교과서가 더 절차 지향적 인 이유는 무엇입니까?

내가 말했듯이, OOP는 알고리즘을 구현하는 데 필요하지 않습니다. 또한 OOP가 여전히 널리 퍼지지 않았을 때 많은 알고리즘이 오래되어 만들어졌습니다. 따라서 그것은 역사적인 것일 수도 있습니다.


1
텍스트의 시대에도 불구하고 아마도 OOP로 알고리즘의 물을 현대적이지 않기 때문에 진흙탕으로 만들고 싶지 않을 것입니다.
Gusdor

15

알고리즘OOP 는 서로 다른 두 용어로, CS 용어라는 공통점 만 있습니다. 간단하게 - 알고리즘이처럼 요리 조리법 : 할 x를 다음 필요한 재료를 단계 1,2,3,4,5,6을 ... 당신은 당신의 식사를 준비합니다.

즉,이 보인다 말했다 자연 algortihms에 맞는가 설명하는 절차 방법. 절차 적 수단 아무것도 아닌 다른 : 첫 번째X를 다음 할 y로 .

일반적인 문제는 다음과 같습니다.» x 집합을 정렬하는 방법 ?«. 이해하기 쉬운 솔루션은 bubble-sort다음과 같습니다.

  1. 첫 번째 요소에 도달하지 않고 반복하는 동안 마지막 요소에서 세트를 반복하십시오.
  2. 첫 번째 반복의 시작부터 현재 요소까지 두 번째 반복을 시작하고
  3. (2)의 현재 요소와 후속 요소를 비교
  4. 더 큰 경우, 스왑 포지션

그것은-알고리즘의 알고리즘 / 언어 적 설명입니다 bubblesort.

다음은 절차 적 / 의사 코드 구현입니다.

bubbleSort(Array A)
  for (n=A.size; n>1; n=n-1){
    for (i=0; i<n-1; i=i+1){
      if (A[i] > A[i+1]){
        A.swap(i, i+1)
    } 
  } 
}

그것은 쉽다.

방법이 releate 않는 OOP를 ? 당신이 사용할 수있는 알고리즘을 다루다에 컬렉션 (객체 자체)의 객체를 :

Javascript의 예 ( 깨끗한 OO-Lingo 는 없지만 상용구가 거의없고 이해하기 쉬운)

objects =[{"name":"Peter"}, {"name":"Paul"}, {"name":"Mary"}]

compareObjects=function(x,y){ return x.name>y.name };

sorted = objects.sort(compareObjects)

console.log(sorted)

우리는 a) 컬렉션 objects, b)sort 정렬 알고리즘을 포함 / 추상화하고 c) 우리의 객체 Peter , Paul , Mary 를 포함 하는이 컬렉션에 공통된 방법을 가지고있다 . 정렬 사양은 여기에 있습니다 .

알고리즘과 OOP의 관계는 무엇입니까? 두 개의 독립적 인 주제입니까?

말한 것으로부터, 분명해야하며, 그 대답은 다음과 같아야합니다.

OOP가 알고리즘을 어떻게 도울 수 있습니까? 아니면 어떤 방향으로 영향을 줄 수 있습니까?

OOP는 하나의 프로그래밍 스타일입니다. 어떤 종류의 도움도 될 수 없습니다 . 그렇지 않으면 객체에 무언가를하기 위해 OO 언어로 알고리즘을 구현할 수 있습니다 (그림 참조).

OOP에 의해서만 제시되고 해결 될 수있는 문제가 있습니까?

나는 하나를 생각할 수 없다 (그러나 그것이 불가능하다는 것을 의미하지는 않는다). 그러나 다른 방법으로 살펴보면 OOP가 유용합니다. 문제를 모델링하고 적절한 알고리즘으로 해결하려면 OOP가 유용합니다. 당신의 기록이 말해 friends그들을 모델링 할 수있는 당신 objects과를 properties당신이 원하는 경우 listfriends 분류 어떤 식 으로든를, 당신은 정확하게 할 위에서 주어진 예제 코드를 사용할 수 있습니다.

알고리즘 교과서가 더 절차 지향적 인 이유는 무엇입니까?

말했듯이 절차 는 알고리즘 의 특성 이기 때문에 자연 스럽습니다 .


7
이 답변은 알고리즘이 자연스럽게 절차 적이라는 것을 전제로합니다. 확실히 그중 일부는 있지만 기능 알고리즘과 같은 것이 있습니다. 알고리즘 북이 절차적인 이유는 아마도 성능에 중점을 둔다는 사실과 더 관련이있을 수 있으며 추상화 적용에 대해 걱정하는 것은 독자에게 달려 있으며 명령형 언어는 기능적 언어보다 더 인기가 있기 때문입니다.
Doval

나는 그것이 옳지 않다고 생각한다. 함수형 프로그래밍 언어를 말할 때 알고리즘 자체가 아니라 구현 에 대해 이야기하고 있습니다. 예를 들어 Haskell의 quicksort wiki.haskell.org/Introduction#Quicksort_in_Haskell 우리는 이것이 quicksort-algortihm에 대한 기능적 구현이라는 것에 동의합니다. 그러나 당신이 무엇을했는지 설명 한다면 , 결정적인 서술 방식 으로 대체되어야합니다 . 이 설명에서 절차 적 구현을 ​​구현할 수 있습니다.
토마스 정크

1
@ThomasJunk 기능적 구현은 일련의 단계가 아니라 상황 무엇인지 나타 내기 때문에 절차 적 설명 모드로 넘어갈 필요가 없습니다 . 순수하고 게으른 계산에 대한 순차적 설명을 어떻게 제공 하시겠습니까? 얼마나 많은 표현식이 평가 될 것인지 또는 하위 표현식이 어떤 순서로 계산 될 것인지 미리 알 수 없습니다.
Doval

2
불행히도 나는 CS 학위가 없으므로 다음을 증명할 광범위한 기술이 부족합니다. 그렇지 않다면, 여행의 완전성은 무엇을 의미합니까?
토마스 정크

2
튜링 자신이 람다 미적분학과 튜링 기계가 동등하다는 것을 증명 한 이후 @Doval은 잘 알고 있습니다. 또한 게으른 계산을 명령형으로 변환하는 것은 사소한 일입니다-Haskell의 컴파일러는 항상 그것을 수행합니다 ... 결국 그것은 단지 선호의 문제입니다. 때때로 기능적 (functional)이 더 적합하고 때로는 명령 적 (imperative)이며 다른 경우에는 논리적 인 것이 가장 좋습니다.
AK_

5

문제가 있군.

비즈니스 도메인 모델 은 문제점 및 처리하려는 문제점 도메인의 개념을 설명합니다.

알고리즘 은 개념적으로 문제를 해결하는 방법을 설명합니다. 당신의 구현은 어떻게 생겼을까 요; "컴퓨터 과학"용어로 번역 한 후 문제를 어떻게 처리합니까?

OOP, Functional, Logical, Procedural 또는 Non-Structured 등의 프로그래밍 패러다임 은 솔루션을 어떻게 구성 할 것인지, 어떤 형태를 취할 것인지, 어떤 "소프트웨어 엔지니어링"개념을 채택 할 것인지, 어떤 " 프로그래밍 언어 이론 "개념을 사용합니다.

더 간단하게 말하면, 알고리즘은 일반적으로 문제에 대한 해결책을 설명합니다 ( "이것이 제가 할 것입니다"). 프로그래밍 패러다임은 실제 구현을 처리하는 동안 ( "이것이 내가 할 방법입니다").


불완전한 방식으로 선언적 언어는 "어떻게"단계를 줄이거 나 없애는 것을 목표로합니다. 그들의 목표는 단순히 "이것이 내가 원하는 것"이라고 말하는 것입니다 (예를 들어, 높은 수준의 방정식을 작성하여). 일반적인 SQL 쿼리를 생각해보십시오. "알고리즘"은 거의 없습니다. 데이터베이스에 원하는 것을 알려 주면 요청을 처리하는 방법에 달려 있습니다 (물론 특정 제한 내에서).
Andres F.

4

알고리즘 = " 방법 "스토리 (즉, 원하는 결과를 얻기 위해 데이터 구조를 사용하여 입력 데이터를 조작하는 방법)

OOP = 메모리 안전과 추상화를 제공하는 프로그램 (= 알고리즘 + 데이터 구조체)을 작성하기 위해 OO 언어로 촉진되는 " 방법론 "

OOP는 알고리즘 구현의 패러다임입니다.

좋은 비유 : 영화

스턴트맨을 사용하거나 사용하지 않고 장면을 녹화 할 수 있습니다. 시나리오 (알고리즘)는 변경되지 않습니다. 사람들은 최종 결과에 차이가 없어야합니다.

편집 : 당신은 좋은 품질의 MOOC를 시도 할 수 있습니다 : https://www.coursera.org/course/algs4partI 는 논의 된 주제 (특히 OOP 접근 방식)를 인터리브하고 여기에서 묻는 내용의 본질을 제공합니다.


나는 당신의 영화 비유를 정말 즐겼습니다. 나는 앞으로 그 것을 빌릴 것입니다.
Marc LaFleur

2

Alexander Stepanov는 C ++의 기본 알고리즘 라이브러리 인 C ++ 표준 템플릿 라이브러리 (STL)의 최초 제작자입니다. C ++은 "Object Oriented"기능을 포함하는 다중 패러다임 언어이지만 Alexander Stepanov는 Object Orientation에 대해 다음과 같이 말합니다.

http://www.stlport.org/resources/StepanovUSA.html

STL은 객체 지향이 아닙니다. 저는 객체 지향성이 인공 지능만큼이나 허위라고 생각합니다. 나는이 OO 사람들로부터 오는 흥미로운 코드 조각을 아직 보지 못했습니다.

OOP는 기술적으로 좋지 않습니다. 단일 유형에 따라 다른 인터페이스 측면에서 세계를 분해하려고 시도합니다. 실제 문제를 해결하려면 여러 유형에 걸친 인터페이스 제품군 인 다중 분류 대수가 필요합니다. 나는 OOP가 철학적으로 좋지 않다고 생각합니다. 모든 것이 대상이라고 주장합니다. 그것이 사실이더라도 그것은 매우 흥미롭지 않습니다. 모든 것이 대상이라고 말하는 것은 전혀 아무것도 말하지 않습니다. OOP가 방법 론적으로 잘못되었다는 것을 알았습니다. 수업으로 시작합니다. 마치 수학자들이 공리로 시작하는 것과 같습니다. 공리로 시작하지 마십시오-증거로 시작하십시오. 관련 증거를 많이 발견했을 때만 공리를 생각해 낼 수 있습니다. 공리로 끝납니다. 프로그래밍에서도 마찬가지입니다. 흥미로운 알고리즘으로 시작해야합니다. 잘 이해해야 만

나는 그 메커니즘이 근본적으로 결함이 있고 사용되어서는 안되는 이유를 이해하기 전에 상속과 가상의 용도를 찾기 위해 수년을 보냈습니다.

Stepanov는 자신의 알고리즘 라이브러리를 Objects가 아니라 Generic Iterators로 표현했습니다 .


글쎄 그는 틀렸어 ... 주로 STL은 객체 지향적이기 때문이다. 용어 이후로보다 현대적인 객체 지향적이다.
AK_

1
@AK_-나는 그가 틀렸다고 생각하지 않습니다. STL은 용어의 의미에서 대략 OO가 아닙니다. STL을 실질적인 방식으로 변경할 필요없이 파라 메트릭 다형성 (예 : Haskell 또는 SML)이있는 비 OO 언어로 직접 변환 할 수 있습니다.
Jules

2

알고리즘은 컴퓨터가해야 할 일을 설명합니다. 구조는 [소스 코드에서] 알고리즘이 배치되는 방법을 설명합니다. OOP는 특정 "객체 지향"구조를 활용하는 프로그래밍 스타일입니다.

알고리즘 책은 종종 구조가 아니라 알고리즘에 초점을 맞추기 때문에 OOP를 피합니다. 구조에 크게 의존하는 코드 조각은 알고리즘 북에 넣는 예가 좋지 않은 경향이 있습니다. 마찬가지로 OOP 서적은 종종 이야기를 복잡하게하기 때문에 알고리즘을 피합니다. OOP의 판매 포인트는 유동성이며, 알고리즘에 고정 시키면보다 강건하게 보입니다. 그것은 무엇보다도 책의 초점에 관한 것입니다.

실제 코드에서는 나란히 사용합니다. 정의없이 알고리즘없이 컴퓨터 문제를 해결할 수 없으며 구조 (OOP 등)없이 좋은 알고리즘을 작성하기가 어렵다는 것을 알게 될 것입니다.

흐려지는 위치의 예로 동적 프로그래밍을 사용하십시오. 알고리즘 책에서는 배열에서 동종 데이터 집합을 가져오고 동적 프로그래밍을 사용하여 솔루션에 도달하는 방법을 설명합니다. OOP 서적에서, 이기종 오브젝트 세트에서 임의의 알고리즘을 수행하는 방법 인 Visitor와 같은 구조를 발견 할 수 있습니다. DP 서적 예제는 일반적으로 상향식으로 오브젝트를 조작하는 매우 간단한 방문자로 생각할 수 있습니다. 방문자 패턴은 DP 문제의 골격으로 생각할 수 있지만 고기와 감자는 빠져 있습니다. 실제로는 둘 다 필요하다는 것을 알게 될 것입니다. 방문자 패턴을 사용하여 데이터 집합에서 이질성을 처리하고 (DP는 그 점이 좋지 않습니다) 방문자 구조 내에서 DP를 사용하여 런타임을 최소화하도록 알고리즘을 구성합니다 (방문자) 하지 않습니다

또한 디자인 패턴의 최상위에서 알고리즘이 작동하는 것을 볼 수 있습니다. 작은 공간에서 예제를 표현하기는 어렵지만 일단 구조가 있으면 해당 구조를 조작하기 시작하고 알고리즘을 사용하여 구조를 작성합니다.

OOP에 의해서만 제시되고 해결 될 수있는 문제가 있습니까?

생각보다 답변하기가 더 어려운 질문입니다. 첫 번째로, 문제를 해결하기 위해 OOP가 필요한 계산상의 이유는 없습니다. 간단한 증거는 모든 OOP 프로그램이 결정적으로 비 OOP 언어 인 어셈블리로 컴파일된다는 것입니다.

그러나 더 큰 계획에서는 대답이 '예'로 부끄러워지기 시작합니다. 컴퓨팅 방법론에 의해 제한되는 경우는 거의 없습니다. 대부분의 경우 비즈니스 요구 사항 및 개발자 기술과 같은 것들이 방정식에 반영됩니다. 오늘날 OOP 없이는 많은 응용 프로그램을 작성할 수 없었습니다. OOP가 어떤 식 으로든 작업의 ​​기본 요소가 아니기 때문에 OOP에서 제공하는 구조가 프로젝트를 계획하고 예산에 맞게 유지하는 데 필수적 이었기 때문입니다.

이것은 우리가 미래에 재미있는 새로운 구조를 위해 OOP를 결코 포기하지 않을 것이라고 말하지 않습니다. 그것은 단지 오늘날의 놀랍도록 많은 프로그래밍 작업을 위해 툴박스에서 가장 효과적인 도구 중 하나라고 말합니다. 미래의 문제로 인해 다른 구조를 사용하여 개발에 접근 할 수 있습니다. 우선 신경망에는 매우 다른 개발 방식이 필요할 것으로 예상되는데, 이는 "개체 지향"일 수도 있고 아닐 수도 있습니다.

알고리즘 디자이너가 생각하는 방식으로 인해 가까운 시일 내에 OOP가 사라지는 것을 보지 못했습니다. 현재까지 일반적인 패턴은 누군가 OOP를 활용하지 않는 알고리즘을 설계하는 것입니다. OOP 커뮤니티는 알고리즘이 OOP 구조에 실제로 맞지 않으며 실제로 필요하지 않다는 것을 알고 있으므로 전체 알고리즘을 OOP 구조로 감싸서 사용하기 시작합니다. 고려하십시오 boost::shared_ptr. 내부에있는 참조 계산 알고리즘은 shared_ptrOOP 친화적이지 않습니다. 그러나, shared_ptrOOP 구조화 된 형식으로 알고리즘의 기능을 노출시키는 OOP 래퍼를 생성 할 때까지 패턴이 인기를 얻지 못했습니다 . 이제는 매우 인기가있어 C ++, C ++ 11의 최신 사양으로 만들었습니다.

이것이 왜 그렇게 성공적인가? 알고리즘은 문제를 해결하는 데 능숙하지만 문제를 사용하는 방법을 이해하려면 상당한 초기 연구 투자가 필요합니다. 객체 지향 개발은 이러한 알고리즘을 래핑하고 학습에 초기 투자가 덜 필요한 인터페이스를 제공하는 데 매우 효과적입니다.


1

큰 답변 외에도 OOP와 알고리즘 사이에 추가적인 개념적 공통성을 언급 할 것 입니다.

OOP와 알고리즘 은 코드의 정확성을 보장하기 위해 전제 조건과 사후 조건의 사용을 강력하게 강조 합니다 .

일반적으로 이것은 모든 컴퓨터 과학 분야의 표준 관행입니다. 그러나이 지침 원리는 OOP 환경에서 알고리즘을 구현하는 것이 상호 이익을주는 OOP의 진화 경로를 초래합니다.

OOP에서는 인터페이스를 구현하기 위해 동일한 계약 (사전 조건 및 사후 조건)을 충족 할 수있는 개체 그룹을 만들 수 있습니다. 이러한 인터페이스의 사용자는 드문 상황 (누수 추상화가 발생하는 경우)을 제외하고 기본 개체에서 어떤 구현이 사용되는지 알 필요가 없습니다.

알고리즘은 전제 조건을 취하고 사후 조건을 생성하는 계산을 수행하는 데 사용되는 단계의 구현입니다.

따라서 전제 조건과 사후 조건의 방식으로 추상화 개념을 빌려 알고리즘에 적용 할 수 있습니다. 때로는 복잡한 알고리즘이 더 작은 단계로 분해 될 수 있으며, 이러한 작은 단계는 동일한 전제 조건과 사후 조건이 충족되는 한 다른 구현 전략을 허용 할 수 있습니다.

OOP에서 알고리즘을 구현하면 이러한 작은 단계를 서로 바꿔서 사용할 수 있습니다.

마지막으로 FP와 OOP는 상호 배타적이지 않습니다. 위에서 설명한 내용은 FP에도 동일하게 적용 할 수 있습니다.


포인트 감사합니다! 알고리즘이 몇 단계 일 경우 OOP를 통해보다 추상적 인 단계를 제공 할 수 있습니다. "OOP에서 알고리즘 구현"에 대해 지적한 결과, 항상 도움이되는지 묻는 질문을 수정했습니다.
Ahmad

1
"계약 별 디자인"과 OOP를 혼동하고 있습니다. OOP 없이는 매우 유용하며 대부분의 OOP 언어 (C #, Java)는 실제 지원을 제공하지 않습니다 (이전 / 후 조건이 아닌 간단한 인터페이스 지원)
AK_

1
@AK_ 계약에 의한 설계가 제 답변에 설명 된 공통성의 올바른 이름이라는 데 동의합니다. 내가 주장하는 것은 디자인 패러다임으로서의 OOP가 계약에 의한 디자인을 강력하게 수용한다는 것입니다. OOP 교과서를 읽으십시오. 내 원래의 대답은 또한이 공통성이 OOP에만 국한되지 않는다고 언급합니다.
rwong

-1
What is the relation between algorithms and OOP? Are they two independent topics?

알고리즘은 문제 를 해결 하는 방법 (지정된 입력에서 출력을 생성하는 방법)에 관한 것이고 OOP는 솔루션 을 공식화하거나 표현하는 방법 (알고리즘의 단계)에 관한 것입니다.

알고리즘은 자연 언어 또는 어셈블리 언어로 설명 할 수 있지만 자연 언어로 된 개념은 알고리즘을 더 잘 작성하고 이해하는 데 도움이됩니다. 예를 들어, 버블 정렬 알고리즘은 다음과 같습니다.

bubbleSort(Array A)
  for (n=A.size; n>1; n=n-1){
    for (i=0; i<n-1; i=i+1){
      if (A[i] > A[i+1]){
        A.swap(i, i+1)
    } 
  } 
}

OOP 구문과 기능을 사용 하여 세부 사항을 숨기고 swap관련시키기 위해 AOO는 알고리즘을 자연어와 이해에 더 가깝게 만듭니다.

Are there some problems which can only be presented and solved by OOP?

아니요, 컴퓨터의 모든 프로그램 (또는 알고리즘)이 CPU ( Turing Machine ) 에서 실행되는 일련의 명령어로 변환 될 것이라고 생각 하고이 명령어를 컴퓨터 의 문제를 해결하는 궁극적 인 알고리즘으로 간주하면 OOP 더 이상 할 수 없습니다. 그것은 단지 인간의 이해와 추론에 더 가깝게 만듭니다. 프로 시저 및 데이터 구조를 패키지화하는 방법입니다.

How OOP can help algorithms? Or in which direction it can affect it?

알고리즘을보다 쉽고 이해하기 쉽게 설명하거나 공식화하는 데 도움이 될 수 있습니다. 세부 사항을 숨기고 솔루션의 큰 그림을 제공 할 수 있습니다.

이론적으로 알고리즘은 첫 번째 이고 두 번째 구현 입니다. 그러나 실제로 알고리즘을 추적하거나 예상 출력을 생성 할 때까지 알고리즘이 예상대로 작동하는지 확신 할 수 없습니다. 컴퓨터가 그렇게하도록 도와 주지만 기계어 (어셈블리)로 작성하지는 않습니다.

이와 관련하여 OOP는 컴퓨터에서 알고리즘의 구현, 테스트 및 개선을 용이하게하며 자연 언어에 가까운 언어로 컴퓨터를 위해 작성합니다.

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