최신 웹 응용 프로그램 프레임 워크는 파일 시스템에서 URL 경로를 분리하기 위해 어떻게 그리고 왜 발전 했습니까?


67

약 10 년 전에 비해 파일 시스템에서 URL 경로를 분리하는 라우팅 스타일을 사용하는 프레임 워크로의 전환에 주목했습니다. 이는 일반적으로 전면 컨트롤러 패턴의 도움으로 수행됩니다.

즉, 이전에는 URL 경로가 파일 시스템에 직접 매핑되어 디스크의 정확한 파일과 폴더를 반영하므로 오늘날 실제 URL 경로는 구성을 통해 특정 클래스로 보내지도록 프로그램되어 더 이상 파일을 반영하지 않습니다. 시스템 폴더 및 파일 구조.

질문

이것이 어떻게 그리고 왜 흔한 일이 되었습니까? 한때 평범한 직접 파일 접근 방식이 효과적으로 포기되는 시점까지 어떻게 "더 나은"것으로 결정 되었습니까?

다른 답변들

여기에 경로 개념과 몇 가지 장점과 단점에 대한 비슷한 대답이 있습니다. PHP 프레임 워크에서 "경로"개념이 사용되는 이유는 무엇입니까?

그러나 오늘날 새로운 프로젝트가이 새로운 라우팅 스타일 패턴을 사용하고 파일로 직접 연결이 오래되거나 포기 된 곳에서 역사적 변화 측면, 또는 이러한 변화가 어떻게 또는 왜 발생했는지는 다루지 않습니다.

또한 언급 된 대부분의 이점과 단점은 이러한 글로벌 변화를 보증 할만큼 중요한 것으로 보이지는 않습니다. 이 변경 사항을 추진하는 유일한 이점은 최종 사용자로부터 파일 / 폴더 시스템을 숨기고 ?param=value&param2=valueURL이 더 깔끔해 보이도록하는 것입니다. 그러나 이것이 변화의 유일한 이유입니까? 그렇다면, 왜 그런 이유가 있었습니까?

예 :

필자는 PHP 프레임 워크에 대해 가장 잘 알고 있으며 널리 사용되는 최신 프레임 워크에서이 분리 된 라우팅 방식을 사용합니다. 웹 응용 프로그램 기능이 더 이상 파일로 직접 연결되는 URL 경로를 통해 더 이상 트리거되지 않는 Apache 또는 유사한 웹 서버에서 URL 재 작성 을 설정합니다 .

젠드 표현

https://docs.zendframework.com/zend-expressive/features/router/aura/
https://docs.zendframework.com/zend-expressive/features/router/fast-route/
https : //docs.zendframework. com / zend-expressive / features / router / zf2 /

젠드 프레임 워크

https://docs.zendframework.com/zend-mvc/routing/

라 라벨

https://laravel.com/docs/5.5/routing

CakePHP

https://book.cakephp.org/3.0/en/development/routing.html


14
정말 그런 변화가 있었습니까? 아니면 대부분의 언어 / 프레임 워크가 직접 파일 시스템 매핑을 사용하지 않았습니까? 아마도 제정신의 나머지 부분을 따라 잡는 것은 단지 PHP일까요? 내 의견으로는 당신의 관찰이 잘못되었으므로 좋은 대답이 없습니다. 또한 "shift"는 PHP 세계에서만 발생했습니다. 그러나 그것은 내 의견으로는 너무 광범위한 질문입니다 ...
rsm

2
@rsm 나는 비슷한 첫 반응을 보였지만, 더 많은 생각에, 그것은 실제로 일반적인 취약점의 원인이되는 많은 언어와 플랫폼에서 이루어진 것입니다.
JimmyJames

6
@rsm, 이것은 PHP 프레임 워크에서 더 분명 할 수도 있지만 다른 방법을 사용하는 경우도 있습니다. 어느 프레임 워크가 실제로 잡히기 전에 ASP, .NET, PHP, JSP 등 웹에서 주로 직접 사용됩니다. 파일 접근 방식. 이러한 모든 프레임 워크가 분리 된 접근 방식을 사용하도록 개발 된 이유는 무엇입니까? 기술적으로 파일에 직접 접근 방식은 여전히 ​​가능하며 최신 프레임 워크에서 사용할 수 있습니다. 아니면 할 수 있습니까? 어쩌면 그들은 할 수 없으며 왜 그렇지 않은지에 대한 충분한 이유가 있습니까? 그 이유는 무엇입니까? 그들은 심지어 이것을 할 수있는 방법이나 플러그인을 제공하지 않으며 단지 파일로 직접 파일을 근절했습니다.
Dennis

