> Java > Java인터뷰 질문들 > 면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

풀어 주다: 2023-07-26 16:07:26
앞으로
1073명이 탐색했습니다.

면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

높은 동시성은 거의 모든 프로그래머가 갖고 싶어하는 경험입니다. 이유는 간단합니다. 트래픽이 증가하면 인터페이스 응답 시간 초과, CPU 로드 증가, 빈번한 GC, 교착 상태, 대용량 데이터 저장 등 다양한 기술적 문제가 발생하게 됩니다. 이러한 문제는 우리가 지속적으로 개선하도록 유도할 수 있습니다. 우리의 기술적 깊이.

과거 인터뷰에서 후보자가 고도의 동시성 프로젝트를 수행한 경우, 주로 후보자에게 고도 동시성에 대한 이해에 대해 이야기해 달라고 요청하지만, 이 질문에 체계적으로 답할 수 있는 사람은 많지 않을 것입니다. 다음 카테고리:

1. 데이터 기반 지표의 개념 없음: 높은 동시성 시스템을 측정하기 위해 어떤 종류의 지표를 선택해야 할지 모르시나요? 동시성과 QPS의 차이를 알 수 없고, 내 시스템의 총 사용자 수, 활성 사용자 수, 플랫 타임과 피크 타임의 QPS 및 TPS, 기타 주요 데이터도 모릅니다.

2. 일부 계획이 설계되었지만 세부 사항이 완전히 파악되지 않았습니다. 주의해야 할 기술적 사항과 계획의 가능한 부작용을 말할 수 없습니다. 예를 들어 읽기 성능에 병목 현상이 발생하면 캐싱이 도입되지만 캐시 적중률, 핫키, 데이터 일관성 등의 문제는 무시됩니다.

3. 높은 동시성 설계와 성능 최적화를 동일시하는 일방적인 이해: 동시 프로그래밍, 다단계 캐싱, 비동기화 및 수평 확장에 대해 이야기하지만 고가용성 설계, 서비스 거버넌스 및 운영을 무시합니다. 유지 보수 보장.

4. 큰 계획을 마스터하지만 가장 기본적인 것은 무시합니다. 수직 레이어링, 수평 파티셔닝, 캐싱과 같은 큰 아이디어를 명확하게 설명할 수 있지만 데이터 구조를 분석할 수 있는 인식이 없습니다. 합리적이고 알고리즘이 효율적이든 아니든 저는 IO와 컴퓨팅의 가장 기본적인 두 가지 차원에서 세부 사항을 최적화하는 것에 대해 생각해 본 적이 없습니다.

이 글에서는 제가 가지고 있는 높은 동시성 프로젝트에서의 경험을 결합하여 높은 동시성에서 숙달해야 할 지식과 실무 아이디어를 체계적으로 정리하여 여러분께 도움이 되기를 바랍니다. 콘텐츠는 다음 3개 부분으로 구성됩니다.

  • 높은 동시성을 이해하는 방법은 무엇입니까?
  • 고동시성 시스템 설계의 목표는 무엇인가요?
  • 높은 동시성을 위한 실용적인 솔루션은 무엇입니까?

01 높은 동시성을 어떻게 이해하나요?

높은 동시성은 대규모 트래픽을 의미하며, 트래픽의 영향에 저항하기 위해 기술적 수단을 사용해야 합니다. 이러한 수단은 트래픽을 운영하는 것과 같아서 시스템에서 트래픽을 보다 원활하게 처리하고 사용자에게 더 나은 경험을 제공할 수 있습니다.

일반적인 높은 동시성 시나리오에는 Taobao의 Double 11, 봄 축제 중 티켓 잡기, Weibo Vs의 최신 뉴스 등이 포함됩니다. 이러한 일반적인 것 외에도 초당 수십만 건의 요청을 처리하는 플래시 세일 시스템, 하루에 수천만 건의 주문을 처리하는 주문 시스템, 하루에 수억 건의 일일 활동을 처리하는 정보 흐름 시스템 등을 모두 분류할 수 있습니다. 높은 동시성으로.

