ORM 또는 일반 SQL을 사용하십니까? [닫은]


245

필자가 개발 한 앱 중 일부를 잊어 버린 경우 주로 MySQL 용 일반 SQL을 작성했습니다. SQLAlchemy 와 같은 파이썬에서 ORM을 사용했지만 오랫동안 그것들을 고수하지 않았습니다. 일반적으로 문서화 또는 복잡성 (내 관점에서 볼 때)이 나를 방해합니다.

다음과 같이 보입니다 : 한 가지 유형의 데이터베이스를 사용하려는 경우 이식성을 위해 ORM을 사용하고 일반 SQL을 사용하십시오. 데이터베이스 지원이 필요한 앱을 개발할 때 언제 ORM 또는 SQL을 사용해야하는지에 대한 조언을 찾고 있습니다.

그것에 대해 생각하면 데이터베이스 래퍼를 사용하거나 ORM을 사용하는 것보다 가벼운 래퍼를 사용하는 것이 훨씬 좋습니다.


표준화, 보안, 유지 관리, 언어 추상화, DRY 등
Ben

ORM의 성능은 거의 SQL에 가깝습니다. 올바르게 사용하고 올바르게 설정했는지에 따라 다릅니다 ... EF6.x를 5 배 더 빠르게하려면 ho 참조 : linkedin.com/pulse/…
baHI

ORM 아키텍처 및 사용 방법 (피해야 할 사항)은 다음과 같습니다. linkedin.com/pulse/…
baHI

ORM (Object-Relational Mapping)은 이미 많은 프로그래밍 언어에서 널리 사용되며 SQL을위한 최상의 대안 중 하나입니다. TRIADB 프로젝트를위한 CQL을 생성하는 메소드 체인 스타일에서 영감을 받았습니다. healis.eu/triadb/#latest-release
Athanassios

2
이 질문이 종결 된 것은 바보입니다.
Mitch Wheat

답변:


169

ORM에는 멋진 기능이 있습니다. 데이터베이스 열을 개체 필드에 복사하는 많은 작업을 처리 할 수 ​​있습니다. 일반적으로 언어의 날짜 및 시간 유형을 적절한 데이터베이스 유형으로 변환합니다. 일반적으로 중첩 된 객체를 인스턴스화하여 일대 다 관계를 매우 우아하게 처리합니다. ORM의 강점과 약점을 염두에두고 데이터베이스를 설계하면 데이터베이스에서 데이터를 가져오고 나가는 데 많은 작업이 절약됩니다. (매핑해야하는 경우 다형성과 다 대다 관계를 처리하는 방법을 알고 싶을 것입니다.이 두 도메인은 ORM을 '컴퓨터 과학의 베트남'이라고 부르는 '임피던스 불일치'를 대부분 제공합니다. .)

트랜잭션이있는 응용 프로그램 (예 : 요청, 일부 개체 가져 오기, 데이터를 가져 와서 웹 페이지에서 렌더링)의 경우 성능 세가 적으며 많은 경우 ORM이 개체를 캐시하기 때문에 ORM이 더 빠를 수 있습니다. 앞에서 본 것처럼, 그렇지 않으면 데이터베이스를 여러 번 쿼리했을 것입니다.

보고가 많거나 요청 당 많은 수의 데이터베이스 행을 처리하는 응용 프로그램의 경우 ORM 세금은 훨씬 더 무겁고, 캐싱하는 캐싱은 큰 쓸모없는 메모리 낭비 부담으로 바뀝니다. 이 경우 간단한 DAL (LinQ 또는 iBatis) 또는 간단한 DAL의 수작업으로 코딩 된 SQL 쿼리를 사용하는 것이 좋습니다.

대규모 응용 프로그램에서 두 가지 방법을 모두 사용한다는 것을 알았습니다. (간단한 CRUD의 경우 ORM,보고의 경우 SQL / thin DAL).


'요청 당 많은 데이터베이스 행 수'를 정의 할 수 있습니까? :)
Mosselman 2016 년

예를 들어 JPA를 IBatis와 통합 할 수 있습니까? 그들이 같은 거래에서 작동하게 했습니까?
Jaime Hablutzel