2
이것은 (부분적으로) URL ( 로케이터 , 리소스를 찾는 방법)을 URI (및 식별자 )로 보는 것이 아닙니까?
Hagen von Eitzen

2
고대 역사 관련 독서 : 쿨 URI는 변경하지 마십시오 - 팀 버너스 - 리, 1998
마이클 햄프 턴

답변:


72

가장 기본적인 형태로 웹 사이트는 정적 파일을 제공합니다. URL 경로를 파일 경로에 매핑하는 것이 가장 확실한 선택입니다. 기본적으로 읽기 전용 FTP 사이트입니다.

그런 다음 사람들은 일부 스크립팅으로 페이지의 내용을 변경하고 싶었습니다. 가장 쉬운 방법은 페이지에 스크립팅 언어를 포함시키고 인터프리터를 통해 실행하는 것입니다. 이미 존재하는 경로-> 파일 경로 라우팅을 고려할 때 이것은 간단합니다.

그러나 실제로는 해당 파일을 현재 통역사에게 인수로 실행하고 있습니다. 요청이 정적 파일에 대한 요청인지, 그리고 해석해야하는 대상에 대한 것인지를 식별해야합니다.

고급 컴파일 언어를 사용하기 시작하면 파일 위치에서 더 이혼하게됩니다.

또한 웹 서버는 이미 정적 파일을 캐싱하고 모든 종류의 최적화를 수행하고 있으므로 파일 시스템에 충돌하는 것이 규칙이 아니라 예외입니다. 이 시점에서 이전 링크 파일 시스템 경로는 도움말보다 장애가됩니다.

그러나 사용자가 경로에서 파일 확장자를 제거하고 싶을 때 실제로 바다가 바뀌 었다고 생각합니다. myPage.asp 또는 myPage.php를 얻는 것은 '정상적인'사람들을 혼란스럽게하고 SEO를 방해하는 것입니다.

사용자는 경로를 볼 수 있으므로 웹 UI의 일부가되었으므로 기술적 제한이 전혀 없어야합니다. 우리는 'www'를 잃어 버렸으며 거의 ​​모든 것이 '.com'입니다. 여러 URL이 같은 페이지를 가리 킵니다.

mydomain.com/sale와 www.mydomain.co.uk/products/sale.aspx로 더 많은 돈을 버는 경우 기술적 제한이있는 것을 원하지 않습니다.


7
필자는 파일 확장명을 숨기려는 욕구가 부분적으로 "불명확 한 보안"이라고 생각했습니다. 특정 서버의 특정 첨부 / 알려진 악용에 대한 타겟팅을 쉽게하기 위해 사이트에서 어떤 기술을 사용했는지 파악하기가 조금 더 어려워졌습니다. 와 당시의 기술
Caius Jard

20
@CaiusJard 그 일부이지만 다른 부분은 기술 불가지론입니다. 경로에서 file.html을 대체 한 후에 나중에 다른 스위치 (예 : file.phtml에서 file.php로 또는 심지어는 file.asp). 그러나 데이터베이스 레코드 및 / 또는 다른 소스에서 빌드 된 리소스에 액세스하기 위해 URL 및 파일 시스템 경로 (라우팅 등을 사용하여)를 분리하기 때문에 왜 URL에 확장명이 있습니까?
HorusKol

39
@HorusKol 기술의 불가지론은 단지 경로의 모든 파일을 변경해야 할 필요조차 없습니다. 고객의 작업 흐름과 책갈피를 손상시키지 않고 SEO를 파괴하지 않고 백엔드 기술을 변경할 수 있다는 것은 엄청날 수 있습니다 .
Shane

7
흥미롭게도 URI에 파일 이름 확장자를 갖는 것은 권장되지 않았으므로 파일 시스템에서 일찍 분리되어야했습니다. 내가 찾을 수있는 가장 초기의 참조는 1998 년부터 이며, 실제로이 답변에 설명 된 대부분의 개발보다 앞서 있습니다.
Konrad Rudolph