분명히 위에서 언급한 높은 동시성 시나리오에서는 동시성의 양이 다릅니다. 그렇다면 얼마나 많은 동시성이 높은 동시성으로 간주됩니까?

1. 숫자만 볼 수는 없고 구체적인 비즈니스 시나리오를 살펴봐야 합니다. 10W QPS의 플래시 세일은 동시성이 높다고 할 수 없지만, 1W QPS의 정보 흐름은 동시성이 높지 않습니다. 정보 흐름 시나리오에는 복잡한 추천 모델과 다양한 수동 전략이 포함되며, 비즈니스 로직은 깜짝 세일 시나리오보다 10배 이상 복잡할 수 있습니다. 그러므로 같은 차원이 아니며, 비교의미도 없습니다.

2. 비즈니스는 0부터 1까지 구축됩니다. 동시성과 QPS는 참고 지표일 뿐입니다. 가장 중요한 것은 비즈니스 규모가 점차 10배가 될 때 사용합니까, 아니면 높은 동시성을 사용할 때 사용합니까? 처리 방법, 시스템을 발전시키는 방법, 아키텍처 설계, 코딩 구현 및 제품 솔루션 차원에서 높은 동시성으로 인해 발생하는 문제를 예방하고 해결하는 방법은 무엇입니까? 맹목적으로 하드웨어를 업그레이드하고 수평적 확장을 위해 기계를 추가하는 대신.

또한, 각 높은 동시성 시나리오의 비즈니스 특성은 완전히 다릅니다. 읽기는 많고 쓰기는 적은 정보 흐름 시나리오가 있고, 읽고 쓰기가 많은 거래 시나리오가 있습니다. 다양한 시나리오를 해결하기 위한 보편적인 기술 솔루션은 어떻습니까?

큰 아이디어와 다른 사람의 계획에서 배울 수 있다고 생각하지만, 실제 구현 과정에서는 세부 사항에 무수히 많은 함정이 있을 것입니다. 또한, 소프트웨어와 하드웨어 환경, 기술 스택, 제품 로직이 완전히 일관되지 않기 때문에 동일한 비즈니스 시나리오로 이어지더라도 동일한 기술 솔루션을 사용하더라도 다른 문제에 직면하게 되며 이러한 함정은 발생합니다. 하나씩 극복해 나가세요.

따라서 이 글에서는 높은 동시성에 대한 더 깊은 이해를 제공하기 위해 제가 실습한 기본 지식, 일반적인 아이디어 및 효과적인 경험에 중점을 둘 것입니다.

02 동시성 높은 시스템 설계의 목표는 무엇인가요?

먼저 높은 동시성 시스템 설계의 목표를 명확히 한 다음, 의미 있고 타겟이 명확할 수 있도록 설계 계획과 실제 경험을 논의합니다.

2.1 거시적 목표

높은 동시성이 단지 높은 성능을 추구한다는 의미는 아니며, 이는 많은 사람들의 일방적인 이해입니다. 거시적 관점에서 동시성 시스템 설계에는 높은성능, 고가용성, 높은 확장성이라는 세 가지 목표가 있습니다.

1. 고성능: 성능은 제한된 하드웨어 투자로 성능 향상은 비용을 의미합니다. 동시에 성능은 사용자 경험을 반영합니다. 응답 시간은 각각 100밀리초와 1초로 사용자에게 완전히 다른 느낌을 줍니다.

2. 고가용성 : 은 시스템이 정상적으로 서비스될 수 있는 시간을 나타냅니다. 하나는 일년 내내 가동 중지 시간이 없고 다른 하나는 때때로 온라인 사고가 발생하고 사용자는 확실히 전자를 선택할 것입니다. 게다가 시스템의 가용성이 90%에 불과하다면 비즈니스에 큰 지장을 초래할 것입니다.

3. 높은 확장성 : 시스템의 확장성을 나타냅니다. 트래픽이 가장 많은 시간대에 확장이 완료될 수 있는지, Double 11 이벤트와 같은 피크 트래픽을 보다 원활하게 처리할 수 있는지 여부 , 연예인 이혼 등 화끈한 이벤트 .

면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