2
아무도 논의하지 않는 또 다른 고려 사항은 기본 상태 관리입니다. 이 전체 프레임 워크 스택 (JSF, JPA 등)은 Java Bean get / set 메소드를 기반으로합니다. 이것은 모든 테이블, 모든 열에 대한 상용구입니다. 여기 실제 반 패턴이 있습니다 : 마치 모든 필드가 마치 공개 된 것처럼 노출시키는 것입니다. 실제로, 객체 / 테이블 / 행의 필드에 대해 get / set 메소드를 갖는 것은 정보 숨기기 및 캡슐화의 모든 테넌트를 위반하는 데 매우 가깝습니다. 마지막으로 상태 관리로 돌아갑니다 ... 불변 옵션은 어디에 있습니까? 반 세트 객체를 허용 할 수 있습니까? 대부분의 옵션이 없습니다.
Darrell Teague

2
나는이 답변에서 핵심 내용에 대해 연마하고 특히 동의하고 싶습니다. "요청 당 많은 데이터베이스 행을 처리하는 응용 프로그램의 경우 ORM 세금이 훨씬 더 큽니다." ORM은 대부분의 개발자가 SQL에 능숙하지 않기 때문에 개발자와 유지 보수에만 유용하지만 실제로 성능에 대해 이야기하는 경우 SQL이 완전히 능가합니다.
나치

"대부분의 개발자는 SQL에 능숙하지 않습니다"??? 대부분의 개발자는 LINQ, 표현 트리의 강력한 기능 및 일반적으로 ORM, 코드 생성 및 기타 여러 가지를 올바르게 사용하는 방법을 모른다고 말합니다. 그러나 아니요, 저는 그러한 강력한 진술을 할 근거가 없습니다.
Adanay Martín

253

Hibernate, EclipseLink, Toplink, OpenJPA 등을 포함하여 JPA (Java Persistence API, 기본적으로 Java / J2EE / EJB에 대한 표준화 된 ORM API)를 다루는 데 상당한 시간을 소비 한 사람으로서 관찰.

  1. ORM은 빠르지 않습니다. 그것들은 적절할 수 있고 대부분의 시간은 적당하지만 대량의 대기 시간이 짧은 환경에서는 그렇지 않습니다.
  2. Java 및 C #과 같은 범용 프로그래밍 언어에서는 작동하기 위해 엄청나게 많은 마법이 필요합니다 (예 : Java에서로드 타임 제직, 계측 등).
  3. ORM을 사용할 때 (의도적 인 것처럼 보이는) SQL에서 멀어지기보다는 ORM이 성능있는 SQL을 생성하도록 XML 및 / 또는 주석 / 속성을 조정하는 데 얼마나 많은 시간이 걸리는지 놀라게 될 것입니다.
  4. 복잡한 쿼리의 경우 실제로 대체 방법이 없습니다. JPA와 마찬가지로 원시 SQL에서는 불가능한 일부 쿼리가 있으며 JPA에서 원시 SQL을 사용해야 할 때 (C # /. Net에는 동적 유형-var가 있습니다.) Object 배열보다 좋습니다);
  5. ORM을 사용할 때 엄청나게 많은 "gotchas"가 있습니다. 여기에는 의도하지 않았거나 예기치 않은 동작, JPA 또는 이와 유사한 메소드에서 refresh ()를 사용하여 데이터베이스에 대한 SQL 업데이트를 수행 할 수있는 기능을 빌드해야한다는 사실이 포함됩니다. JPA는 기본적으로 모든 것을 캐시하므로 직접 데이터베이스를 포착하지 않습니다. 업데이트-직접 SQL 업데이트를 실행하는 것이 일반적인 프로덕션 지원 활동입니다).
  6. 객체 관계 불일치는 항상 문제를 일으킬 것입니다. 이러한 문제로 인해 추상화의 복잡성과 완전성 사이에 상충 관계가 있습니다. 때때로 나는 JPA가 너무 멀리 가고 추상화가 복잡성 히트가 정당화되지 않은 실제 수익률 감소 법칙에 부딪쳤다 고 느꼈다.

좀 더 설명이 필요한 또 다른 문제가 있습니다.

웹 응용 프로그램의 전통적인 모델은 지속성 계층과 프레젠테이션 계층을 갖는 것입니다 (서비스 또는 다른 계층 사이에있을 수 있지만이 논의에서 중요한 두 가지입니다). ORM은 퍼시스턴스 레이어에서 프리젠 테이션 레이어 (즉, 엔티티)까지 견고하게 보여줍니다.