8
예전에는 mydomain.com/sale가 여전히 작동했습니다. / sale /로 리디렉션되어 정상적으로로드되었습니다 (페이지는 mydomain.com/sale/index.aspx이지만 아무도 index.aspx를 보지 못했습니다).
Joshua

39

로이 필딩 (Roy Fielding )의 REST (Representational State Transfer) 에 관한 백서 에서 언제 , 왜 그런지 에 대해 살펴볼 수 있습니다 . 내가 아는 첫 번째 프레임 워크는 리소스와 파일을 구별하는 것이 Ruby on Rails라는 것입니다. URL 대 코드 라우팅 개념을 소개합니다.

변형적인 REST의 주요 개념은 다음과 같습니다.

  • URL은 리소스를 나타냅니다
  • 해당 자원은 여러 표현을 가질 수 있습니다
  • 응용 프로그램이 재구성 된 경우 URL이 끊어지지 않아야합니다.
  • 응용 프로그램은 웹의 무국적 상태를 수용해야합니다

URL에서 파일을 직접 제공하는 데 따른 주요 단점은 다음과 같은 문제가 발생한다는 것입니다.

  • 웹 사이트가 재구성 될 때 리소스 링크가 지속적으로 끊어짐
  • 자원과 표현은 함께 묶여있다

공정한 균형을 유지하는 것이 중요하다고 생각합니다.

  • 모든 자원의 중요성이 같은 것은 아닙니다. 스타일 기반 리소스를 직접 제공하는 이유 (CSS, JavaScript / EcmaScript, 이미지)
  • 단일 페이지 앱을 더 잘 지원하는 HATEOAS 와 같은 REST의 개선이 있습니다 .

표현할 때 JSON / HTML / TEXT / etc와 같은 것을 의미합니까? REST에 대해 잘 알고 있지만 REST를 사용하더라도 응답 표현을 변경하려면 트리거가 필요하다고 생각합니다.
Dennis

@ 데니스. HTTP에는 원하는 형식 ( developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation ) 을 암시하는 데 사용할 수있는 많은 헤더가 있으며 REST는 모두 HTTP의 장점을 수용하는 것입니다. 그러나 앱이 원하는 콘텐츠를 독점적으로 협상하는 방법은 여전히 ​​드문 일이 아닙니다.
Berin Loritsch

5
CGI (1993), Servlets (1997) 및 JSP (1999)는 종종 파일 시스템에서 URL을 분리하고 REST (2000) 이전 버전을 분리했습니다. 그러나이 답변은 기본적으로 디자인 패턴의 인기 이유를 식별하는 데 정확합니다. REST, Java Struts 및 Ruby on Rails는 21 세기의 리소스를 표현과 분리하는 인기에 큰 영향을 미칩니다.
17 분 39 초에 dcorking

1
Fielding의 논문에 따르면, "RES의 첫 번째 버전은 1994 년 10 월에서 1995 년 8 월 사이에 개발되었습니다"
Connor

1
@dcorking, 당시 CGI는 파일에서 URL을 분리하지 않고 10에서 9 번 대신 파일을 실행했습니다. 서블릿이 가장 일치 할 수 있지만 경로 개념에 대해 이야기하고 URL 공간을 설계 한 경우 레일과 프레임 워크가 함께 제공됩니다.
Berin Loritsch

20

나는 그것이 현대 웹 응용 프로그램 프레임 워크 의 인공물이라고 생각하지 않으며 , 일반적으로 동적 페이지 제공의 인공물입니다.

에서 옛날 소프트웨어가 자신의 경로 파일 시스템에서 개별 파일을 제공 주로 정적 웹 페이지가 있었다. URL 경로를 파일 시스템 경로 (웹 루트로 지정된 하나의 디렉토리로)에 1 : 1로 매핑하는 것이 명백한 선택 이었기 때문에 URL 재 작성 (예 : 파일 이동 후 경로 재 지정)도 일반적 이었으므로 대부분 그렇게했습니다.

그런 다음 동적 콘텐츠를 제공하는 시대가되었습니다. CGI 스크립트 (및 그로부터 진화 된 모든 것)는 어떤 종류의 데이터베이스에 의해 뒷받침되는 페이지를 즉석에서 만들었습니다. URL의 GET 매개 변수가 일반적이되었습니다 (예 : en.wikipedia.org/w/index.php?title=Path_(computing)) .