이 세 가지 목표는 상호 연관되어 있고 심지어 서로 영향을 미치기 때문에 종합적으로 고려해야 합니다.

like 보다: 시스템의 확장성을 고려하고 서비스를 무상태로 설계합니다. , 이런 클러스터는 designdesign은 실제로 시스템의 성능과 유용성도 향상시킵니다.

또 다른 예: 가용성을 보장하기 위해 일반적으로 많은 수의 스레드가 느린 요청을 차단하고 시스템 사태를 일으키는 것을 방지하기 위해 서비스 인터페이스에 시간 초과가 설정됩니다. 그렇다면 합리적인 시간 초과 설정은 무엇입니까? 일반적으로 종속 서비스의 성능을 기반으로 설정을 수행합니다.

2.2 마이크로 목표

미시적 관점에서 고성능, 고가용성 및 높은 확장성을 측정하는 구체적인 지표는 무엇인가요? 이 지표를 선택한 이유는 무엇입니까?

❇ 성능 지표

성능 지표는 현재 성능 문제를 측정하고 성능 최적화를 위한 평가 기준으로 사용할 수 있습니다. 일반적으로 일정 기간 내의 인터페이스 응답 시간이 지표로 사용됩니다.

1. 평균 응답 시간: 가장 일반적으로 사용되지만 결함이 분명하며 느린 요청에 민감하지 않습니다. 예를 들어 10,000개의 요청이 있고 그 중 9,900개가 1ms이고 100개가 100ms라면 평균 응답 시간은 1.99ms입니다. 비록 평균 시간 소모는 0.99ms만 증가했지만 1% 요청에 대한 응답 시간은 100ms 증가했습니다. 타임스.

2, TP90, TP99 및 기타 분위수 값: TP90은 90번째 백분위수로 순위가 매겨진 응답 시간을 나타냅니다. 느린 요청.

면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

3. 처리량: 응답 시간에 반비례합니다. 예를 들어 응답 시간이 1ms이면 처리량은 초당 1000회입니다.

일반적으로 성능 목표를 설정할 때 처리량과 응답 시간을 모두 고려합니다. 예를 들어 초당 요청 10,000개 미만, AVG는 50ms 미만, TP99는 100ms 미만으로 제어됩니다. 동시성이 높은 시스템의 경우 AVG 및 TP 분위수 값을 동시에 고려해야 합니다.

또한 사용자 경험의 관점에서 보면 200밀리초가 첫 번째 구분점으로 간주되어 사용자는 지연을 느끼지 않을 것이며 두 번째 구분점은 사용자가 지연을 느끼지만 허용됩니다. .

따라서 건강한 높은 동시성 시스템을 위해서는 TP99는 200ms 이내에 제어되어야 하고, TP999 또는 TP9999는 1초 이내에 제어되어야 합니다.

❇ 가용성Indicator

가용성은 시스템이 오류 없이 실행될 수 있는 능력이 높다는 것을 의미합니다. 가용성 = 가동 시간/총 시스템 실행 시간은 일반적으로 시스템을 설명하는 데 사용됩니다. .

면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

고동시성 시스템의 경우 가장 기본적인 요구 사항은 3 9s 또는 4 9s를 보장하는 것입니다. 그 이유는 간단합니다. 9만 2개만 할 수 있다면 실패 시간은 1%라는 뜻입니다. 예를 들어 일부 대기업은 종종 GMV가 1,000억이 넘거나 매년 1%의 수익이 비즈니스에 미치는 영향을 의미합니다. 억 수준.

❇ 확장성Indicator

갑작스러운 트래픽에 직면하여 일시적으로 아키텍처를 변환하는 것은 불가능합니다. 가장 빠른 방법은 시스템의 처리 능력을 선형적으로 향상시키기 위해 머신을 추가하는 것입니다.

비즈니스 클러스터나 기본 구성 요소의 경우 확장성 = 성능 향상 비율 / 머신 추가 비율이 이상적인 확장성은 리소스를 여러 번 늘리고 성능을 여러 번 향상시키는 것입니다. 일반적으로 확장능력은 70% 이상을 유지해야 합니다.