보다 원시적 인 SQL 메소드에 대한 비판 중 하나는 단순히 하나의 쿼리에서 사용되는 이러한 모든 VO (값 오브젝트) 또는 DTO (데이터 전송 오브젝트)로 끝나는 것입니다. 이를 없애기 때문에 ORM의 장점으로 선전됩니다.

문제는 ORM에서 사라지지 않는 문제이며 단순히 프리젠 테이션 레이어로 넘어갑니다. 쿼리에 대한 VO / DTO를 만드는 대신 일반적으로 모든보기마다 하나씩 사용자 지정 프레젠테이션 개체를 만듭니다. 이것이 어떻게 더 낫습니까? 그렇지 않다.

ORM 또는 SQL로 이것에 대해 썼습니다 : 아직 있습니까? .

요즘 내 선택 기술 (자바)은 이바 티스입니다. JPA가 할 수있는 것의 90 % 이상을 수행하는 SQL 주위의 꽤 얇은 래퍼입니다 (문서화되지는 않았지만 관계의 지연 로딩을 수행 할 수도 있음).하지만 복잡성과 실제 코드 측면에서 오버 헤드가 훨씬 적습니다.

이것은 작년에 내가 작성한 GWT 응용 프로그램에서 나왔습니다. 서비스 구현에서 EclipseLink에서 프리젠 테이션 오브젝트로의 많은 변환 우리가 ibatis를 사용한다면, ibatis로 적절한 객체를 생성 한 다음 스택 위아래로 전달하는 것이 훨씬 간단했을 것입니다. 일부 순수 주의자들은 이것이 Bad ™라고 주장 할 수 있습니다. 어쩌면 (이론적으로) 어쨌든 나는 당신에게 무엇을 말해줍니다 : 그것은 더 간단한 코드, 더 간단한 스택 및 더 많은 생산성으로 이어질 것입니다.


2
나는 이와 같은 것들에 대한 자료를 모으기 위해 다른 커뮤니티 질문이 있지만 다른 질문을 게시하도록 영감을 받았습니다. 마지막 단락에 대해 : 나는 단순함을 좋아한다. 아마 너무 많아
hydrapheetz가

3
iBATIS는 훌륭하지만 jOOQ : jooq.sourceforge.net 을 사용해보십시오 . 여기서 언급 한 6 가지 이유로 SQL과 밀접한 관계를 유지하는 것이 가장 중요합니다.
Lukas Eder

5
포인트 3에 +1. 많은 사람들이 ORM을 사용하면 SQL에 대한 철저한 이해가 줄어든다고 생각합니다. 일단 SQL로 체조를 할 수 있고 배우면 ORM에서 아주 빨리 멀어 질 것입니다.
Ryan Fernandes

4
이제 2013 년 말이되었는데 우리 모두 알다시피 "오래된 사실"보다 오해의 소지가있는 것은 없을 것입니다. 따라서 요점이 여전히 같은지 물어볼 수 있습니까? 그렇지 않다면 블로그 게시물을 작성하거나 그에 따라 답변을 업데이트 할 수 있다면 좋을 것입니다.
Dominik

3
var는 .NET에서 동적 유형을 생성하지 않으며 dynamic 키워드가있는 변수는 .NET의 동적 유형입니다. var는 여전히 정적 인 타이핑입니다. 참조 stackoverflow.com/questions/961581/...
Fazi

45

R eads에 대한 일반 SQL , CUD에 대한 ORM을 말합니다 .

성능은 특히 웹 응용 프로그램에서 항상 염려하는 부분이지만 코드 유지 관리 성과 가독성도 중요합니다. 이러한 문제를 해결하기 위해 SqlBuilder를 작성 했습니다 .


1
CUD 란 무엇입니까? 정의를 찾을 수 없습니다.
Kimchi Man

27
@ 김치만 CRUD없이 CRUD
최대 토로

3
CUD-생성, 업데이트, 삭제
결합

14

ORM은 이식성 만있는 것이 아닙니다 (ORM으로도 달성하기 어렵습니다). 그것이 제공하는 것은 ORM 도구가 상용구 SQL 쿼리 (PK 또는 술어, 삽입, 업데이트 및 삭제에 의해 선택)를 작성하지 못하게하고 문제 도메인에 집중할 수있게하는 기본적으로 영구 저장소에 대한 추상화 계층입니다.