그러나 경로 세그먼트로만 구성된 읽기 가능한 URL을 갖는 것이 사용자 에게 친숙 합니다. 따라서 동적 응용 프로그램은 간단한 경로 (예 : en.wikipedia.org/wiki/Path_(computing) )를 매개 변수에 매핑했으며 이러한 매핑을 "라우트"라고합니다.

이 접근 방식은 유용성의 중요성이 더 널리 인식되고 SEO의 일부가되었을 때 인기를 얻었을 때 더 최근에 느껴질 수 있습니다. 이것이 아마도 대형 웹 프레임 워크에 직접 구축 된 이유 일 것입니다.


12

한 가지 이유는 모든 요청에 ​​대해 디스크에서 파일을로드하는 속도가 느리기 때문에 웹 서버가 파일을 메모리에 캐시하는 방법을 만들기 시작한 것입니다. 디스크?

그 이유 중 하나는 많은 웹 프레임 워크가 컴파일 된 언어로 작성 되었기 때문에 디스크에 파일 구조 jar나 파일 또는 기타 요소 가 없기 때문 입니다. 해석 된 언어는 컴파일 된 언어에서 원하는 아이디어를 빌 렸습니다.

한 가지 이유는보다 의미적이고 역동적 인 경로에 대한 요구 때문입니다 https://softwareengineering.stackexchange.com/questions/363517/how-and-why-did-modern-web-application-frameworks-evolve-to-decouple-url-routes. 분명히, 당신은 /var/www/questions/363517/how-and-why-did-modern-web-application-frameworks-evolve-to-decouple-url-routes.php파일을 원하지 않습니다 . 웹 서버 구성에서 URL 재 작성 규칙을 작성하여 이와 같은 경로를 작성했습니다. 이제는 코드 변경 일 뿐이며 운영상 훨씬 간단합니다.


해당 예제에 대한 URL 재 작성이 필요하지 않습니다.
Yay295

1
경로의 첫 부분을 인식하는 코드로 처리되며 숫자 / 363517 /을 사용하여 데이터베이스에서 질문을 찾습니다. 웹 서버 자체와는 관련이 없지만 애플리케이션은 ...
Will Crawford

11

URI를 파일 경로에 매핑하는 이러한 접근 방식은 파일 경로 탐색을 통해 실수로 많은 데이터를 릴리스 한 주요 원인 중 하나 일 수 있습니다.

경로를 파일 시스템에 맵핑 할 때 요청으로 수신 한 모든 경로가 클라이언트를 통해 액세스 할 수있는 파일에 맵핑되는지 확인해야합니다. 일어나지 않도록하는 간단한 방법은 투명 매핑을 제거하고보다 명확하게 수행하는 것입니다.

이것은 PHP 전용 문제가 아닙니다. 여기 증거로 아파치 강화 가이드 의 관련 섹션이 있습니다.


1
왜 공감해야합니까?
JimmyJames

8

업계에 대해서는 대답 할 수 없지만 2000 년 초반 URL = 파일 시스템에서 가상 '라우트'로 이동 한 이유를 알 수 있습니다.

'오래된 학교'PHP로 작업 할 때, 1000 개의 PHP 페이지가 있다면, 해당 페이지를 나타내는 1000 개의 PHP 파일이 있습니다. 각 중복 머리글 / 바닥 글에는 다른 논리가 포함될 수 있습니다. 이제 변경해야한다고 가정 해 봅시다. 당신은 지금 당신의 손에 얼마나 엉망입니다! 1000 개의 파일을 모두 변경해야하거나 모든 경우를 처리하기 위해 머리글 / 바닥 글에 매우 추한 코드가 혼동됩니다. 가상 경로를 사용하면 머리글 / 바닥 글 논리, 데이터베이스 연결 논리 및 기타 초기화가 한 번 에 포함 됩니다. 작업하는 것이 훨씬 좋습니다.