그러나 높은 동시성 시스템의 전체 아키텍처 관점에서 볼 때 확장의 목표는 단지 ​​서비스를 무상태로 설계하는 것이 아닙니다. 트래픽이 10배 증가하면 비즈니스 서비스는 10배로 빠르게 확장할 수 있지만 데이터베이스는 새로운 병목 현상이 발생할 수 있습니다.

MySQL과 같은 상태 저장 서비스는 일반적으로 기술적으로 확장하기 어렵습니다. 아키텍처가 사전에 계획되지 않은 경우(수직 및 수평 분할) 대량의 데이터 마이그레이션이 필요합니다.

따라서 높은 확장성을 고려해야 합니다: 서비스 클러스터, 데이터베이스, 캐시 및 메시지 큐와 같은 미들웨어, 로드 밸런싱, 대역폭, 종속 타사 등. 동시성이 특정 수준에 도달하면 위의 각 요소는 확장에 병목 현상이 발생할 수 있습니다.


03 높은 동시성을 위한 실용적인 솔루션은 무엇입니까?
고동시성 설계의 세 가지 주요 목표를 이해한 후, 고동시성 설계 계획을 체계적으로 요약하겠습니다. 이는 다음 두 부분으로 확장됩니다. 먼저 일반적인 설계 방법을 요약한 다음 고성능에 중점을 둡니다. 고가용성, 고확장은 각각 구체적인 실용적인 솔루션을 제공합니다. ㅋㅋㅋ 높은 동시성 처리 두 가지 주요 과제: 수직 확장과 수평 확장.

❇수직 확장(scale-up)

단일 머신의 처리 능력을 향상시키는 것이 목표이며, 계획에는 다음도 포함됩니다.

1. 메모리, CPU 코어, 저장 용량을 늘리거나 광장 에서 디스크 를 SSD 및 기타 하드 웨어 로 업그레이드하여 단일 시스템의 하드웨어 성능을 향상시킵니다. 스타일 개선을 위해 오세요 .
2. 단일 시스템의 소프트웨어 성능을 향상합니다. 캐시를 사용하여 IO 수를 줄이고 동시 또는 비동기 방법을 사용하여 처리량을 늘립니다.

❇ 수평적 확장(scale-out)

단일 머신 성능에는 항상 한계가 있기 때문에 궁극적으로 수평 확장을 도입하고 클러스터 배포를 통해 동시 처리 기능을 더욱 향상시키는 것이 필요합니다. 다음 두 가지 방향을 따릅니다. :

1. 계층적 아키텍처 개발: 이는 수평적 확장을 위한 진보입니다. 왜냐하면 높은 동시성 시스템에는 종종 복잡한 비즈니스가 있고 계층화된 처리를 통해 복잡한 문제를 단순화하고 수평적 확장을 더 쉽게 달성할 수 있기 때문입니다.

면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...

위 그림은 인터넷의 가장 일반적인 계층형 아키텍처입니다. 물론 실제 높은 동시성 시스템 아키텍처는 이를 기반으로 더욱 향상됩니다. 예를 들어, 동적 및 정적 분리가 이루어지고 CDN이 도입될 것입니다. 리버스 프록시 레이어는 LVS+Nginx가 될 수 있고, 웹 레이어는 통합 API 게이트웨이가 될 수 있으며, 비즈니스 서비스 레이어는 수직적 비즈니스에 따라 추가로 마이크로서비스될 수 있습니다. , 저장 계층은 다양한 이기종 데이터베이스가 될 수 있습니다.

2. 각 레이어의 수평 확장: 상태 비저장 수평 확장, 상태 저장 샤드 라우팅. 비즈니스 클러스터는 일반적으로 상태 비저장으로 설계될 수 있지만 데이터베이스와 캐시는 상태 저장이 되는 경우가 많습니다. 따라서 파티션 키는 스토리지 샤딩을 위해 설계되어야 합니다. 물론 마스터-슬레이브 동기화 및 읽기-쓰기 분리를 통해 읽기 성능도 향상될 수 있습니다.