3
데이터베이스의 특징에 대한 이식성에 더 가까운 것을 생각하고있었습니다. 늦은 밤에 질문을 게시해서는 안됩니다.
hydrapheetz

1
그것은 내가 말한 것과 정확히 같습니다. 심지어 가장 기본적인 시나리오조차도 다른 DBMS에서 오류가 발생할 수 있습니다 (예 : 다른 NULL 처리).
Anton Gogolev 08 년

ORM은 객체 간의 관계에 대한 추상화 계층을 제공하지만 언급 한 상용구 쿼리와 관련하여 큰 이점은 없습니다. JDBC 앱에서는 소량의 코드로 이러한 유형의 쿼리를 추상 수퍼 클래스 또는 유틸리티 클래스에 작성할 수 있습니다. 각각의 새 테이블에 대해 상용구를 반복 할 필요가 없습니다.
케빈 스템 브리지

11

임피던스 불일치를 처리하기 위해서는 데이터베이스에 대한 추상화가 필요합니다. 그러나 가장 간단한 첫 단계 (대부분의 경우에 적합)는 무거운 ORM이 아닌 DAL이 될 것으로 기대합니다. 유일한 옵션은 스펙트럼 끝의 옵션이 아닙니다.


DAL과 ORM을 구별하는 방법을 설명하는 의견에 대한 답변으로 편집하십시오.

DAL은 단순히 테이블을 캡슐화하고 해당 필드를 속성에 매핑하는 클래스에서 시작하여 직접 작성하는 것입니다. ORM은 dbms 스키마의 다른 속성 (주로 PK 및 FK)에서 유추하거나 추상화하지 않는 코드입니다. (여기서 자동 추상화가 누출되기 시작하는지 여부를 알 수 있습니다. 나는 의도적으로 정보를 제공하는 것을 선호하지만 그저 개인적 선호 일 수도 있습니다).


2
DAL이란 무엇이며 ORM은 무엇입니까?
혼돈

4
ORM 작성자 인 경우 ORM이 자동으로 DAL로 돌아 갑니까? :)
Bombe

DAL = 지속성 계층 및 ORM은 DAL 내부에서 데이터 저장소에 대한 CRUD 작업을 수행하는 데 사용하는 도구입니다.
Vahid Ghadiri

7

모든 도구에는 목적과 비전이 있습니다. iBatis는 아마도 당신에게도 좋은 해결책이지만, 나는 당신의 필요에 맞게 http://www.jooq.org/ 를 만들었습니다 .

jOOQ에는 기본 ORM 기능이 있지만, 대부분의 개발자는 자신의 요구에 가장 적합한 ORM을 찾을 때 대부분의 개발자가 가장 필요로하는 것들에 중점을 둡니다.

  • 코드 생성
  • 변수 바인딩 (JDBC의 고통)
  • SQL 구문 추상화 (구문 오류 방지)

그러나 종종 너무 멀리 가고 너무 많은 추상화를 제공하므로 RDBMS에 대해 실행되고 있다고 생각하지 않을 것입니다. 반면에 RDBMS를 정확하게 선택했기 때문에

  • 강력한 데이터 소스입니다
  • SQL은 여러 가지 우수한 성능을 발휘할 수 있습니다 (선택된 선택, 공용체, 복잡한 조인 등). ORM은 종종 이런 일을 할 수 없습니다.
  • 거래와 세션을 직접 처리 할 수 ​​있습니다
  • UDT와 저장 프로 시저가 있습니다

jOOQ는 이러한 점을 정확하게 해결합니다. JDBC만큼 성능이 좋을 것입니다.


6

현대 소프트웨어 개발 시나리오에서 프레임 워크 사용 여부는 매우 일반적입니다.

이해해야 할 것은 모든 프레임 워크 또는 접근 방식에 장단점이 있다는 것입니다. 예를 들어 경험상 ORM이 트랜잭션을 처리 할 때 (예 : 삽입 / 업데이트 / 삭제 작업) 유용하지만 복잡한 데이터를 가져 오는 경우 결과 ORM 도구의 성능과 효과를 평가하는 것이 중요해집니다.