또 다른 이유는 모호성을 피하는 것입니다. 응용 프로그램이 증가함에 따라 포함되는 머리글 / 바닥 글이 더 복잡해집니다. 그들은 일반적으로 다양한 것들에 의존하는 자신의 포함을 중첩했습니다. 'page'에 대한 PHP 파일에서 변수 isset () 여부에 대해 모호한 경우가 종종있었습니다. 가상 경로와 필요한 모든 것이 각 페이지로드에로드되는 응용 프로그램을 사용하면 더 이상 그런 걱정이 없습니다.

마지막으로 (다른 이유가 있지만 마지막으로 나열 할 것입니다), 1000 페이지 중 다수는 복제 될 코드를 나타냅니다. 따라서 적절한 클래스 및 템플릿 세트로 리팩토링 한 후 코드가 크게 단순화되어 1000 개의 파일 없이도 원하는 모든 작업을 수행 할 수 있습니다.


왜 그렇게 추악한 코드로 끝나는 지 더 말할 수 있습니까? 1000 개의 파일을 변경해야한다는 것을 알 수 있습니다 (헤더 / 바닥 글 포함을 업데이트하는 것으로 가정). 추악한 코드가 혼란 스럽다는 것은 무엇을 의미합니까?
Dennis

방금 추가 한 단락을 참조하십시오. 그러나 기본적으로 헤더 / 바닥 글 / 초기화 코드를 확장하여 더 많은 경우를 처리 할 때, 특히 다른 파일을 조건부로 포함하는 경우 (나쁜 습관이지만 많은 PHP 프로그래머가 수행 한 경우) 코드를 따르기가 매우 어렵습니다. .
GrandmasterB

5

이 분리가 유리한 이유에 대해서는 너무 자세하게 설명하지 않겠습니다. 주요한 논점은 시맨틱 (실제로 액세스하려는 것)을 기본 구현에서 분리한다는 것입니다.

이익이 주어진 비용보다 중요하다는 점을 고려하면 (이는 별도의 질문 일 수 있음) 그것이 왜 점차 적용되는지를 보는 것은 어렵지 않습니다. 나는 이것에 대해 교육받은 것에 확실히 개방되어 있지만, 이것을 일으킨 사건이 하나도 없다고 생각합니다.

적어도 내 경험상 처음에는 Apache 구성을 통해 수행되었으며 종종 다른 웹 서버에서도이를 지원했습니다. 그러나 개념적으로 서버가이 작업을 수행해야하는 이유는 없습니다. 결국 경로는 실제 응용 프로그램에 따라 다르므로 여기에서 정의하는 것이 좋습니다.

이것은 전 세계적으로 바뀌었지만 점진적으로 점진적으로 나타납니다. 그 이유는 거의 확실히 아주 간단한 이유입니다. 좋은 아이디어는 시간이 지남에 따라 퍼집니다. 이것이 또한 변화가 전 세계적으로 일어난다는 놀라운 일이 아닙니다. 모두가 함께 모여서 이렇게하기로 결정한 것은 아닙니다. 오히려 모든 프로젝트는이 방법이 도움이 될 것이라고 생각했을 때이 접근법을 채택했습니다 (그리고이를 지원하지 않는 프로젝트는 결국 사라졌습니다).


1

RFC는 이미 개념 (로컬 부분에 의미를 첨부하지 않은 URI)과 URL과 경로와 같은 의미를 도입하여 HTML 문서가 문서와 관련된 링크를 사용할 수 있도록하는 URL을 사용하여 개념을 처음부터 구축했습니다. 기본 URL.

명백한 구현은 URL의 로컬 부분을 파일 시스템에 직접 매핑하는 것입니다. 따라서 전용 관계형 데이터베이스를 사용하여 문서를 찾거나 고도로 최적화 된 낮은 오버 헤드 키를 이용하는 등 간단한 설정이 수행됩니다. -가치 상점은 이미 외부에 중요하지 않지만 문서를 제공하는 비용 구조에 영향을 미칩니다.

지속적인 데이터가 포함 된 웹 응용 프로그램이있는 경우 비용 구조가 변경됩니다. 항상 응용 프로그램을 실행해야하는 오버 헤드가 있으며 URL 디코딩을 통합하면 많은 기능을 쉽게 구현하여 비용을 절감 할 수 있습니다.


1

처음에는 URL이 쉽고 파일 경로에 직접 매핑되었으므로 다른 방법이 없으므로 어떻습니까? 내가 부탁하면 /path/to/index.php, 내가거야 /path/to/index.php웹 사이트의 루트 디렉토리에서 시작 (일반적으로 서버가 아닌 자체, 웹 사이트는 디렉토리에 보관 또는 하위 디렉토리 더 아래되어야한다).