3.2 구체적인 실용 솔루션
제 개인적인 경험을 합쳐 고성능, 고가용성, 고확장성 3가지 측면에서 구현할 수 있는 실용적인 솔루션을 정리해보겠습니다.

❇ 고성능 실용적인 솔루션

1, 클러스터 배포, 로드 밸런싱을 통해 단일 시스템에 대한 부담을 줄입니다.

2. 정적 데이터에 대한 CDN, 로컬 캐싱, 분산 캐싱 등의 사용과 단축키 처리, 캐시 침투, 캐시 동시성, 데이터 일관성 및 캐싱 시나리오의 기타 문제를 포함한 다단계 캐싱 .
3. 하위 데이터베이스, 테이블 및 인덱스 최적화 및 검색 엔진을 사용하여 복잡한 쿼리 문제를 해결합니다.
4. HBase, TiDB 등과 같은 NoSQL 데이터베이스의 사용을 고려하되 팀은 이러한 구성 요소에 익숙해야 하며 강력한 운영 및 유지 관리 능력을 갖추고 있어야 합니다.
5. 멀티스레딩, MQ 및 지연된 작업을 통해 비동기식으로 보조 프로세스를 처리합니다.
6. 현재 제한 먼저 프런트 엔드 흐름 제한을 포함하여 비즈니스에서 흐름 제한을 허용하는지 여부를 고려해야 합니다. 레이어 흐름 제한, 서버 측 전류 제한.
7. 교통 상황에서 피크 저감 및 계곡 채우기를 수행하고 MQ를 통해 교통을 처리합니다.
8. 동시 처리, 멀티스레딩을 통한 직렬 논리 병렬화.
9. 빨간 봉투 잡기 시나리오 등 사전 계산을 통해 빨간 봉투 금액을 미리 계산하여 캐시하고, 빨간 봉투를 보낼 때 직접 사용할 수 있습니다.
10, 캐시 예열, 비동기 작업을 통해 데이터를 로컬 캐시 또는 분산 캐시로 미리 예열 .
11. 데이터베이스 및 캐시와 같은 IO 수를 줄이고 일괄 읽기 및 쓰기, RPC 일괄 인터페이스 지원 또는 중복 데이터를 통해 RPC 호출을 제거합니다.
12. 경량 통신 프로토콜, 적절한 데이터 구조 사용, 인터페이스의 중복 필드 제거, 캐시 키 크기 감소, 캐시 값 압축 등을 포함하여 IO 중 데이터 패킷 크기를 줄입니다.
13. 실행 프로세스를 차단할 확률이 높은 사전 위치 결정 논리, For 루프의 계산 논리 최적화 또는보다 효율적인 알고리즘 사용과 같은 프로그램 논리 최적화.
14. HTTP 요청 풀, 스레드 풀(핵심 매개변수 설정을 위해 CPU 집약적 또는 IO 집약적 고려), 데이터베이스 및 Redis 연결 풀 등을 포함한 다양한 풀링 기술 및 풀 크기 설정 사용
15. 신세대와 구세대의 크기, GC 알고리즘 선택 등을 포함한 JVM 최적화를 통해 GC 빈도와 시간 소모를 최대한 줄입니다.
16. 잠금 선택, 읽기가 많고 쓰기가 적은 시나리오에서는 낙관적 잠금을 사용하거나 분할된 잠금을 통해 잠금 충돌을 줄이는 것을 고려하세요.

위 솔루션은 컴퓨팅과 IO의 두 가지 차원에서 가능한 모든 최적화 지점을 고려한 것에 지나지 않습니다. 현재 성능을 실시간으로 이해하고 성능 병목 현상 분석을 수행할 수 있도록 지원하는 모니터링 시스템이 필요합니다. 그런 다음 28가지 원칙을 따르고 주요 모순을 파악하고 최적화합니다.

❇ 고가용성 실용적인 솔루션

1. 피어 노드의 장애 조치 Nginx와 서비스 거버넌스 프레임워크는 하나의 노드가 실패한 후 다른 노드에 대한 액세스를 지원합니다.