또한 프레임 워크 나 접근 방식을 선택하고 그 안에있는 모든 것을 구현하는 것이 의무적이지 않다는 것을 이해하는 것이 중요합니다. 우리가 의미하는 바는 ORM과 기본 쿼리 언어를 혼합하여 사용할 수 있다는 것입니다. 많은 ORM 프레임 워크는 기본 SQL에서 플러그인에 대한 확장 점을 제공합니다. 프레임 워크 나 접근 방식을 과도하게 사용해서는 안됩니다. 특정 프레임 워크 또는 접근 방식을 결합하여 적절한 솔루션을 제공 할 수 있습니다.

높은 수준의 동시성으로 삽입, 업데이트, 삭제, 버전 관리와 관련하여 ORM을 사용할 수 있으며 보고서 생성 및 긴 리스팅에 Native SQL을 사용할 수 있습니다.


3
높은 동시성을 위해 ORM이 더 나은 이유는 무엇입니까?
user359996

6

내 ORM을 실제로 사용하게 만든 열쇠는 코드 생성이었습니다. 코드 성능 측면에서 ORM 경로가 가장 빠르지 않다는 데 동의합니다. 그러나 중간 규모에서 큰 규모의 팀이있을 경우 DB는 빌드 프로세스의 일부로 특히 CI를 사용할 때 주목할만한 수준으로 DB에서 클래스 및 매핑을 재생성하는 기능이 빠르게 변화하고 있습니다. 따라서 코드가 가장 빠르지는 않지만 코딩이 빠릅니다. 대부분의 프로젝트에서 어떤 코드를 사용할지 알고 있습니다.

스키마가 유동적 인 동안 ORM을 사용하여 개발하고 프로파일 링을 사용하여 병목 현상을 찾은 다음 원시 Sql을 사용하여 필요한 영역을 조정하는 것이 좋습니다.

또 다른 생각으로, Hibernate에 내장 된 캐싱은 종종 올바른 방식으로 사용될 경우 성능을 크게 향상시킬 수 있습니다. 더 이상 참조 데이터를 읽기 위해 DB로 돌아 가지 않습니다.


2
절대적으로 개인적인 취향의 문제. 나에게 코드 생성은 결함이다.
dkretz

5
두 번째 단락을 읽으십시오 .... 아마도 완전성은 또한 유용합니다
MrTelly

코드 생성은 특정 작업을보다 빠르게 수행 할 수있는 유일한 방법입니다. 모든 도구와 마찬가지로 강력하거나 재난으로 이어질 수 있습니다. 기술적으로 모든 언어는 다른 유형의 코드를 생성합니다.
Banjocat

4

'한 도구에 맞는'솔루션은 없으며 '또는 / m을 사용해야합니까?'라는 질문에 대해서도 마찬가지입니다. '.

나는 말할 것입니다 : 많은 다른 논리없이 매우 '데이터'중심의 응용 프로그램 / 도구를 작성해야한다면 SQL은 이러한 종류의 응용 프로그램에 대한 도메인 별 언어이므로 일반 SQL을 사용합니다.

반면에, 많은 '도메인'로직을 포함하는 비즈니스 / 기업 응용 프로그램을 작성하려면이 도메인을 코드로 표현할 수있는 풍부한 클래스 모델을 작성합니다. 이러한 경우 OR / M 맵퍼는 많은 수의 배관 코드를 제거하므로 성공적으로 처리하는 데 도움이 될 수 있습니다.


" '모든 도구에 맞는 솔루션'은 없습니다."
Rushino

1

내가 개발 한 앱 중 하나는 파이썬으로 작성된 IRC 봇이었습니다. 사용하는 모듈은 별도의 스레드에서 실행되지만 sqlite를 사용할 때 스레딩을 처리하는 방법을 찾지 못했습니다. 그러나 그것은 별도의 질문에 더 좋을 수도 있습니다.

제목 실제 질문을 모두 바꿔야했습니다 . 나는 실제로 어떤 언어로도 DAL을 사용한 적이 없다.


4
글쎄, 난 당신이해야한다고 의견입니다. 모든 곳의 원시 SQL은 꽤 가증합니다.
혼돈

그래 내가 가지고 때때로에 해킹 포럼 소프트웨어의 조각있다 저기는 mysql_query ()와 mysql_result () 모든의는. 견과류입니다.
hydrapheetz

이 "앱"은 무엇입니까?
Zoran Pavlovic

