디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

[Java] 프로그래밍 원칙 (2)

마갤러(220.122) 2024.05.12 18:52:02
조회 167 추천 8 댓글 0

[!] 이 게시글은 프로그래밍 원칙 (1)의 후속 게시글임. https://cafe.naver.com/minecraftgame/1907323

Avoid Premature Optimization

───────────────────────

조기 최적화 방지 원칙은 프로그램이 만들어질 때 성급하게 최적화를 하지 말라는 원칙임.

최적화는 좋은 거라고 쉽게 생각할 수 있지만, 일반적으로 성능상 심각한 문제가 있는게 아니면 최적화를 하지 않는 것이 좋음. 아예 "성급한 최적화는 모든 악의 근원이다" 라는 격언이 존재할 정도이며, 최적화의 규칙은 1. 하지 마라 2. (전문가만 해당함) 아직은 하지 마라, 최적화가 필요함을 100% 확신하는 것이 아니라면 이라는 말이 있을 정도로 조기 최적화는 좋지 않음.

최적화는 프로그램을 복잡하게 하기 때문에 유지 관리를 어렵게 하며, 기본적으로 어렵고, 상식적이지 않은 방법을 사용할 경우 수정을 어렵게 함. 또한 프로그램의 실행 시간 대부분은 프로그램의 작은 일부분에서 발생함. (https://en.wikipedia.org/wiki/Pareto_principle)

따라서 최적화는 병목 현상이 발생하는 지점에 적용해야 하며 그 외에 경우에는 시간 대비 효율이 좋지 않음. (https://en.wikipedia.org/wiki/Amdahl%27s_law) 또한 병목 현상이 일어나는 지점에 최적화를 적용하더라도 프로그램 개발이 완료되는 시점에 적용하는 것이 좋으며 수정 사항은 언제든지 발생할 수 있으므로 트릭은 최대한 피하는 것이 좋음.

추가 정보: https://wiki.c2.com/?PrematureOptimization

When in Doubt, Use Brute Force

───────────────────────

이게 효율적인지 의심스러울 때는 그냥 생각하지 말고 브루트 포스를 쓰라는 원칙임.

이는 조기 최적화 방지 원칙의 특별한 케이스임. 현대 컴퓨터는 생각보다 강력함. 작업이 0.00001 초에 끝나는 것과 0.001 초에 끝나는 것 사이에는 별다른 외부적인 차이점이 없음. 사용자에게는 그냥 바로 끝나는 것으로 보임.

또한 일반적으로 브루트 포스를 시행하더라도 그 횟수가 10만을 넘어갈 확률은 적으며, 알고리즘의 대부분은 n이 작을 때를 상정하고 만든 것이 아님. 그를 위해 최적화라고 복잡한 알고리즘을 도입하는 것은 오히려 효율적이지 못함. 그냥 간단하게 브루트 포스를 쓰는 것이 일반적으로 더 좋은 결과를 가져옴.

주의 사항: 위와 같이 병목 현상이 발생하거나 할 수 있어서 효율적이어야 하는 부분에는 적용해서는 안됨.

추가 정보:

- https://www.brainyquote.com/quotes/ken_thompson_185574

- https://users.ece.utexas.edu/~adnan/pike.html

Code for Maintainer

───────────────────────

개발자는 유지보수자를 위한 코드를 작성해야 한다는 원칙임.

일반적으로 소프트웨어 개발에서 제일 비용이 많이 드는 작업은 유지 보수임.(대략 전체의 50%) 그리고, 그 유지 보수자는 코드를 작성한 본인일 확률이 큼. 유지 보수자가 본인이 아니더라도, 남이 읽을 수 있는 코드를 짜야 함. 그 사람이 팀에 갓 들어온 주니어라도 말임.

유지 보수자가 코드를 보고 바로 알아차리지 못하고 생각하게 하거나(https://sensible.com/dont-make-me-think/), 이 코드는 왜 이렇게 작동하지?(PLS) 하고 놀라게 해서는 안됨. 그건 좋은 코드가 아님.

추가 정보: https://wiki.c2.com/?CodeForTheMaintainer

PLS (Principle of Least Surprise)

───────────────────────

PLS란 사용자가 코드를 보고 놀라는 횟수를 최소화 해야 한다는 원칙임.

인터페이스는 사용자가 예상하는 대로 작동해야 함. 그렇지 못할 경우 사용자를 실망시키거나, 사용자의 실수를 유도할 수 있음. 사용자가 원하는대로 작동하는 시스템은 사용하기 편함.

이를 달성하기 위해서는 CQS를 적용하거나, 모듈과 객체, 메서드의 이름을 정확히 지정하고, Model Principle을 적용해 현실의 개념과 동일한 구조를 부여해야 함.

추가 정보:

- https://en.wikipedia.org/wiki/Principle_of_least_astonishment

- http://principles-wiki.net/principles:principle_of_least_surprise

CQS (Command Query Separation)

───────────────────────

명령 쿼리 분리 원칙이란 메서드는 명령을 수행하거나 데이터를 반환하는 두가지 종류만 존재해야 한다는 원칙임.

단순히 데이터를 가져오려고 메소드를 호출했는데 명령이 수행되어 내부 데이터가 변경된다면 이는 사이드 이펙트이며 사용자를 혼란하게 함. 따라서 메서드는 데이터를 변경하거나, 데이터를 반환하는 두 종류만 존재해야 하며 동시에 이를 수행해서는 안됨.

이를 분리하고 어떤 종류의 메서드인지 알 수 있도록 명명 규칙을 적용하면 데이터를 가져오는 메서드를 사이드 이펙트 걱정없이 호출할 수 있으므로 생각할 것이 줄어듬.

추가 정보: https://en.wikipedia.org/wiki/Command%E2%80%93query_separation

Model Principle

───────────────────────

모델 원리란 객체 구조는 현실 세계의 개념과 동작들을 반영해야 한다는 원칙임.

이는 객체 지향의 기본 콘셉트임. (비록 적절한 설명은 아니지만) 객체를 현실의 물건에 비유하는 설명이 자주 보일 정도로 직관적인 내용임. 만약 그렇지 못한 코드를 생성할 경우 일단 개발자의 혼란을 초래하고, 유지 보수를 어렵게 만들며 잠재적으로 버그의 원인이 될 수 있음.

주의 사항: 이를 과도하게 적용하면 현실과 너무 동일하게 모델링 하게 되어 쓸데 없는 부분이 발생하게 될 수 있음. 또한 현실과는 다른, 개발에 특수화된 개념을 넣는 것이 더 좋을 때도 있음.

추가 정보: http://principles-wiki.net/principles:model_principle

Brooks's Law

───────────────────────

브룩스의 법칙은 프로젝트에 사람을 더 투입하면 완료 기간이 더 길어진다는 법칙임.

상식적으로, 개발자를 더 투입하면 프로젝트 완료 기간이 더 빨라져야 하겠지만 개발은 제조업이 아님. 이미 충분히 진행된 개발에 개발자를 더 투입하면 진행이 더 느려짐.

추가된 개발자는 프로젝트를 이해하기 위한 적응 기간이 필요함. 이 과정에서 의사소통을 하느라 기존 개발자들의 시간이 지체되며, 일반적으로 이 지체된 시간이 신규 개발자가 내는 생산성보다 높기 어려움. 또한 신규 개발자는 기존 개발자들보다 버그를 낼 확률이 높으며 이로 인해 시간이 더 지체됨.

브룩스의 법칙은 기본적으로 의사소통의 문제이므로, 이를 보완하기 위해서는 디자인 패턴을 적극적으로 사용하여 작업 분배를 쉽게 하거나, 작업을 세분화하여 더 적은 의사소통이 필요하게 하거나, 지연으로 인해 생기는 생산성 저하를 보완할 수 있을 정도의 인력을 투입해야 함.

추가 정보: https://en.wikipedia.org/wiki/Brooks%27s_law

Linus's Law

───────────────────────

리누스의 법칙은 보는 사람이 많을 수록 문제가 발견될 확률이 높다는 법칙임.

따라서 코드는 가능한 한 많은 사람들에게 보여지는 것이 좋으며, 많은 테스터와 코드 리뷰를 거치도록 해야 함.

추가 정보: https://en.wikipedia.org/wiki/Linus%27s_law

Orthogonality

───────────────────────

직교성이란 작업이 다른 작업에 영향을 주지 않는 정도를 의미함.

이는 Coupling 및 SRP와 일맥상통하나, 문맥까지 포함하는 이들과 다르게 작업 또는 시스템, 또는 언어에 관한 개념임.

소프트웨어 설계에서 직교성이란 작업이나 시스템이 다른 시스템과 완전히 독립적으로 돌아가는 정도를 의미함. 즉, 이를 높이기 위해서는 사이드 이펙트가 없어야 함.

예를 들어 백엔드에서 쿼리를 만들어서 이상한 짓을 한다면 데이터베이스의 종류에 따라 실행이 안될 수도 있으므로 이는 비직교한 시스템임.

추가 정보:

- https://en.wikipedia.org/wiki/Orthogonality_(programming)

- https://www.baeldung.com/cs/orthogonality-cs-programming-languages-software-databases

Principle of Separate Understandability

───────────────────────

분리 이해 가능성(PSU)의 원리란 모듈은 그 자체로 이해 가능해야 한다는 원칙임.

다른 모듈을 끌어와야 이해가 가능한 모듈은 사실 모듈화가 적절하지 않음을 의미함. 이는 잠재적으로 다른 모듈의 기능이 있거나 다른 모듈에 기능이 있음을 의미함.

클래스의 목적은 명확해야 함. 메서드는 한번 보고 뭐하는 메서드인지 바로 알 수 있어야 함. 그렇지 못하면 일단 유지보수에 문제가 생김. 모듈화가 적절히 되었다면 유닛 테스트를 통해 적절한 검증을 할 수 있음.

추가 정보: http://principles-wiki.net/principles:principle_of_separate_understandability

Robustness Principle

───────────────────────

견고성 원칙이란 시스템 자체가 하는 일은 보수적으로 다뤄야 하고, 다른 시스템에서 받는 일은 진보적으로 다루어야 한다는 원칙임.

이는 Postel's law 라도도 함. 간단히 말해, 외부에서 받은 정보는 의미가 명확한 한 이상한 입력이 있어도 무시하도록 만들어야 하고, 내부에서 발생하는 오류나 보내야 하는 정보는 까다롭게 처리해야 함.

외부에서 받은 정보를 까다롭게 처리하는 시스템은 일단 유연하지 못할 뿐만 아니라, 추후 변경시에도 마찬가지로 유연하지 못함. 맞는 데이터를 넣었는데 스페이스 하나 잘못 들어갔다고 오류를 뿜거나 변경된 데이터를 처리하지 못하고 오류를 내는 시스템은 실제 운영 환경에서 불안정하게 작동할 확률이 큼.

반대로 내부의 데이터는 견고하게 다루지 않으면 시스템이 불안정 해질 수 있음. 그렇게 되면 유지보수가 어려워짐.

주의 사항: 외부에서 받은 데이터라도 까다롭게 검증해야 하는 시스템이 있을 수 있음. 특히 신뢰할 수 없는 데이터라면 검증이 더 중요함.

추가 정보:

- http://principles-wiki.net/principles:postel_s_law

- https://en.wikipedia.org/wiki/Robustness_principle

Tell Don't Ask

───────────────────────

TDA 원칙이란 다른 객체에 정보를 묻지 말고 그냥 행위하도록 시켜야 한다는 원칙임.

또한 이는 작업을 해야 하는 경우 제일 많은 정보를 가지고 있는 모듈에 작업을 맡겨야 한다는 Information Expert 원칙과 동치임.

간단해 말해서, Getter를 쓰지 말아야 한다는 원칙임. 이게 무슨 소린가 싶겠지만 진짜임. Getter는 기본적으로 데이터를 요청하는 일임. 그리고 데이터를 요청하는 일의 문제점은 다음과 같음.

• 데이터를 요청하는 것은 다른 모듈이 "필요"한 일이므로 종속성을 증가시킴. 즉 다른 모듈을 알아야 하는 일이 추가되며, 데이터의 변경이 이를 사용하는 모든 모듈에 영향을 미치게 됨.

• 동일한 데이터가 왔다갔다 거리면 동일한 동작을 하게 될 확률이 높음. 이는 DRY를 위반함.

• 데이터가 왔다갔다 거리면 이곳 저곳에서 데이터를 수정하게 됨. 즉 데이터의 무결성을 지키기 어려워짐.

대신 데이터를 가지고 있는 클래스를 분리시키고 모든 조작은 다른 모듈이 데이터 클래스의 메서드들을 호출해서 시행하도록 만드는 것이 좋음.

라고 하는데 전 적용시킬 엄두는 안 나노. 솔직히 이건 상식 파괴 수준이긴 함.

주의 사항: 이는 정보 자체에 관한 원칙이며 정보 은닉의 원리과 같은 목적을 가지고 있는 원칙임. 오용할 경우 좋지 않을 수 있음.

추가 정보:

- http://principles-wiki.net/principles:tell_don_t_ask_information_expert?redirect=1

- https://effectiveprogramming.tistory.com/entry/Tell-dont-ask

EUHM (Easy to Use, Hard to Misuse)

───────────────────────

모듈은 사용하기는 쉽고 오용하기는 어려워야 함.

일반적으로, 모듈은 많은 사람들이 사용하며 주로 모듈을 구현하지 않은 사람들이 사용하게 됨. 문서를 전부 읽고 확실한 방법으로 모듈을 사용하려는 사람은 거의 없음. 물론 이를 지적하는 RTFM(Read the Full Manual)이 있긴 하지만, 그렇다고 해도 개발에서 모든 문서를 전부 읽는다는 것은 사실상 매우 어려움. 또한, 시간이 지나면 모듈을 만든 본인도 까먹게 됨.

따라서, 모듈은 문서를 읽지 않아도 쉽고 직관적이며 올바르게 사용할 수 있도록 설계해야 함. 이를 지키지 않으면 사실상 사용하기 어려운 모듈이 되어 버림. 또한 모듈을 오용하기 어려운 경우 실수가 줄어들고 디버깅 비용이 감소하며 유지보수가 쉬워짐.

추가 정보: http://principles-wiki.net/principles:easy_to_use_and_hard_to_misuse

Add More Classes

───────────────────────

기능이 복잡해진다면 클래스를 추가해 이를 나누라는 원칙임.

복잡성은 클래스를 추가해 관심사를 분리함으로서 줄어들 수 있음. 이때 디자인 패턴 등을 활용하면 좋음.

주의 사항: 클래스를 너무 많이 생성하면 라비올리 코드(https://en.wikipedia.org/wiki/Spaghetti_code#Ravioli_code), 즉 개별적으로 이해하기는 쉽지만 전체적으로 이해하기 어려운 코드가 만들어질 수 있음. 또한 밑의 MIMC 원칙은 이 원칙과 반대되는 원칙임.

추가 정보: http://principles-wiki.net/principles:easy_to_use_and_hard_to_misuse

More is More Complex

───────────────────────

MIMC 원칙이란 더 많을수록 더 복잡하다는 원칙임.

사람이 한번에 읽고 이해할 수 있는 범위에는 제한이 있음. 일반적으로 클래스가 길수록 이해해야 할 부분이 많아짐. 모듈이 크면 읽는데 걸리는 시간이 많아지고, 모듈이 많으면 특정 모듈을 찾는데 걸리는 시간이 길어짐. 문서가 길면 읽는데 더 오랜 시간이 걸림. 이로 인해 가독성 및 유지 보수성이 저해됨.

이는 단순히 클래스의 라인수, 메서드나 클래스의 갯수를 의미하는 것이 아니며, 이해를 위해 필요한 개념의 숫자가 많으면 좋지 않다는 것을 의미함. 따라서 가능하면 이해에 필요한 개념의 수를 줄여야 함.

주의 사항: 복잡한 기능은 어쩔 수 없이 길어질 수밖에 없음. 그렇다고 나누는 것을 주저하면 God Class로 쉽게 향함. 이 문제에 있어서는 결국 적절한 지점을 찾는 것이 중요함.

추가 정보: http://principles-wiki.net/principles:more_is_more_complex

Uniformity Principle

───────────────────────

균일성 원리란 비슷한 문제를 같은 방법으로 풀어보라는 원칙임.

개발의 각 요소는 일관적이어야 함. 일관성을 지키게 되면 일단 추가로 학습할 부분이 줄어듬. 발생할 수 있는 실수나 버그가 줄어들고, 같은 방법으로 비슷한 문제를 풀 수 있다면 재사용에 따른 이점이 발생함. 따라서 개발 및 유지 보수가 쉬워짐.

일관적이나 잘못된 이름은 일관적이지 않으면서 수정된 이름보다 좋음. 엎으려면 한번에 다 엎어야 함. 언제나 같은 명명 규칙을 사용하며, 같은 기술, 메커니즘, 프레임워크, 라이브러리들을 사용하고, 유사한 작업을 하는 함수의 매개변수 순서를 같게 유지하는 것이 좋음. 문서들은 동일한 구조를 가져야 함.

주의 사항: 이는 강제사항이 아니며 가능하면 같은 방법으로 풀어보라는 원칙임. 때로는 완전히 같은 방법으로 약간 다른 문제를 해결하는 것이 불가능하거나 코드를 더 복잡하게 할 수도 있음. 그냥 나누는 게 나을 때도 있음.

추가 정보: http://principles-wiki.net/principles:uniformity_principle

Rule of Explicitness

───────────────────────

명시성 원칙이란 명시적인 것이 암시적인 것보다 낫다는 원칙임.

암시적인 것은 알아차리기 어려움. 그리고 알아차리기 어렵다는 속성은 모듈을 더 복잡하게 만듬. 명시적으로 구현되어 있는 것이 있으면 더 이해하기 쉬우며 유지 관리가 더 쉬움.

이를 위해 다음과 같은 것들을 피해야 함.

간접 참조: 이벤트/리스너/옵저버 등을 피하고 직접 참조를 사용하는 것이 좋음. (단, 이럴 경우 결합도가 올라감)

설정 파일: 고도로 구성 가능한 설정 파일을 제공하는 대신 명시적인 기능을 제공하는 것이 좋음. (단, 이럴 경우 일반화 및 재사용이 어려울 수 있음)

와일드카드: import 할 모듈을 *로 다 가져오지 말고 필요한 것만 명시적으로 가져오셈.

기본형 강박관념: 우편번호, 전화번호와 같은 데이터에 그냥 String이나 int를 쓰지 마셈. 대신 PhoneNumber와 같은 작은 객체들을 사용하셈. (https://refactoring.guru/ko/smells/primitive-obsession)

옵션 매개변수: boolean isForce, boolean isNotice 와 같은 연산의 옵션을 나타내는 매개 변수를 쓰지 마셈. 대신 각자의 명시적인 메서드로 분리하셈. (https://en.wikipedia.org/wiki/Option%E2%80%93operand_separation)

암시적 캐스팅: 대신 명시적 캐스팅을 사용하셈.

주의 사항: 위에 적혀있듯이 결합도 최소화 및 일반화 원칙에 반할 수 있음. 따라서 이는 적절히 해석되어야 함.

추가 정보: http://principles-wiki.net/principles:rule_of_explicitness

작성/수정 일자: 2024.05.12

추천 비추천

8

고정닉 0

0

댓글 영역

전체 댓글 0
등록순정렬 기준선택
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 힘들게 성공한 만큼 절대 논란 안 만들 것 같은 스타는? 운영자 24/06/10 - -
이슈 [디시人터뷰] 웃는 모습이 예쁜 누나, 아나운서 김나정 운영자 24/06/11 - -
93792 마이크 됨? [4] ㅇㅇ(121.152) 06.07 107 0
93791 연습중이다 ㅇㅇ(49.170) 06.07 73 0
93790 -endrms qmffhr [2] 마갤러(222.234) 06.07 157 6
93789 악놀 도끼 상향점… [8] ㅇㅇ(39.121) 06.07 137 0
93788 귀 , 꼬리 까지 있는 사진에 있는 캐릭터 가능한게이 찾음. ㅇㅇ(115.86) 06.07 205 0
93787 마붕아 잘자 ㅇㅇ(119.66) 06.07 60 0
93786 이번 생방 진짜 놓치면 안되겠다 [1] 마갤러(121.152) 06.07 89 0
93785 뉴비 질문.. 마갤러(49.173) 06.07 38 0
93784 띵물의숲 보는 게이들! [4] 마갤러(175.196) 06.07 93 0
93783 지듣노 ㅇㅇ(121.140) 06.07 56 0
93781 팔라딘 소신 발언 [18] 마갤러(218.149) 06.07 206 0
93780 마크 아이템 설명창? 리소스팩으로 바꿀 수 있음 [1] 마갤러(220.86) 06.07 146 0
93779 여러분, 절대 포기하지 마세요. [1] ㅇㅇ(116.41) 06.07 132 1
93778 멈췄던 나의 모래시계가 [3] ㅇㅇ(220.87) 06.07 99 1
93777 여름 준비 [1] ㅇㅇ(218.149) 06.07 59 0
93776 오늘 양생 [2] 마갤러(59.5) 06.07 74 0
93775 새 트윗 알렉스말랑뷰갤로그로 이동합니다. 06.07 83 0
93774 이번주 단타 기대된 민트빙수(121.135) 06.07 57 0
93773 BE] 6년차 반야생 건축서버 - 놀러오셈 해용랜드 오토싱(1.227) 06.06 166 0
93772 핫타임 [5] S2 Zicky(222.236) 06.06 112 0
93771 왜자꾸징징댄다그러는거임 [18] 런닝구(119.66) 06.06 111 0
93770 정신병환자 13세 잼민이 이준우 폭로함. ㅇㅇ(183.99) 06.06 258 0
93769 노래 추천 해주실 분 [2] [16] 큐빌드(175.113) 06.06 91 0
93768 마망호 [6] 마갤러(218.239) 06.06 117 0
93767 옆면만 보고 아이템을 맞혀야 함 ㅇㅇ(123.215) 06.06 76 0
93766 마크는 아직도 서버 아이피 쳐서 들어가냐 마갤러(112.152) 06.06 80 0
93765 마크 의외로 혼자해도 재밌네 [4] ㅇㅇ(121.165) 06.06 138 0
93764 마을을 어떻게 지을까 고민이노 [4] ㅇㅇ(210.91) 06.06 168 0
93763 아 하기 싫다~ [1] ㅇㅇ(61.106) 06.06 82 0
93762 솔직히 현충일 그냥 ㅋㅋ ... [9] 야스오와요네(59.14) 06.06 107 0
93761 마크 초보인데 도와주실분 명령어 도와주실분... [1] 마갤러(175.127) 06.06 43 1
93760 하다보니 여기까지 [9] 마갤러(116.127) 06.06 263 4
93759 커미션 ( Feat. 응애여나 ) “ 달빛 햇빛 ” [3] 햇빛(222.109) 06.06 117 0
93758 팔라딘 [9] ㅇㅇ(121.135) 06.06 160 0
93757 결국 또 질렀다 마갤러(125.191) 06.06 191 0
93756 서버 로그에 계속 뜨는 에러인데 갑자기 왜이럴까 마갤러(115.41) 06.06 58 0
93755 팬아트 받았슴니다. 햇빛(221.144) 06.06 41 0
93754 티그르 [2] ㅇㅇ(121.135) 06.06 181 9
93753 악놀보기가 힘드냐 [28] ㅇㅇ(218.149) 06.06 197 0
93752 팔라딘 ㅇㅇ(182.161) 06.06 84 0
93751 팔라딘 사령 우클차이 미쳤네ㅋㅋ 마갤러(220.95) 06.06 134 0
93750 일어나거라 나의 개척자여! 마갤러(222.121) 06.06 171 5
93749 현재 팔라딘 상태 [73] ㅇㅇ(221.165) 06.06 259 0
93747 스켈레톤 버그있노 [3] 마갤러(175.124) 06.06 173 1
93746 찰칵찰칵... [2] Villain1101(222.106) 06.06 68 0
93745 베드락 버전하는데 템 사라지는데 어케못고침? [1] ㅇㅇ갤로그로 이동합니다. 06.06 46 0
93744 악어형 큰일난거 같아... [5] ㅇㅇ(222.120) 06.06 219 0
93743 아이템에더 셀프호스팅 [1] 자유로운 구름(119.200) 06.06 108 0
93742 우리는 실제로 만난다. [2] 월애임(59.13) 06.06 125 0
93741 개인적으로 느끼는거긴 한데 [3] ㅇㅇ(61.77) 06.06 95 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2