몇 년 후, 우리는 재 작성에 대해 배우기 시작했습니다. /request/path/to/index.php실제로 봉사 할 수 있습니다 /response/path/to/index.php.

또 다른 트릭은 숨어 index.php있습니다. 내가 요청하면 /index.php?foo=bar&baz=qux서버 숨겨 응답 할 수 있습니다 index.php:과 같이 /?foo=bar&baz=qux, 모든 동안 실제로 제공 index.php어쨌든.

다음으로 중요한 단계는 모든 URL을 로 리디렉션하는 방법을 배운 것 /index.php입니다. 이제는 /path/to/some/page자동으로로 리디렉션됩니다 /index.php?path/to/some/page. 일반적으로 각 슬래시는 새 하위 디렉토리를 나타내므로 웹 서버는 경로를 찾는 대신 경로를 매개 변수로 보내도록 구성되어 있기 때문에 약간 까다 롭습니다.

이제 우리는 웹 사이트가 어떻게 구성되어 있는지에 대해 완전히 다른 사고 방식이 필요합니다. 이전에는 다른 페이지의 느슨한 컬렉션이었습니다. 이제 모든 것이 단일 항목 페이지를 통해 라우팅됩니다. 이렇게하면 사이트가 훨씬 복잡해 지지만 사이트 전체 사용자 인증, 균일 한 머리글 적용, 바닥 글 및 스타일 등 이전에는 없었던 기회가 제공됩니다.

수백 또는 수천 개의 앱 웹 사이트 (각 파일을 자체 앱으로 간주하는 경우)를 훨씬 더 복잡하지만 일관된 단일 앱으로 효과적으로 전환합니다.

단순히 URL을보고 어떤 코드가 실행 될지 더 이상 알 수 없기 때문에 이것은 큰 도약입니다. 이제는 특정 프레임 워크가 URL 경로를 코드 경로로 변환하는 방법에 대해 깊이 이해해야합니다. 프레임 워크간에 유사점이 있지만 대부분은 코드 작업에 익숙해야 할 정도로 충분히 다릅니다.

간단히 말해, 갑작스런 점프가 아니라 점진적인 발견의 진화였으며, 각 개발자는 거의 같은 발견의 여정을 거쳐야했습니다. 추상적 개념을 정말 빠르게 파악할 수 없다면 학습 곡선은 매우 가파르다.


-1

오랜 시간 webdev 로서 HTML5 시대에 탐색이없는 히스토리 제어 ( history.pushState()) 의 출현이이를 실현했다고 생각합니다 . 그 전에 조각 ( /path#fragment) 만 업데이트하지 않는 한 URL 표시 줄을 업데이트하려면 페이지를 다시로드해야했습니다 . 이 조각은 서버에 표시되지 않았으므로 (라우팅되지 않음) 동적 페이지를 새로 고치거나 북마크하는 유일한 방법은 JavaScript를 사용하는 것입니다.

이는 SEO에 중요한 영향을 미치며 Google 은 동적 해시를 실제 URL에 서버 측으로 매핑 해야하는 거의 사용하지 않는 "hashbang"스키마 를 개발하도록 이끌었습니다 . 이것은 로봇들 사이에서 다루기 힘들고 보편적이지 않았으며, "거짓은 아약스 콘텐츠를 크롤링 할 수 없습니다"라는 잘못된 원칙을 이끌었습니다. 그러나 아약스 콘텐츠의 이점은 실용적입니다. 예를 들어 JS가없는 Google지도를 사용해보십시오.

해결책은 페이지를 다시로드하지 않고 서버에서 미러링 할 수있는 값 (책갈피 및 JS가없는 새로 고침 허용)으로 URL 표시 줄을 업데이트하는 방법이었습니다. 이 기능을 사용할 수있게되면 개발자는 단순히 "주요 콘텐츠 섹션", URL 표시 줄 및 이동 경로를 업데이트하여 사이트를 "탐색"할 수 있습니다. 이것은 모든 JS + CSS가 리 페치 + 파싱 할 필요가 없었기 때문에 훨씬 빠른 페이지 간 전송을 가능하게합니다.

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