이 질문이 irc 봇 앱에 대해 질문되었고 그것이 매우 유용한 안내서가되었다는 것은 재밌습니다! irc 봇 앱은 스케일의 한 쪽 끝에 있으며 복잡한 조인이있는 50-100 개 이상의 테이블과 20 명 이상의 개발자가 작업하는 수백만 개의 데이터 행이있는 어플리케이션은 스케일의 다른 쪽 끝에 있습니다. 스케일의 'irc bot 앱'에 관해서는 감히 중요하지 않습니다.
나치

1

SQL 처럼 작동 하지만 컴파일 타임 검사 및 유형 안전성을 제공 하는 ORM을 사용하십시오 . 내가 좋아하는 것 : Data Knowledge Objects (공개 : 나는 썼다)

예를 들면 다음과 같습니다.

for (Bug bug : Bug.ALL.limit(100)) {
  int id = bug.getId();
  String title = bug.getTitle();
  System.out.println(id +" "+ title);
}

완전 스트리밍. 손쉬운 설정 (정의 할 매핑이 없음-기존 스키마를 읽습니다). 조인, 트랜잭션, 내부 쿼리, 집계 등을 지원합니다. SQL에서 수행 할 수있는 대부분의 작업. 그리고 거대한 데이터 세트 (재무 시계열)에서 사소한 (Android)까지 입증되었습니다.


IDE는 이러한 정적 검사를 직접 제공 할 수도 있습니다 (IDEA는 DB 구조를 알고 있으므로 DB가있는 위치 / DDL 파일의 위치를 ​​알려주기 때문에 SQL 쿼리 / 프로 시저 / 무엇이든 유형 검사 / 관계 검사 / 등을 수행 할 수 있음) )
Xenos

유용합니다. 빌드 / CI 단계의 일부로 할 수 있습니까? SQL과 다른 문자열을 어떻게 분류합니까? 문자열 조작 또는 문자열 상수 만 처리 할 수 ​​있습니까?
keredson

abBlock에 의해 차단되지만 IntelliJ는 다른 언어 jetbrains.com/datagrip/features 와 마찬가지로 SQL을 구문 분석 하여 CI / CD / build에 통합 할 수 있습니다 (IJ 팀에 SQL 구문 분석 코드를 분리하도록 요청하면 어쩌면 Sonar는 이미 그런 파서가 있습니다). 구문 분석은 데이터 유형을 가져 와서 사용자 정의 플러그인으로 확인을 추가하거나 "조인 열에 FK? 색인이 있습니까?"와 같은 확인을 추가 할 수 있습니다. 이것들은 네이티브 IJ의 SQL 검사에 깔끔한 개선이 될 것입니다
Xenos

1

나는이 질문이 매우 오래되었다는 것을 알고 있지만 누군가 나와 같은 질문을 겪을 경우 답변을 게시 할 것이라고 생각했습니다. ORM은 먼 길을 왔습니다. 그들 중 일부는 실제로 개발을보다 생산적으로 만들고 성능을 유지하는 두 가지 장점을 모두 제공합니다.

SQL 데이터 ( http://sqldata.codeplex.com )를 살펴보십시오 . 모든 염기를 덮는 c #의 경우 매우 가벼운 ORM입니다.

참고로, 저는 SQL Data의 저자입니다.


1

"중간 근거가 있습니다!"라는 답글의 코러스에 내 목소리를 추가하고 싶습니다.

응용 프로그램 프로그래머에게 SQL은 제어하고자하는 것들과 거의 확실하게 제어하고 싶지 않은 것들의 혼합입니다.

내가 항상 원했던 것은 완전히 예측 가능한 결정 (SQL 키워드 철자법, 괄호가있는 곳)을 담당하는 계층 (DAL, ORM 또는 micro-ORM이라고 함)입니다. 열 별명, 두 개의 float 및 int를 보유하는 클래스에 대해 생성 할 열 ...)을 발명하면서 SQL의 높은 수준의 측면, 즉 JOIN을 정렬하는 방법, 서버 측 계산, DISTINCT, GROUP BY, 스칼라 하위 쿼리 등

그래서 나는 이것을하는 것을 썼습니다 : http://quince-lib.com/

C ++ 용입니다. 사용중인 언어인지는 모르겠지만 "중간 영역"이 어떻게 보이는지 보는 것이 흥미로울 수 있습니다.

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