2. 하트비트 감지 및 마스터-슬레이브 전환 구현(예: redis의 센티넬 모드 또는 클러스터 모드, MySQL의 마스터-슬레이브 전환 등)을 통해 비피어 노드의 장애 조치.
3. 인터페이스 수준의 시간 초과 설정, 재시도 전략 및 멱등성 디자인.
4. 다운그레이드 처리: 핵심 서비스 보장, 비핵심 서비스 희생, 필요한 경우 회로 차단 또는 핵심 링크에 문제가 있는 경우 대체 링크가 있습니다.
5. 전류 제한 처리: 시스템 처리 용량을 초과하는 요청에 대해 직접 거부하거나 오류 코드를 반환합니다.
6. 생산자 측의 재시도 메커니즘, 브로커 측의 지속성, 소비자 측의 확인 메커니즘 등을 포함하여 MQ 시나리오에서 메시지 안정성 보장
7. 그레이스케일 릴리스는 시스템 크기에 따라 소규모 트래픽 배포를 지원하고 시스템 로그 및 비즈니스 지표를 관찰한 다음 작업이 안정된 후 전체 볼륨을 푸시할 수 있습니다.
8. 모니터링 및 알람: CPU, 메모리, 디스크, 네트워크에 대한 가장 기본적인 모니터링은 물론 웹 서버, JVM, 데이터베이스, 각종 미들웨어 모니터링, 비즈니스 지표 모니터링까지 포함하는 종합 모니터링 시스템입니다. .
9. 재해 복구 훈련: 현재의 "카오스 엔지니어링"과 유사하게 시스템에 몇 가지 파괴적인 방법을 사용하여 로컬 오류로 인해 가용성 문제가 발생하는지 관찰합니다.

고가용성 솔루션은 주로 중복성, 절충, 시스템 운영 및 유지 관리의 세 가지 방향에서 고려됩니다. 동시에 온라인 문제가 발생할 경우 지원 의무 메커니즘과 오류 처리 프로세스가 필요합니다. 시간 내에 후속 조치를 취할 수 있습니다.

❇ 확장성이 뛰어난 실용적인 솔루션

1. 합리적인 계층형 아키텍처: 예를 들어 위에서 언급한 인터넷에서 가장 일반적인 계층형 아키텍처는 또한 데이터 액세스 계층 및 비즈니스 로직 계층 마이크로서비스는 보다 세분화된 방식으로 계층화됩니다(그러나 네트워크에 홉이 하나 더 있을 수 있으므로 성능을 평가해야 합니다).

2. 저장 계층 분할: 비즈니스 차원에 따른 수직 분할, 데이터 기능 차원(하위 데이터베이스 및 하위 테이블)에 따른 추가 수평 분할.
3. 비즈니스 계층 분할: 가장 일반적인 것은 비즈니스 차원(예: 전자 상거래 시나리오의 상품 서비스, 주문 서비스 등)에 따라 분할하는 것입니다. 및 비핵심 인터페이스이며 요청 소스 제거(예: To C 및 To B, APP 및 H5)에 따라 분할될 수도 있습니다.


마지막으로

높은 동시성은 제한된 공간으로 인해 분산 추적, 전체 링크 스트레스 테스트 및 유연한 트랜잭션과 같은 기술적 사항을 고려해야 합니다. 또한, 비즈니스 시나리오가 다르면 동시성 구현 솔루션도 달라지겠지만 전체적인 디자인 아이디어와 참고할 수 있는 솔루션은 기본적으로 유사합니다.

고동시성 디자인은 또한 건축 디자인의 세 가지 원칙인 단순성, 적절성 및 진화를 준수해야 합니다. "성급한 최적화는 만악의 근원이다", 사업의 실제 상황과 분리될 수 없으며, 과도하게 설계하지 마세요 , 적절한 솔루션이 가장 완벽합니다.

이 글을 통해 높은 동시성에 대한 보다 포괄적인 이해가 되기를 바랍니다. 또한 배울 수 있는 경험과 깊이 있는 생각이 있다면 토론을 위해 댓글 영역에 메시지를 남겨주세요.

위 내용은 면접관: 높은 동시성에 대해 얼마나 알고 있나요? 나: 음...의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:Java学习指南
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