feat(showcase): 트웬티온스 사이트를 전면 개편한다
All checks were successful
ci / build (push) Successful in 33s

This commit is contained in:
Yun Chan 2026-08-25 03:50:28 +09:00
parent cb3c323c9f
commit 9529e3747c
29 changed files with 8906 additions and 1326 deletions

View file

@ -0,0 +1,94 @@
Copyright (c) 2021, Kil Hyung-jin (https://github.com/orioncactus/pretendard),
with Reserved Font Name Pretendard.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,14 @@
Model: Scifi Drone 1.1
Source: https://sketchfab.com/3d-models/scifi-drone-11-dd21953e81a24bd385d16eaf0c6a8ae7
Author: Javier Martin Hidalgo
Author page: https://sketchfab.com/Jj.Mmhh
License: Creative Commons Attribution 4.0 International (CC BY 4.0)
License URL: https://creativecommons.org/licenses/by/4.0/
This work is based on "Scifi Drone 1.1" by Javier Martin Hidalgo, licensed under CC BY 4.0.
Adaptations for this showcase:
- Converted the source glTF package to a single GLB.
- Resized textures to 1024 px and converted them to WebP.
- Quantized mesh and animation data for web delivery.
- Integrated the model into an original orbital field-instrument scene.

View file

@ -3,35 +3,30 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>트웬티온스 — 네 개의 현장에서 돌아가는 소프트웨어</title>
<title>트웬티온스 — 네 현장을 하나로</title>
<meta
name="description"
content="2020년 설립. 가상현실·산업용 IoT·이커머스 솔루션 전문 기업. VIVEN·EduBill·XD Hub·XD Works 네 개의 자체 제품이 강의실, 데이터센터, 공공기관, 공장 현장에서 돌아간다."
content="트웬티온스는 가상현실, 산업용 IoT, AI SaaS 결제, 현장 애플리케이션을 하나의 제품 체계로 설계하고 운영하는 소프트웨어 스튜디오입니다."
/>
<meta property="og:title" content="트웬티온스 — 네 개의 현장" />
<meta property="og:title" content="트웬티온스 — 네 현장을 하나로" />
<meta
property="og:description"
content="회사 소개 대신 한 일을 앞에 둔다. 6년 159건, 자체 제품 4종."
content="강의실, 데이터센터, 공공기관, 공장의 서로 다른 조건을 실제로 움직이는 소프트웨어로 연결합니다."
/>
<meta property="og:type" content="website" />
<meta name="theme-color" content="#fafaf8" />
<meta property="og:image" content="./og.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="theme-color" content="#0d0f0f" media="(prefers-color-scheme: dark)" />
<meta name="theme-color" content="#e9e7e2" media="(prefers-color-scheme: light)" />
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap"
/>
<link rel="preload" href="./assets/pretendard-twentyoz.woff2" as="font" type="font/woff2" crossorigin />
<link rel="stylesheet" href="./styles/tokens.css" />
<link rel="stylesheet" href="./styles/main.css" />
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23111214'/%3E%3Ctext x='16' y='22' font-family='monospace' font-size='15' font-weight='700' fill='%23FAFAF8' text-anchor='middle'%3E20%3C/text%3E%3C/svg%3E"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23151616'/%3E%3Ccircle cx='16' cy='16' r='7' fill='none' stroke='%23F6F4EF' stroke-width='2'/%3E%3Cpath d='M16 5v22M5 16h22' stroke='%23B9362B'/%3E%3C/svg%3E"
/>
<script defer src="./scripts/core-boot.js"></script>
</head>
<body>
@ -39,604 +34,387 @@
<header class="site-head">
<div class="wrap head-inner">
<a class="wordmark" href="#top">
<span class="wordmark-badge mono" aria-hidden="true">20</span>
<span>트웬티온스</span>
<a class="wordmark" href="#top" aria-label="트웬티온스 처음으로">
<span class="wordmark-mark" aria-hidden="true"><i></i><i></i></span>
<span>TWENTYOZ</span>
</a>
<nav class="nav" aria-label="주요 섹션">
<a href="#products">제품</a>
<a href="#ledger">한 일</a>
<a href="#record">기록</a>
<a href="#contact">연락</a>
<a href="#company">회사</a>
<a href="#contact">문의</a>
</nav>
<p class="head-meta mono">EST. 2020</p>
<p class="head-meta">HWASEONG · KR</p>
</div>
</header>
<main id="main">
<!-- ══════════════════════════════════════════════════════════
1 · 히어로 = 현장 선택기.
회사 이름과 슬로건을 첫 화면에 두지 않는다 — 감수한 리스크다
══════════════════════════════════════════════════════════ -->
<section class="band band-light hero" id="top" aria-labelledby="heroHeading">
<div class="wrap">
<h1 id="heroHeading">
네 개의 현장에서<br />
돌아가고 있다
</h1>
<p class="hero-lead">
트웬티온스는 2020년 1월에 세운 가상현실·산업용 IoT·이커머스 솔루션 회사입니다.
어느 현장의 이야기부터 보시겠습니까.
</p>
<section class="hero" id="top" aria-labelledby="heroHeading">
<div class="hero-stage" aria-hidden="true">
<picture class="core-poster">
<source media="(prefers-color-scheme: dark)" srcset="./assets/core-dark.webp" />
<img
src="./assets/core-light.webp"
width="1600"
height="900"
alt="트웬티온스의 네 산업 현장을 연결하는 정밀 공간 코어"
fetchpriority="high"
decoding="async"
/>
</picture>
<canvas id="coreCanvas"></canvas>
</div>
<form class="fields">
<div class="wrap hero-grid">
<div class="hero-copy">
<p class="eyebrow">Independent software studio · since 2020</p>
<h1 id="heroHeading">네 현장을 하나로</h1>
<p class="hero-lead">
가상현실부터 산업용 IoT까지. 서로 다른 현장의 데이터를 읽고,
사람이 바로 움직일 수 있는 하나의 시스템으로 바꿉니다.
</p>
<div class="hero-actions">
<a class="button button-primary" href="mailto:hello@twentyoz.kr?subject=%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%20%EB%AC%B8%EC%9D%98">
프로젝트 문의
</a>
<a class="text-link" href="#fields">현장 선택</a>
<button class="motion-toggle" id="motionToggle" type="button" aria-pressed="false" hidden>
3D 모션 끄기
</button>
</div>
<output class="sr-only" id="coreStatus" aria-live="polite">선택한 현장: 강의실과 훈련장</output>
</div>
<form class="fields" id="fields">
<fieldset>
<legend class="sr-only">현장 고르기</legend>
<legend class="sr-only">트웬티온스가 일하는 현장 선택</legend>
<input type="radio" name="field" id="field-edu" class="field-radio" checked />
<input type="radio" name="field" id="field-dc" class="field-radio" />
<input type="radio" name="field" id="field-gov" class="field-radio" />
<input type="radio" name="field" id="field-plant" class="field-radio" />
<input type="radio" name="field" id="field-edu" class="field-radio" value="edu" checked />
<input type="radio" name="field" id="field-dc" class="field-radio" value="dc" />
<input type="radio" name="field" id="field-gov" class="field-radio" value="gov" />
<input type="radio" name="field" id="field-plant" class="field-radio" value="plant" />
<div class="field-tabs">
<label for="field-edu">
<span class="tab-num mono">01</span>
<span class="tab-name">강의실과 훈련장</span>
<label for="field-edu" aria-label="강의실과 훈련장">
<span class="tab-num">01</span>
<span class="tab-long">강의실과 훈련장</span>
<span class="tab-short">교육·훈련</span>
</label>
<label for="field-dc">
<span class="tab-num mono">02</span>
<span class="tab-name">데이터센터와 발전소</span>
<label for="field-dc" aria-label="데이터센터와 발전소">
<span class="tab-num">02</span>
<span class="tab-long">데이터센터와 발전소</span>
<span class="tab-short">데이터·에너지</span>
</label>
<label for="field-gov">
<span class="tab-num mono">03</span>
<span class="tab-name">공공기관과 대학 행정</span>
<label for="field-gov" aria-label="공공기관과 대학 행정">
<span class="tab-num">03</span>
<span class="tab-long">공공기관과 대학 행정</span>
<span class="tab-short">행정·결제</span>
</label>
<label for="field-plant">
<span class="tab-num mono">04</span>
<span class="tab-name">공장과 설비 현장</span>
<label for="field-plant" aria-label="공장과 설비 현장">
<span class="tab-num">04</span>
<span class="tab-long">공장과 설비 현장</span>
<span class="tab-short">설비·공정</span>
</label>
</div>
<div class="field-panels">
<div class="field-panels" aria-live="polite">
<article class="field-panel" data-panel="edu">
<p class="panel-what">
헤드셋을 쓴 학생이 실습을 하고, 강사는 그 장면을 밖에서 본다.
캐릭터의 몸짓은 웹캠 한 대로 잡는다.
</p>
<div class="panel-intro">
<p class="panel-index">Field 01 · Immersive learning</p>
<p class="panel-what">
헤드셋을 쓴 학생의 실습을 강사가 밖에서 보고, 웹캠 한 대로 캐릭터의 몸짓까지 잡습니다.
</p>
</div>
<dl class="panel-facts">
<div>
<dt>제품</dt>
<dd><strong>VIVEN</strong> — 몰입형 VR 교육·훈련 플랫폼</dd>
</div>
<div>
<dt>기술</dt>
<dd class="mono">Unity3D × WebXR × MediaPipe</dd>
</div>
<div>
<dt>특징</dt>
<dd>PC VMC · Mobile VMC 모듈로 캐릭터 실시간 모션캡처</dd>
</div>
<div>
<dt>납품 사례</dt>
<dd>미래기술학교 운영 (2024) · 메타버스 기반 교육 플랫폼</dd>
</div>
<div>
<dt>성숙도</dt>
<dd class="mono">TRL 9 · 2021 – 현재</dd>
</div>
<div><dt>제품</dt><dd><strong>VIVEN</strong> · 몰입형 VR 교육·훈련 플랫폼</dd></div>
<div><dt>기술</dt><dd>Unity3D × WebXR × MediaPipe</dd></div>
<div><dt>특징</dt><dd>PC VMC · Mobile VMC 실시간 모션캡처</dd></div>
<div><dt>납품</dt><dd>미래기술학교 운영 · 메타버스 기반 교육 플랫폼</dd></div>
<div><dt>성숙도</dt><dd>TRL 9 · 2021 – 현재</dd></div>
</dl>
</article>
<article class="field-panel" data-panel="dc">
<p class="panel-what">
설비 여섯 종류가 각자의 프로토콜로 떠드는 것을 한 엔진이 받아
같은 시간축에 올린다. 그 위에서 운전이 자동으로 돈다.
</p>
<div class="panel-intro">
<p class="panel-index">Field 02 · Connected operations</p>
<p class="panel-what">
서로 다른 여섯 산업 프로토콜을 한 엔진이 받아 같은 시간축에 올리고, 그 위에서 운전을 자동화합니다.
</p>
</div>
<dl class="panel-facts">
<div>
<dt>제품</dt>
<dd>
<strong>XD Hub</strong> — 산업용 IoT 데이터 통합 엔진<br />
<strong>XD Works</strong> — DCIM · FEMS 통합 운영 애플리케이션
</dd>
</div>
<div>
<dt>기술</dt>
<dd class="mono">
Java Spring Boot × Netty × TimescaleDB<br />
Spring Boot × NestJS × TypeScript
</dd>
</div>
<div>
<dt>특징</dt>
<dd>6종 산업 프로토콜을 단일 엔진으로 수집·전처리·전송</dd>
</div>
<div>
<dt>납품 사례</dt>
<dd>
과천 데이터 센터 · LS 일렉 청주 FEMS · 제주 폐기물 EMS ·
비금도 EMS · 한유 AFIMS (모두 2024)
</dd>
</div>
<div>
<dt>성숙도</dt>
<dd class="mono">TRL 8 · 2022 – 현재</dd>
</div>
<div><dt>제품</dt><dd><strong>XD Hub · XD Works</strong> · 데이터 통합과 운영 자동화</dd></div>
<div><dt>기술</dt><dd>Spring Boot × Netty × TimescaleDB × NestJS</dd></div>
<div><dt>특징</dt><dd>6종 산업 프로토콜 수집·전처리·전송</dd></div>
<div><dt>납품</dt><dd>과천 DC · LS 일렉 청주 FEMS · 제주·비금도 EMS · 한유 AFIMS</dd></div>
<div><dt>성숙도</dt><dd>TRL 8 · 2022 – 현재</dd></div>
</dl>
</article>
<article class="field-panel" data-panel="gov">
<p class="panel-what">
해외 AI 서비스를 쓰고 싶은데 법인카드도 세금계산서도 안 되는 기관이 있다.
그 사이에 들어가 원화 결제와 증빙을 대신한다.
</p>
<div class="panel-intro">
<p class="panel-index">Field 03 · Public AI access</p>
<p class="panel-what">
해외 AI 서비스를 쓰기 어려운 기관을 위해 원화 결제와 세금계산서 발행을 하나의 흐름으로 연결합니다.
</p>
</div>
<dl class="panel-facts">
<div>
<dt>제품</dt>
<dd><strong>EduBill</strong> — AI SaaS 구독 대행 플랫폼</dd>
</div>
<div>
<dt>기술</dt>
<dd class="mono">Next.js × TypeScript × Supabase PostgreSQL</dd>
</div>
<div>
<dt>쓰는 곳</dt>
<dd>공공기관 · 대학 · 초중고 · 기업 HRD</dd>
</div>
<div>
<dt>납품 사례</dt>
<dd>KDIS EAI (2024) · EduBill (2024)</dd>
</div>
<div>
<dt>성숙도</dt>
<dd class="mono">TRL 8 · 2024 – 현재</dd>
</div>
<div><dt>제품</dt><dd><strong>EduBill</strong> · AI SaaS 구독 대행 플랫폼</dd></div>
<div><dt>기술</dt><dd>Next.js × TypeScript × Supabase PostgreSQL</dd></div>
<div><dt>현장</dt><dd>공공기관 · 대학 · 초중고 · 기업 HRD</dd></div>
<div><dt>납품</dt><dd>KDIS EAI · EduBill</dd></div>
<div><dt>성숙도</dt><dd>TRL 8 · 2024 – 현재</dd></div>
</dl>
</article>
<article class="field-panel" data-panel="plant">
<p class="panel-what">
현장에서는 사무실 화면이 안 열린다. 장갑 낀 손과 밝은 햇빛,
끊기는 통신을 전제로 다시 만든다.
</p>
<div class="panel-intro">
<p class="panel-index">Field 04 · Industrial interface</p>
<p class="panel-what">
장갑 낀 손, 밝은 햇빛, 끊기는 통신을 전제로 사무실 화면을 현장용 인터페이스로 다시 만듭니다.
</p>
</div>
<dl class="panel-facts">
<div>
<dt>성격</dt>
<dd>고객사 설비·공정에 맞춰 짓는 현장 애플리케이션</dd>
</div>
<div>
<dt>납품 사례</dt>
<dd>
브래키츠 BSLIM · 영진EL 2.0 스마트 APP · LS 전선 부스덕트 (모두 2024)
</dd>
</div>
<div>
<dt>기술</dt>
<dd class="mono">Spring Boot / PostgreSQL / WebSocket · Vue3</dd>
</div>
<div>
<dt>가장 무거운 것</dt>
<dd>
ACS (Auto Control System) — Unity Engine · RFS 실시간 유체 시뮬레이션 ·
Transformer 기반 AI (2024)
</dd>
</div>
<div><dt>성격</dt><dd>고객사 설비·공정에 맞춘 현장 애플리케이션</dd></div>
<div><dt>기술</dt><dd>Spring Boot × PostgreSQL × WebSocket × Vue3</dd></div>
<div><dt>납품</dt><dd>브래키츠 BSLIM · 영진EL 2.0 · LS 전선 부스덕트</dd></div>
<div><dt>시뮬레이션</dt><dd>Unity Engine · RFS 실시간 유체 · Transformer AI</dd></div>
<div><dt>대표 시스템</dt><dd>ACS · Auto Control System</dd></div>
</dl>
</article>
</div>
</fieldset>
</form>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
2 · 회사
══════════════════════════════════════════════════════════ -->
<section class="band band-light section-about" id="about" aria-labelledby="aboutHeading">
<div class="wrap split">
<div class="split-lead">
<h2 id="aboutHeading">여섯 해 동안 쌓인 것</h2>
</div>
<div class="split-body">
<p class="lead">
서로 다른 산업의 프로젝트 경험과 새 기술을 붙여, 고객이 다음 성장 동력을 찾도록
돕는 것이 하는 일입니다. 에너지, 건물 자동화, 헬스케어처럼 틀리면 곤란한 영역이
주 무대입니다.
</p>
<dl class="counts">
<div>
<dt>수행 프로젝트</dt>
<dd class="mono">159<span>건</span></dd>
</div>
<div>
<dt>고객사</dt>
<dd class="mono">42<span>곳</span></dd>
</div>
<div>
<dt>구성원</dt>
<dd class="mono">40<span>명</span></dd>
</div>
<div>
<dt>특허</dt>
<dd class="mono">4<span>건</span></dd>
</div>
</dl>
<p class="counts-note">
위 넷은 회사가 공개한 값입니다. 아래 <a href="#ledger">한 일</a> 목록에는
그중 공개 가능한 49건의 일부를 이름·연도·기술 스택과 함께 적었습니다.
<section class="section proof" aria-labelledby="proofHeading">
<div class="wrap proof-grid">
<div class="section-intro">
<p class="eyebrow">Operational proof</p>
<h2 id="proofHeading">운영 결과를 수치로 증명합니다</h2>
<p>
서로 다른 산업의 경험과 새 기술을 붙여 고객의 다음 운영 방식을 만드는 것이 하는 일입니다.
</p>
</div>
<dl class="counts">
<div><dt>수행 프로젝트</dt><dd>159<span>건</span></dd></div>
<div><dt>고객사</dt><dd>42<span>곳</span></dd></div>
<div><dt>구성원</dt><dd>40<span>명</span></dd></div>
<div><dt>특허</dt><dd>4<span>건</span></dd></div>
</dl>
<p class="source-note">
2026년 8월 24일 기준
<a href="https://twentyoz.kr/" target="_blank" rel="noreferrer">트웬티온스 공식 공개 자료</a>의 값입니다.
아래에는 공개 가능한 49건 중 12건을 이름·연도·기술과 함께 적었습니다.
</p>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
3 · 제품 — 반전 밴드. 제품은 기계다
══════════════════════════════════════════════════════════ -->
<section class="band band-dark section-products" id="products" aria-labelledby="prodHeading">
<section class="section principles" aria-labelledby="principlesHeading">
<div class="wrap">
<p class="eyebrow">자체 제품</p>
<h2 id="prodHeading">팔러 다니는 것이 아니라 계속 고치는 것</h2>
<p class="section-lead">
네 개 모두 특정 고객의 요구에서 시작해 제품이 됐습니다. 지금도 각자의 개발 주기가
돌아가고 있습니다.
</p>
<div class="section-intro section-intro-wide">
<p class="eyebrow">Operating principles · 04</p>
<h2 id="principlesHeading">서로 다른 기술을 하나의 운영 기준으로 연결합니다</h2>
<p>프로젝트의 분야가 달라도 설계와 검증에 적용하는 네 가지 원칙은 같습니다.</p>
</div>
<ol class="principle-list">
<li><p>01 / Hybrid</p><h3>교배</h3><span>산업 경험과 신기술을 결합해 현장에 필요한 새로운 운영 방식을 만듭니다.</span></li>
<li><p>02 / Continuum</p><h3>연속성</h3><span>단발성 납품에 머물지 않고 제품과 프로젝트를 지속적으로 고도화합니다.</span></li>
<li><p>03 / Precision</p><h3>정확성</h3><span>에너지·건물 자동화·헬스케어처럼 오차 비용이 큰 영역에서 정확성을 우선합니다.</span></li>
<li><p>04 / Empowerment</p><h3>확장성</h3><span>자동화된 운영과 데이터 기반 의사결정이 고객 조직 안에서 이어지도록 설계합니다.</span></li>
</ol>
</div>
</section>
<section class="section products" id="products" aria-labelledby="productsHeading">
<div class="wrap">
<div class="section-intro section-intro-wide">
<p class="eyebrow">Product system · 04</p>
<h2 id="productsHeading">한 번 납품하고 끝내지 않는 네 개의 시스템</h2>
<p>특정 고객의 요구에서 시작했지만, 지금도 각자의 개발 주기로 계속 고치고 있습니다.</p>
</div>
<ol class="product-list">
<li>
<p class="prod-id mono">V–01</p>
<div class="prod-body">
<h3>VIVEN <span class="prod-kind">메타버스 플랫폼</span></h3>
<p>
기업과 교육기관을 위한 몰입형 VR 교육·훈련 플랫폼. PC VMC 와 Mobile VMC
모듈로 캐릭터 실시간 모션캡처를 지원합니다.
</p>
<p class="prod-stack mono">Unity3D × WebXR × MediaPipe</p>
<p class="product-id">01 / 04</p>
<div class="product-main">
<h3>VIVEN</h3>
<p>기업과 교육기관을 위한 몰입형 VR 교육·훈련 플랫폼. PC와 모바일 VMC로 캐릭터의 몸짓을 실시간으로 연결합니다.</p>
<p class="tech-line">Unity3D × WebXR × MediaPipe</p>
<a class="product-link" href="./products.html#viven">VIVEN 상세 보기</a>
</div>
<dl class="prod-meta mono">
<div><dt>규모</dt><dd>Enterprise</dd></div>
<div><dt>주기</dt><dd>2021 –</dd></div>
<div><dt>성숙도</dt><dd>TRL 9</dd></div>
<dl class="product-meta">
<div><dt>Domain</dt><dd>Immersive learning</dd></div>
<div><dt>Cycle</dt><dd>2021 –</dd></div>
<div><dt>Maturity</dt><dd>TRL 9</dd></div>
</dl>
</li>
<li>
<p class="prod-id mono">V–02</p>
<div class="prod-body">
<h3>EduBill <span class="prod-kind">교육 SaaS</span></h3>
<p>
공공기관·대학·초중고·기업 HRD 를 위한 AI SaaS 구독 대행 플랫폼.
해외 AI 서비스를 원화 결제와 세금계산서 발행으로 들여옵니다.
</p>
<p class="prod-stack mono">Next.js × TypeScript × Supabase PostgreSQL</p>
<p class="product-id">02 / 04</p>
<div class="product-main">
<h3>EduBill</h3>
<p>공공기관·대학·초중고·기업 HRD가 해외 AI 서비스를 원화 결제와 세금계산서로 구독하도록 연결합니다.</p>
<p class="tech-line">Next.js × TypeScript × Supabase PostgreSQL</p>
<a class="product-link" href="./products.html#edubill">EduBill 상세 보기</a>
</div>
<dl class="prod-meta mono">
<div><dt>규모</dt><dd>B2G · 교육</dd></div>
<div><dt>주기</dt><dd>2024 –</dd></div>
<div><dt>성숙도</dt><dd>TRL 8</dd></div>
<dl class="product-meta">
<div><dt>Domain</dt><dd>Public AI access</dd></div>
<div><dt>Cycle</dt><dd>2024 –</dd></div>
<div><dt>Maturity</dt><dd>TRL 8</dd></div>
</dl>
</li>
<li>
<p class="prod-id mono">V–03</p>
<div class="prod-body">
<h3>XD Hub <span class="prod-kind">산업용 IoT</span></h3>
<p>
데이터센터·제조·에너지·빌딩 도메인을 위한 산업용 IoT 데이터 통합 엔진.
6종 산업 프로토콜을 단일 엔진으로 수집·전처리·전송합니다.
</p>
<p class="prod-stack mono">Java Spring Boot × Netty × TimescaleDB</p>
<p class="product-id">03 / 04</p>
<div class="product-main">
<h3>XD Hub</h3>
<p>데이터센터·제조·에너지·빌딩의 여섯 산업 프로토콜을 단일 엔진으로 수집하고 전처리해 전송합니다.</p>
<p class="tech-line">Java Spring Boot × Netty × TimescaleDB</p>
<a class="product-link" href="./products.html#xd-hub">XD Hub 상세 보기</a>
</div>
<dl class="prod-meta mono">
<div><dt>규모</dt><dd>설비</dd></div>
<div><dt>주기</dt><dd>2022 –</dd></div>
<div><dt>성숙도</dt><dd>TRL 8</dd></div>
<dl class="product-meta">
<div><dt>Domain</dt><dd>Industrial IoT</dd></div>
<div><dt>Cycle</dt><dd>2022 –</dd></div>
<div><dt>Maturity</dt><dd>TRL 8</dd></div>
</dl>
</li>
<li>
<p class="prod-id mono">V–04</p>
<div class="prod-body">
<h3>XD Works <span class="prod-kind">DCIM · FEMS</span></h3>
<p>
XD Hub 가 모은 데이터를 받아 데이터센터 코로케이션, 빌딩, 공장, 발전소의
운영을 자동화하는 통합 운영 애플리케이션입니다.
</p>
<p class="prod-stack mono">Spring Boot × NestJS × TypeScript</p>
<p class="product-id">04 / 04</p>
<div class="product-main">
<h3>XD Works</h3>
<p>XD Hub가 모은 데이터를 받아 데이터센터, 빌딩, 공장, 발전소의 운영을 자동화하는 통합 애플리케이션입니다.</p>
<p class="tech-line">Spring Boot × NestJS × TypeScript</p>
<a class="product-link" href="./products.html#xd-works">XD Works 상세 보기</a>
</div>
<dl class="prod-meta mono">
<div><dt>규모</dt><dd>설비 · B2B</dd></div>
<div><dt>주기</dt><dd>2023 –</dd></div>
<div><dt>성숙도</dt><dd>TRL 8</dd></div>
<dl class="product-meta">
<div><dt>Domain</dt><dd>DCIM · FEMS</dd></div>
<div><dt>Cycle</dt><dd>2023 –</dd></div>
<div><dt>Maturity</dt><dd>TRL 8</dd></div>
</dl>
</li>
</ol>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
4 · 한 일 — 프로젝트 원장
══════════════════════════════════════════════════════════ -->
<section class="band band-light section-ledger" id="ledger" aria-labelledby="ledgerHeading">
<div class="wrap">
<h2 id="ledgerHeading">한 일</h2>
<p class="section-lead">
공개 가능한 49건 가운데 12건입니다. 회사 소개서에 쓰는 문장 대신 이름과 연도,
그리고 무엇으로 만들었는지를 적습니다.
</p>
<section class="section ledger-section" id="ledger" aria-labelledby="ledgerHeading">
<div class="wrap ledger-grid">
<div class="section-intro sticky-intro">
<p class="eyebrow">Selected work · 12 / 49</p>
<h2 id="ledgerHeading">프로젝트는 이름과 기술로 증명합니다</h2>
<p>
소개서 문장 대신 실제 프로젝트, 완료 연도, 사용 기술을 남깁니다.
마지막 항목은 GPU 위에서 공기 흐름을 실시간으로 풀어 제어를 검증합니다.
</p>
</div>
<table class="ledger">
<caption class="sr-only">트웬티온스 수행 프로젝트 12건 — 이름, 연도, 사용 기술</caption>
<thead>
<tr>
<th scope="col" class="col-id">번호</th>
<th scope="col">프로젝트</th>
<th scope="col" class="col-year">연도</th>
<th scope="col">기술</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mono">001</td>
<th scope="row">EduBill</th>
<td class="mono">2024</td>
<td class="mono">Next.js · TypeScript · Supabase PostgreSQL</td>
</tr>
<tr>
<td class="mono">002</td>
<th scope="row">과천 데이터 센터</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · PostgreSQL</td>
</tr>
<tr>
<td class="mono">003</td>
<th scope="row">제주 폐기물 EMS</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · PostgreSQL</td>
</tr>
<tr>
<td class="mono">004</td>
<th scope="row">KDIS EAI</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · PostgreSQL</td>
</tr>
<tr>
<td class="mono">005</td>
<th scope="row">LS 일렉 청주 FEMS</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · PostgreSQL</td>
</tr>
<tr>
<td class="mono">006</td>
<th scope="row">LS 전선 부스덕트</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · PostgreSQL</td>
</tr>
<tr>
<td class="mono">007</td>
<th scope="row">브래키츠 BSLIM</th>
<td class="mono">2024</td>
<td class="mono">Spring Boot · PostgreSQL · WebSocket</td>
</tr>
<tr>
<td class="mono">008</td>
<th scope="row">영진EL 2.0 스마트 APP</th>
<td class="mono">2024</td>
<td class="mono">Vue3</td>
</tr>
<tr>
<td class="mono">009</td>
<th scope="row">미래기술학교 운영</th>
<td class="mono">2024</td>
<td class="mono">Unity Engine · Blender · Unreal Engine</td>
</tr>
<tr>
<td class="mono">010</td>
<th scope="row">한유 AFIMS</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · PostgreSQL</td>
</tr>
<tr>
<td class="mono">011</td>
<th scope="row">비금도 EMS</th>
<td class="mono">2024</td>
<td class="mono">Vue3 · Spring · Java</td>
</tr>
<tr class="row-mark">
<td class="mono">012</td>
<th scope="row">ACS (Auto Control System)</th>
<td class="mono">2024</td>
<td class="mono">Unity Engine · RFS 실시간 유체 시뮬레이션 · Transformer 기반 AI</td>
</tr>
</tbody>
</table>
<p class="ledger-note">
마지막 줄이 지금 가장 멀리 가 있는 일입니다. 데이터센터의 공기 흐름을 GPU 위에서
실시간으로 풀어 제어를 검증합니다.
</p>
<div class="table-wrap" tabindex="0" role="region" aria-label="트웬티온스 프로젝트 목록">
<table class="ledger">
<caption class="sr-only">트웬티온스 수행 프로젝트 12건</caption>
<thead>
<tr><th scope="col">No.</th><th scope="col">프로젝트</th><th scope="col">연도</th><th scope="col">기술</th></tr>
</thead>
<tbody>
<tr><td data-label="번호">001</td><th scope="row">EduBill</th><td data-label="연도">2024</td><td data-label="기술">Next.js · TypeScript · Supabase PostgreSQL</td></tr>
<tr><td data-label="번호">002</td><th scope="row">과천 데이터 센터</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · PostgreSQL</td></tr>
<tr><td data-label="번호">003</td><th scope="row">제주 폐기물 EMS</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · PostgreSQL</td></tr>
<tr><td data-label="번호">004</td><th scope="row">KDIS EAI</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · PostgreSQL</td></tr>
<tr><td data-label="번호">005</td><th scope="row">LS 일렉 청주 FEMS</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · PostgreSQL</td></tr>
<tr><td data-label="번호">006</td><th scope="row">LS 전선 부스덕트</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · PostgreSQL</td></tr>
<tr><td data-label="번호">007</td><th scope="row">브래키츠 BSLIM</th><td data-label="연도">2024</td><td data-label="기술">Spring Boot · PostgreSQL · WebSocket</td></tr>
<tr><td data-label="번호">008</td><th scope="row">영진EL 2.0 스마트 APP</th><td data-label="연도">2024</td><td data-label="기술">Vue3</td></tr>
<tr><td data-label="번호">009</td><th scope="row">미래기술학교 운영</th><td data-label="연도">2024</td><td data-label="기술">Unity Engine · Blender · Unreal Engine</td></tr>
<tr><td data-label="번호">010</td><th scope="row">한유 AFIMS</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · PostgreSQL</td></tr>
<tr><td data-label="번호">011</td><th scope="row">비금도 EMS</th><td data-label="연도">2024</td><td data-label="기술">Vue3 · Spring · Java</td></tr>
<tr class="ledger-focus"><td data-label="번호">012</td><th scope="row">ACS · Auto Control System</th><td data-label="연도">2024</td><td data-label="기술">Unity Engine · RFS 실시간 유체 시뮬레이션 · Transformer AI</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
5 · 함께 일한 곳
══════════════════════════════════════════════════════════ -->
<section class="band band-light section-partners" id="partners" aria-labelledby="partnersHeading">
<div class="wrap">
<h2 id="partnersHeading">함께 일한 곳</h2>
<p class="section-lead">
대학과 대기업 설비 부문이 섞여 있습니다. 어느 쪽이든 검수 기준이 까다로운 곳입니다.
</p>
<ul class="partners">
<li>LS SAUTER</li>
<li>경희대학교</li>
<li>SAEKI P&amp;C</li>
<li>KDI School</li>
<li>COSS 사업단</li>
<li>클라우드브릭</li>
<li>한유</li>
<li>게임랩</li>
<li>METANET PLATFORM</li>
<li>안랩</li>
<li>강원대학교</li>
<li>중앙대학교</li>
<li>건국대학교</li>
<li>한화솔루션</li>
<li>가비아</li>
<li>GS칼텍스</li>
<li>SK하이닉스</li>
<li>LG디스플레이</li>
<li>대구한의대학교</li>
<section class="section company" id="company" aria-labelledby="companyHeading">
<div class="wrap company-grid">
<div class="section-intro">
<p class="eyebrow">Company record</p>
<h2 id="companyHeading">엄격한 검수 기준의 현장과 함께해 왔습니다</h2>
<p>대학, 공공기관, 대기업 설비 부문처럼 운영 중단의 비용이 큰 현장이 주 무대입니다.</p>
</div>
<ul class="partners" aria-label="함께 일한 곳">
<li>LS SAUTER</li><li>경희대학교</li><li>SAEKI P&amp;C</li><li>KDI School</li>
<li>COSS 사업단</li><li>클라우드브릭</li><li>한유</li><li>게임랩</li>
<li>METANET PLATFORM</li><li>안랩</li><li>강원대학교</li><li>중앙대학교</li>
<li>건국대학교</li><li>한화솔루션</li><li>가비아</li><li>GS칼텍스</li>
<li>SK하이닉스</li><li>LG디스플레이</li><li>대구한의대학교</li>
</ul>
<details class="archive" id="record" open>
<summary>
<span>최근 외부 기록</span>
<span>07 entries</span>
</summary>
<ol class="record-list">
<li><time datetime="2026-02-25">2026.02.25</time><div><h3><a href="https://twentyoz.kr/news/111" target="_blank" rel="noreferrer">K기술대상 산업대상 수상</a></h3><p>실감미디어·산업용 IoT 분야의 기술 혁신 성과를 인정받았습니다.</p></div><span>수상·인증</span></li>
<li><time datetime="2026-02-24">2026.02.24</time><div><h3>경기우수벤처기업 표창</h3><p>경기지방중소벤처기업청장상 · 기술·경영·혁신과 사회공헌 인정</p></div><span>수상·인증</span></li>
<li><time datetime="2026-01-20">2026.01.20</time><div><h3>2025 경기도 일자리 우수기업 인증</h3><p>고용증가율, 근무환경, 복리후생 제도 개선으로 인정</p></div><span>수상·인증</span></li>
<li><time datetime="2025-11-03">2025.11.03</time><div><h3>건국대, 시리아·요르단 교육기관 대표단 방문</h3><p>함께 개발한 메타버스 기반 교육 플랫폼 시연</p></div><span>교육·협력</span></li>
<li><time datetime="2025-10-31">2025.10.31</time><div><h3>중동 대표단, X-Space에서 K-에듀테크 체험</h3><p>메타버스 기반 교육 플랫폼 체험과 협력 논의</p></div><span>교육·협력</span></li>
<li><time datetime="2025-08-19">2025.08.19</time><div><h3>과기정통부 가상융합대학원 성과공유회</h3><p>서강대 개최 · AI 시대 인재양성 비전 논의 참여</p></div><span>행사</span></li>
<li><time datetime="2025-07-04">2025.07.04</time><div><h3>벤처기업 혁신성장유형 재인증</h3><p>기술 중심 비전과 디지털 혁신 노력 인정</p></div><span>수상·인증</span></li>
</ol>
</details>
<details class="archive career" id="career">
<summary>
<span>현재 채용 상태</span>
<span>정규 공고 마감</span>
</summary>
<div class="career-body">
<p>닫힌 공고를 열려 있는 것처럼 보이지 않게 상태를 그대로 적습니다.</p>
<ul class="jobs">
<li><strong>시니어 소프트웨어 엔지니어</strong><span>산업용 소프트웨어 · C++ / C# / Python · PLC · HMI · SCADA</span><em>마감</em></li>
<li><strong>DevOps 엔지니어</strong><span>컨테이너 · 오케스트레이션 · CI/CD · IaC</span><em>마감</em></li>
<li><strong>프로덕트 매니저</strong><span>IT 서비스 기획·운영 · 데이터 기반 의사결정</span><em>마감</em></li>
<li><strong>서비스 기획자</strong><span>UI/UX 기획 · 와이어프레임 · 애자일 / 스크럼</span><em>마감</em></li>
<li><strong>UI/UX 디자이너</strong><span>Figma · 웹 / 모바일 · 사용자 중심 설계</span><em>마감</em></li>
</ul>
<a class="text-link" href="mailto:hello@twentyoz.kr?subject=%EC%B1%84%EC%9A%A9%20%EB%AC%B8%EC%9D%98">채용 문의 보내기</a>
</div>
</details>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
6 · 기록 — 반전 밴드
══════════════════════════════════════════════════════════ -->
<section class="band band-dark section-record" id="record" aria-labelledby="recordHeading">
<div class="wrap">
<p class="eyebrow">최근 기록</p>
<h2 id="recordHeading">밖에서 확인된 것</h2>
<ol class="record-list">
<li>
<p class="rec-date mono">2026.02.24</p>
<div>
<h3>경기우수벤처기업 표창 — 경기지방중소벤처기업청장상</h3>
<p>기술·경영·혁신 능력이 뛰어나고 사회공헌도가 높은 벤처기업으로 인정</p>
</div>
<p class="rec-kind">수상 · 인증</p>
</li>
<li>
<p class="rec-date mono">2026.01.20</p>
<div>
<h3>2025 경기도 일자리 우수기업 인증</h3>
<p>고용증가율 10% 이상, 근무환경과 복리후생 제도 개선으로 인정</p>
</div>
<p class="rec-kind">수상 · 인증</p>
</li>
<li>
<p class="rec-date mono">2025.11.03</p>
<div>
<h3>건국대, 시리아·요르단 교육기관 대표단 방문</h3>
<p>트웬티온스와 함께 개발한 메타버스 기반 교육 플랫폼 시연</p>
</div>
<p class="rec-kind">교육 · 협력</p>
</li>
<li>
<p class="rec-date mono">2025.10.31</p>
<div>
<h3>중동 대표단, X-Space 에서 K-에듀테크 체험</h3>
<p>메타버스 기반 교육 플랫폼 체험과 협력 논의</p>
</div>
<p class="rec-kind">교육 · 협력</p>
</li>
<li>
<p class="rec-date mono">2025.08.19</p>
<div>
<h3>과기정통부 2025 가상융합대학원 성과공유회</h3>
<p>서강대 개최. AI 시대 인재양성 비전 논의에 참여</p>
</div>
<p class="rec-kind">행사</p>
</li>
<li>
<p class="rec-date mono">2025.07.04</p>
<div>
<h3>벤처기업 혁신성장유형 재인증</h3>
<p>기술 중심의 비전과 디지털 혁신 노력을 인정받음</p>
</div>
<p class="rec-kind">수상 · 인증</p>
</li>
</ol>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
7 · 채용
══════════════════════════════════════════════════════════ -->
<section class="band band-light section-career" id="career" aria-labelledby="careerHeading">
<div class="wrap split">
<div class="split-lead">
<h2 id="careerHeading">지금은 정규 공고가 닫혀 있습니다</h2>
<section class="section contact" id="contact" aria-labelledby="contactHeading">
<div class="wrap contact-grid">
<div>
<p class="eyebrow">Start a project</p>
<h2 id="contactHeading">다음 현장을<br />함께 설계하겠습니다</h2>
</div>
<div class="split-body">
<p class="lead">
다섯 개 직무가 모두 마감 상태입니다. 닫힌 것을 열려 있는 것처럼 적어 두면
지원하는 쪽의 시간을 뺏게 되므로, 상태를 그대로 적습니다.
</p>
<ul class="jobs">
<li>
<span class="job-name">시니어 소프트웨어 엔지니어</span>
<span class="job-hint">산업용 소프트웨어 · C++ / C# / Python · PLC · HMI · SCADA</span>
<span class="job-state mono">마감</span>
</li>
<li>
<span class="job-name">DevOps 엔지니어</span>
<span class="job-hint">컨테이너 · 오케스트레이션 · CI/CD · IaC</span>
<span class="job-state mono">마감</span>
</li>
<li>
<span class="job-name">프로덕트 매니저</span>
<span class="job-hint">IT 서비스 기획·운영 3년 이상 · 데이터 기반 의사결정</span>
<span class="job-state mono">마감</span>
</li>
<li>
<span class="job-name">서비스 기획자</span>
<span class="job-hint">UI/UX 기획 · 와이어프레임 · 애자일 / 스크럼</span>
<span class="job-state mono">마감</span>
</li>
<li>
<span class="job-name">UI/UX 디자이너</span>
<span class="job-hint">Figma · 웹 / 모바일 포트폴리오 · 사용자 중심 설계</span>
<span class="job-state mono">마감</span>
</li>
</ul>
<p class="jobs-open">
공고와 무관하게 이야기를 시작할 수는 있습니다.
<a href="mailto:hello@twentyoz.kr?subject=%EC%B1%84%EC%9A%A9%20%EB%AC%B8%EC%9D%98">채용 문의 보내기</a>
</p>
</div>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
8 · 연락
══════════════════════════════════════════════════════════ -->
<section class="band band-light section-contact" id="contact" aria-labelledby="contactHeading">
<div class="wrap split">
<div class="split-lead">
<h2 id="contactHeading">연락</h2>
</div>
<div class="split-body">
<dl class="contact-rows">
<div>
<dt>주소</dt>
<dd>경기도 화성시 동탄첨단산업1로 27, A909호<br />(영천동, 금강펜테리움 IX 타워)</dd>
</div>
<div>
<dt>전화</dt>
<dd><a class="mono" href="tel:+8207043531190">070-4353-1190</a></dd>
</div>
<div>
<dt>메일</dt>
<dd><a class="mono" href="mailto:hello@twentyoz.kr">hello@twentyoz.kr</a></dd>
</div>
<div>
<dt>설립</dt>
<dd class="mono">2020년 1월</dd>
</div>
<div class="contact-main">
<p>가상현실, 산업 데이터, 운영 자동화가 실제 현장에서 돌아가야 한다면 지금 이야기할 수 있습니다.</p>
<a class="contact-mail" href="mailto:hello@twentyoz.kr?subject=%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%20%EB%AC%B8%EC%9D%98">hello@twentyoz.kr</a>
<dl class="contact-list">
<div><dt>Address</dt><dd>경기도 화성시 동탄첨단산업1로 27, A909호</dd></div>
<div><dt>Telephone</dt><dd><a href="tel:+8207043531190">070-4353-1190</a></dd></div>
<div><dt>Founded</dt><dd>2020년 1월</dd></div>
</dl>
<a class="btn" href="mailto:hello@twentyoz.kr?subject=%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%20%EB%AC%B8%EC%9D%98">
프로젝트 문의
</a>
</div>
</div>
</section>
</main>
<footer class="band band-dark site-foot">
<div class="wrap foot-inner">
<p class="foot-name">트웬티온스 · TWENTYOZ</p>
<p class="foot-line">
가상현실 · 산업용 IoT · 이커머스 솔루션 · 경기도 화성시 동탄
<footer class="site-foot">
<div class="wrap foot-grid">
<p>TWENTYOZ · 트웬티온스</p>
<p>Virtual reality · Industrial IoT · Commerce solutions</p>
<p>© 2020–2026 TWENTYOZ. All rights reserved.</p>
<p class="model-credit">
3D field instrument adapted from
<a href="https://sketchfab.com/3d-models/scifi-drone-11-dd21953e81a24bd385d16eaf0c6a8ae7" rel="noopener noreferrer">Scifi Drone 1.1</a>
by <a href="https://sketchfab.com/Jj.Mmhh" rel="noopener noreferrer">Javier Martín Hidalgo</a>,
licensed under <a href="https://creativecommons.org/licenses/by/4.0/" rel="license noopener noreferrer">CC BY 4.0</a>.
<a href="./assets/twentyoz-field-core-LICENSE.txt">Attribution details</a>
</p>
<p class="foot-fine">© 2020–2026 TWENTYOZ</p>
</div>
</footer>
</body>

View file

@ -0,0 +1,161 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>제품 시스템 — TWENTYOZ</title>
<meta name="description" content="트웬티온스의 VIVEN, EduBill, XD Hub, XD Works가 제공하는 핵심 기능, 기술 구성, 운영 사양과 도입 흐름을 제품별로 확인합니다." />
<meta property="og:title" content="제품 시스템 — TWENTYOZ" />
<meta property="og:description" content="교육·AI 도입·산업 데이터·시설 운영을 연결하는 트웬티온스의 네 제품 시스템을 확인합니다." />
<meta property="og:type" content="website" />
<meta property="og:image" content="./assets/core-light.webp" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="theme-color" content="#0d0f0f" media="(prefers-color-scheme: dark)" />
<meta name="theme-color" content="#e9e7e2" media="(prefers-color-scheme: light)" />
<link rel="preload" href="./assets/pretendard-twentyoz.woff2" as="font" type="font/woff2" crossorigin />
<link rel="stylesheet" href="./styles/tokens.css" />
<link rel="stylesheet" href="./styles/main.css" />
<link rel="stylesheet" href="./styles/catalog.css" />
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23151616'/%3E%3Ccircle cx='16' cy='16' r='7' fill='none' stroke='%23F6F4EF' stroke-width='2'/%3E%3Cpath d='M16 5v22M5 16h22' stroke='%23B9362B'/%3E%3C/svg%3E" />
</head>
<body class="catalog-page">
<a class="skip-link" href="#main">본문으로 건너뛰기</a>
<header class="site-head">
<div class="wrap head-inner">
<a class="wordmark" href="./index.html" aria-label="트웬티온스 메인으로">
<span class="wordmark-mark" aria-hidden="true"><i></i><i></i></span><span>TWENTYOZ</span>
</a>
<nav class="nav" aria-label="제품 상세 탐색">
<a href="#viven">VIVEN</a><a href="#edubill">EduBill</a><a href="#xd-hub">XD Hub</a><a href="#xd-works">XD Works</a>
</nav>
<p class="head-meta">PRODUCT SYSTEMS · 04</p>
</div>
</header>
<main class="catalog-main" id="main">
<section class="catalog-hero" aria-labelledby="catalogHeading">
<div class="wrap catalog-hero-grid">
<div>
<p class="eyebrow">Self IP · Product catalog</p>
<h1 id="catalogHeading">네 개의 시스템</h1>
</div>
<p class="catalog-lede">
교육과 훈련, 공공 AI 도입, 산업 데이터 수집, 시설 운영 자동화까지 각 제품의 기능과 기술 사양을 공개합니다.
</p>
<nav class="catalog-index" aria-label="제품 바로가기">
<a href="#viven"><span>V–01 · 2021</span><strong>VIVEN</strong></a>
<a href="#edubill"><span>V–02 · 2024</span><strong>EduBill</strong></a>
<a href="#xd-hub"><span>V–03 · 2022</span><strong>XD Hub</strong></a>
<a href="#xd-works"><span>V–04 · 2023</span><strong>XD Works</strong></a>
</nav>
</div>
</section>
<article class="specimen" id="viven" aria-labelledby="vivenHeading">
<div class="wrap">
<header class="specimen-heading">
<p class="specimen-code">V–01 / IMMERSIVE</p>
<h2 id="vivenHeading">VIVEN</h2>
<p class="specimen-summary">최대 100명이 VR·PC·모바일에서 함께 참여하는 교육 특화 메타버스 플랫폼입니다.</p>
</header>
<dl class="vital-grid">
<div><dt>Type</dt><dd>Self IP / Platform</dd></div><div><dt>Category</dt><dd>VR 교육·훈련</dd></div>
<div><dt>Build cycle</dt><dd>2021 – 현재</dd></div><div><dt>Maturity</dt><dd>TRL 9</dd></div>
</dl>
<div class="detail-grid">
<section aria-labelledby="vivenCapabilities">
<p class="detail-label">Capability matrix</p><h3 class="sr-only" id="vivenCapabilities">VIVEN 주요 기능</h3>
<ol class="capability-list">
<li><span>C–01</span><strong>실시간 협업</strong><p>단일 가상 공간에서 최대 100명의 교육과 훈련을 지원합니다.</p></li>
<li><span>C–02</span><strong>멀티 디바이스</strong><p>VR 헤드셋, PC, iOS와 Android 환경을 하나의 세션으로 연결합니다.</p></li>
<li><span>C–03</span><strong>AI 모션캡처</strong><p>PC VMC와 Mobile VMC로 웹캠 기반 아바타 동작을 실시간 반영합니다.</p></li>
<li><span>C–04</span><strong>성과 분석</strong><p>커스텀 시나리오, 교육 성과 리포트, 클라우드 콘텐츠 관리를 제공합니다.</p></li>
</ol>
</section>
<aside class="technical-panel" aria-label="VIVEN 기술과 사양">
<p class="detail-label">Technology lineage</p>
<ul class="stack-list"><li>Unity3D</li><li>WebXR</li><li>MediaPipe</li><li>Socket.IO</li><li>Spring Boot</li></ul>
<dl class="spec-list">
<div><dt>Devices</dt><dd>Oculus Quest, HTC Vive, PC, iOS·Android</dd></div>
<div><dt>Minimum</dt><dd>Windows 10 · Intel i5 · 8GB RAM · GTX 1060</dd></div>
<div><dt>Concurrency</dt><dd>단일 공간 최대 100명</dd></div>
<div><dt>Languages</dt><dd>한국어 · 영어</dd></div>
</dl>
</aside>
</div>
<section class="operation-flow" aria-label="VIVEN 운영 흐름">
<p class="detail-label">Operating sequence</p>
<ol><li data-step="01"><strong>시나리오 구성</strong><span>교육 목적에 맞는 가상 공간과 과정을 설계합니다.</span></li><li data-step="02"><strong>멀티 디바이스 접속</strong><span>VR·PC·모바일 사용자를 같은 세션으로 연결합니다.</span></li><li data-step="03"><strong>실시간 참여</strong><span>협업, 공간음향, 모션캡처를 동기화합니다.</span></li><li data-step="04"><strong>성과 확인</strong><span>활동 결과를 분석하고 리포트로 제공합니다.</span></li></ol>
</section>
<p class="specimen-action"><a class="button" href="mailto:hello@twentyoz.kr?subject=VIVEN%20%EB%8F%84%EC%9E%85%20%EB%AC%B8%EC%9D%98">VIVEN 도입 문의</a></p>
</div>
</article>
<article class="specimen" id="edubill" aria-labelledby="edubillHeading">
<div class="wrap">
<header class="specimen-heading">
<p class="specimen-code">V–02 / PUBLIC AI</p><h2 id="edubillHeading">EduBill</h2>
<p class="specimen-summary">공공기관과 교육기관이 해외 AI 서비스를 원화 결제와 세금계산서로 도입하도록 지원합니다.</p>
</header>
<dl class="vital-grid"><div><dt>Type</dt><dd>Self IP / SaaS</dd></div><div><dt>Category</dt><dd>EdTech 구독 관리</dd></div><div><dt>Build cycle</dt><dd>2024 – 현재</dd></div><div><dt>Maturity</dt><dd>TRL 8</dd></div></dl>
<div class="detail-grid">
<section aria-labelledby="edubillCapabilities"><p class="detail-label">Capability matrix</p><h3 class="sr-only" id="edubillCapabilities">EduBill 주요 기능</h3>
<ol class="capability-list">
<li><span>C–01</span><strong>원화 결제</strong><p>해외 AI 서비스 비용을 원화로 결제하고 세금계산서를 발행합니다.</p></li>
<li><span>C–02</span><strong>통합 라이선스</strong><p>ChatGPT, Claude, Gemini 등 여러 서비스의 라이선스를 함께 관리합니다.</p></li>
<li><span>C–03</span><strong>계약 자동화</strong><p>계약 만료와 자동 갱신 일정을 사전에 알립니다.</p></li>
<li><span>C–04</span><strong>일괄 배정</strong><p>기관, 부서, 사용자 단위로 라이선스를 배정하고 회수합니다.</p></li>
</ol>
</section>
<aside class="technical-panel" aria-label="EduBill 기술과 사양"><p class="detail-label">Technology lineage</p>
<ul class="stack-list"><li>Next.js</li><li>TypeScript</li><li>Supabase</li><li>PostgreSQL</li><li>Cloudflare Workers</li></ul>
<dl class="spec-list"><div><dt>Services</dt><dd>ChatGPT · Claude · Gemini 외</dd></div><div><dt>Audience</dt><dd>공공기관 · 대학 · 초중고 · 기업</dd></div><div><dt>Payment</dt><dd>원화 · 세금계산서</dd></div><div><dt>Management</dt><dd>기관 · 부서 · 사용자</dd></div></dl>
</aside>
</div>
<section class="operation-flow" aria-label="EduBill 운영 흐름"><p class="detail-label">Operating sequence</p><ol><li data-step="01"><strong>수요 취합</strong><span>기관별 서비스와 사용자 수를 확인합니다.</span></li><li data-step="02"><strong>라이선스 배정</strong><span>부서와 사용자 단위로 접근 권한을 구성합니다.</span></li><li data-step="03"><strong>결제·증빙</strong><span>원화 결제와 세금계산서 발행을 처리합니다.</span></li><li data-step="04"><strong>갱신 관리</strong><span>만료 일정과 사용 현황을 함께 관리합니다.</span></li></ol></section>
<p class="specimen-action"><a class="button" href="mailto:hello@twentyoz.kr?subject=EduBill%20%EB%8F%84%EC%9E%85%20%EB%AC%B8%EC%9D%98">EduBill 도입 문의</a></p>
</div>
</article>
<article class="specimen" id="xd-hub" aria-labelledby="xdHubHeading">
<div class="wrap">
<header class="specimen-heading"><p class="specimen-code">V–03 / INDUSTRIAL DATA</p><h2 id="xdHubHeading">XD Hub</h2><p class="specimen-summary">최대 100만 포인트를 실시간 처리하고 여섯 산업 프로토콜을 통합하는 IoT 데이터 엔진입니다.</p></header>
<dl class="vital-grid"><div><dt>Type</dt><dd>Self IP / Engine</dd></div><div><dt>Category</dt><dd>산업용 IoT</dd></div><div><dt>Build cycle</dt><dd>2022 – 현재</dd></div><div><dt>Maturity</dt><dd>TRL 8</dd></div></dl>
<div class="detail-grid">
<section aria-labelledby="xdHubCapabilities"><p class="detail-label">Capability matrix</p><h3 class="sr-only" id="xdHubCapabilities">XD Hub 주요 기능</h3><ol class="capability-list">
<li><span>C–01</span><strong>멀티 프로토콜</strong><p>Modbus, OPC UA, SNMP, BACnet, MQTT, REST를 한 엔진으로 수집합니다.</p></li>
<li><span>C–02</span><strong>히스토리안</strong><p>실시간 데이터를 시계열 저장소에 자동 보관하고 조회합니다.</p></li>
<li><span>C–03</span><strong>Web HMI</strong><p>SCADA 화면을 웹에서 구성하고 현장 상태를 시각화합니다.</p></li>
<li><span>C–04</span><strong>하이브리드 배포</strong><p>엣지와 클라우드 환경을 현장 조건에 맞게 함께 구성합니다.</p></li>
</ol></section>
<aside class="technical-panel" aria-label="XD Hub 기술과 사양"><p class="detail-label">Technology lineage</p><ul class="stack-list"><li>Java Spring Boot</li><li>Netty</li><li>TimescaleDB</li><li>Redis</li><li>Caffeine</li></ul><dl class="spec-list"><div><dt>Points</dt><dd>최대 1,000,000개</dd></div><div><dt>Protocols</dt><dd>Modbus · OPC UA · SNMP · BACnet · MQTT · REST</dd></div><div><dt>Storage</dt><dd>TimescaleDB · Redis</dd></div><div><dt>Domains</dt><dd>데이터센터 · 제조 · 발전소 · 빌딩</dd></div></dl></aside>
</div>
<section class="operation-flow" aria-label="XD Hub 운영 흐름"><p class="detail-label">Operating sequence</p><ol><li data-step="01"><strong>프로토콜 연결</strong><span>서로 다른 설비 통신 규격을 게이트웨이에 연결합니다.</span></li><li data-step="02"><strong>수집·전처리</strong><span>실시간 값을 정규화하고 품질을 확인합니다.</span></li><li data-step="03"><strong>시계열 저장</strong><span>히스토리안과 캐시에 운영 데이터를 보관합니다.</span></li><li data-step="04"><strong>전송·시각화</strong><span>운영 애플리케이션과 Web HMI에 데이터를 제공합니다.</span></li></ol></section>
<p class="specimen-action"><a class="button" href="mailto:hello@twentyoz.kr?subject=XD%20Hub%20%EB%8F%84%EC%9E%85%20%EB%AC%B8%EC%9D%98">XD Hub 도입 문의</a></p>
</div>
</article>
<article class="specimen" id="xd-works" aria-labelledby="xdWorksHeading">
<div class="wrap">
<header class="specimen-heading"><p class="specimen-code">V–04 / OPERATIONS</p><h2 id="xdWorksHeading">XD Works</h2><p class="specimen-summary">XD Hub의 IoT 데이터를 기반으로 데이터센터와 시설의 운영, 점검, 과금을 자동화합니다.</p></header>
<dl class="vital-grid"><div><dt>Type</dt><dd>Self IP / Application</dd></div><div><dt>Category</dt><dd>DCIM · BEMS · FM</dd></div><div><dt>Build cycle</dt><dd>2023 – 현재</dd></div><div><dt>Maturity</dt><dd>TRL 8</dd></div></dl>
<div class="detail-grid">
<section aria-labelledby="xdWorksCapabilities"><p class="detail-label">Capability matrix</p><h3 class="sr-only" id="xdWorksCapabilities">XD Works 주요 기능</h3><ol class="capability-list">
<li><span>C–01</span><strong>상면·계약·청구</strong><p>데이터센터 상면과 고객 계약, 사용량 기반 청구를 통합 관리합니다.</p></li>
<li><span>C–02</span><strong>에너지 분석</strong><p>BEMS 데이터를 분석하고 PUE를 자동 산정합니다.</p></li>
<li><span>C–03</span><strong>시설물 점검</strong><p>정기 점검과 유지보수 작업의 책임과 이력을 관리합니다.</p></li>
<li><span>C–04</span><strong>다채널 알림</strong><p>SMS, 알림톡, 이메일로 운영 이상과 업무 일정을 전달합니다.</p></li>
</ol></section>
<aside class="technical-panel" aria-label="XD Works 기술과 사양"><p class="detail-label">Technology lineage</p><ul class="stack-list"><li>Spring Boot</li><li>NestJS</li><li>TypeScript</li><li>PostgreSQL</li><li>Vue 3</li></ul><dl class="spec-list"><div><dt>Domains</dt><dd>DCIM · BEMS · FM</dd></div><div><dt>Billing</dt><dd>다통화 · 다과금 정책</dd></div><div><dt>Alerts</dt><dd>SMS · 알림톡 · 이메일</dd></div><div><dt>Audience</dt><dd>데이터센터 · 빌딩 · 공장 · 발전소</dd></div></dl></aside>
</div>
<section class="operation-flow" aria-label="XD Works 운영 흐름"><p class="detail-label">Operating sequence</p><ol><li data-step="01"><strong>자산·계약 구성</strong><span>공간, 설비, 고객, 계약 정보를 연결합니다.</span></li><li data-step="02"><strong>실시간 운영</strong><span>XD Hub의 계측 데이터를 운영 화면에 반영합니다.</span></li><li data-step="03"><strong>점검·분석</strong><span>유지보수와 에너지 성과를 같은 흐름에서 관리합니다.</span></li><li data-step="04"><strong>과금·알림</strong><span>사용량을 계산하고 청구서와 운영 알림을 발행합니다.</span></li></ol></section>
<p class="specimen-action"><a class="button" href="mailto:hello@twentyoz.kr?subject=XD%20Works%20%EB%8F%84%EC%9E%85%20%EB%AC%B8%EC%9D%98">XD Works 도입 문의</a></p>
</div>
</article>
<p class="wrap catalog-source">제품 정보는 2026년 8월 24일 기준 <a href="https://twentyoz.kr/" rel="noopener noreferrer">트웬티온스 공식 공개 자료</a>를 바탕으로 구성했습니다.</p>
</main>
<footer class="site-foot"><div class="wrap foot-grid"><p>TWENTYOZ · 트웬티온스</p><p>Product systems · Technical specifications</p><p>© 2020–2026 TWENTYOZ. All rights reserved.</p></div></footer>
</body>
</html>

View file

@ -0,0 +1,100 @@
(() => {
const hero = document.querySelector(".hero");
const canvas = document.getElementById("coreCanvas");
const toggle = document.getElementById("motionToggle");
const status = document.getElementById("coreStatus");
const inputs = [...document.querySelectorAll('input[name="field"]')];
const ownScript = document.currentScript;
if (!hero || !canvas || !toggle || !status || !ownScript || inputs.length !== 4) return;
const stateLabels = [
"선택한 현장: 강의실과 훈련장",
"선택한 현장: 데이터센터와 발전소",
"선택한 현장: 공공기관과 대학 행정",
"선택한 현장: 공장과 설비 현장",
];
let controller = null;
function selectedIndex() {
const checked = inputs.findIndex((input) => input.checked);
return checked < 0 ? 0 : checked;
}
function syncState() {
const index = selectedIndex();
hero.dataset.coreState = inputs[index].value;
status.textContent = stateLabels[index];
controller?.setState(index);
}
inputs.forEach((input) => input.addEventListener("change", syncState));
syncState();
function gate() {
const explicitWebgl = new URLSearchParams(location.search).has("webgl");
if ((navigator.webdriver || location.protocol === "file:") && !explicitWebgl) return "automation";
if (matchMedia("(prefers-reduced-motion: reduce)").matches) return "reduced-motion";
if (navigator.connection?.saveData) return "save-data";
if ((navigator.deviceMemory ?? 8) < 4) return "low-memory";
if ((navigator.hardwareConcurrency ?? 8) < 4) return "low-cpu";
try {
const probe = document.createElement("canvas");
const gl = probe.getContext("webgl2", { failIfMajorPerformanceCaveat: true });
if (!gl) return "no-webgl2";
gl.getExtension("WEBGL_lose_context")?.loseContext();
return "ready";
} catch {
return "no-webgl2";
}
}
const result = gate();
if (result !== "ready") {
hero.dataset.webgl = "fallback";
hero.dataset.webglReason = result;
return;
}
function loadCore() {
if (hero.dataset.webgl === "loading" || hero.dataset.webgl === "ready") return;
hero.dataset.webgl = "loading";
const script = document.createElement("script");
script.src = new URL("../assets/core.iife.js", ownScript.src).href;
script.async = true;
script.onload = () => {
try {
controller = globalThis.TwentyozCore.mount({
canvas,
hero,
toggle,
initialState: selectedIndex(),
});
addEventListener("pagehide", () => controller?.dispose(), { once: true });
} catch {
hero.dataset.webgl = "fallback";
hero.dataset.webglReason = "mount-failed";
toggle.hidden = true;
}
};
script.onerror = () => {
hero.dataset.webgl = "fallback";
hero.dataset.webglReason = "asset-failed";
toggle.hidden = true;
};
document.head.append(script);
}
const observer = new IntersectionObserver(
([entry]) => {
if (!entry.isIntersecting) return;
observer.disconnect();
const schedule = window.requestIdleCallback || ((callback) => setTimeout(callback, 1));
schedule(loadCore, { timeout: 1200 });
},
{ rootMargin: "200px" },
);
observer.observe(hero);
matchMedia("(prefers-reduced-motion: reduce)").addEventListener("change", () => location.reload());
})();

View file

@ -0,0 +1,352 @@
.catalog-page .site-head {
position: fixed;
background: color-mix(in srgb, var(--page) 88%, transparent);
backdrop-filter: blur(18px);
}
.catalog-main {
overflow: clip;
}
.catalog-hero {
min-height: 76svh;
display: grid;
align-items: end;
padding-block: calc(var(--header-h) + var(--space-8)) var(--space-7);
border-block-end: var(--hairline) solid var(--line-strong);
}
.catalog-hero-grid {
display: grid;
grid-template-columns: minmax(0, 1.25fr) minmax(16rem, 0.75fr);
gap: var(--space-7);
align-items: end;
}
.catalog-hero h1 {
max-width: 11ch;
margin-block-start: var(--space-5);
font-size: clamp(3.5rem, 2rem + 7vw, 7.5rem);
font-weight: 500;
line-height: 0.94;
letter-spacing: -0.045em;
white-space: nowrap;
}
.catalog-lede {
max-width: var(--measure);
color: var(--ink-muted);
font-size: var(--text-lead);
}
.catalog-index {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
margin-block-start: var(--space-7);
border-block: var(--hairline) solid var(--line-strong);
}
.catalog-index a {
min-height: 5.5rem;
display: grid;
align-content: center;
gap: var(--space-1);
padding: var(--space-3) var(--space-4);
border-inline-start: var(--hairline) solid var(--line);
text-decoration: none;
}
.catalog-index a:first-child {
border-inline-start: 0;
}
.catalog-index span {
color: var(--signal-strong);
font-size: var(--text-xs);
letter-spacing: var(--tracking-label);
}
.catalog-index strong {
font-size: var(--text-body);
font-weight: 620;
}
.specimen {
scroll-margin-top: calc(var(--header-h) + var(--space-3));
padding-block: var(--space-9);
border-block-end: var(--hairline) solid var(--line-strong);
}
.specimen:nth-of-type(even) {
background: var(--surface-quiet);
}
.specimen-heading {
display: grid;
grid-template-columns: minmax(5rem, 0.3fr) minmax(0, 1.35fr) minmax(17rem, 0.65fr);
gap: var(--space-6);
align-items: end;
}
.specimen-code {
align-self: start;
color: var(--signal-strong);
font-size: var(--text-xs);
font-weight: 650;
letter-spacing: var(--tracking-label);
}
.specimen h2 {
font-size: clamp(3.5rem, 2.5rem + 4vw, 7rem);
font-weight: 500;
line-height: 0.94;
letter-spacing: -0.04em;
}
.specimen-summary {
color: var(--ink-muted);
font-size: var(--text-lead);
}
.vital-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
margin-block-start: var(--space-7);
border-block: var(--hairline) solid var(--line-strong);
}
.vital-grid div {
min-width: 0;
padding: var(--space-4);
border-inline-start: var(--hairline) solid var(--line);
}
.vital-grid div:first-child {
border-inline-start: 0;
}
.vital-grid dt,
.spec-list dt {
color: var(--ink-muted);
font-size: var(--text-xs);
letter-spacing: var(--tracking-label);
}
.vital-grid dd {
margin-block-start: var(--space-3);
font-size: var(--text-sm);
font-weight: 620;
}
.detail-grid {
display: grid;
grid-template-columns: minmax(0, 1.25fr) minmax(18rem, 0.75fr);
gap: var(--space-7);
margin-block-start: var(--space-8);
align-items: start;
}
.detail-label {
margin-block-end: var(--space-4);
color: var(--ink-muted);
font-size: var(--text-xs);
letter-spacing: var(--tracking-label);
}
.capability-list {
border-block-start: var(--hairline) solid var(--line-strong);
}
.capability-list li {
display: grid;
grid-template-columns: 4.5rem minmax(0, 0.8fr) minmax(0, 1.2fr);
gap: var(--space-4);
padding-block: var(--space-4);
border-block-end: var(--hairline) solid var(--line);
}
.capability-list span {
color: var(--signal-strong);
font-size: var(--text-xs);
}
.capability-list strong {
font-size: var(--text-body);
font-weight: 620;
}
.capability-list p {
color: var(--ink-muted);
font-size: var(--text-sm);
}
.technical-panel {
position: sticky;
inset-block-start: calc(var(--header-h) + var(--space-5));
}
.stack-list {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-block-end: var(--space-6);
}
.stack-list li {
padding: var(--space-1) var(--space-2);
border: var(--hairline) solid var(--line-strong);
font-size: var(--text-xs);
}
.spec-list {
border-block-start: var(--hairline) solid var(--line-strong);
}
.spec-list div {
display: grid;
grid-template-columns: 7rem minmax(0, 1fr);
gap: var(--space-3);
padding-block: var(--space-3);
border-block-end: var(--hairline) solid var(--line);
}
.spec-list dd {
font-size: var(--text-sm);
}
.operation-flow {
margin-block-start: var(--space-8);
padding-block-start: var(--space-5);
border-block-start: var(--hairline) solid var(--line-strong);
}
.operation-flow ol {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
margin-block-start: var(--space-4);
}
.operation-flow li {
position: relative;
min-height: 10rem;
padding: var(--space-4);
border-inline-start: var(--hairline) solid var(--line);
}
.operation-flow li:first-child {
border-inline-start: 0;
}
.operation-flow li::before {
content: attr(data-step);
display: block;
margin-block-end: var(--space-4);
color: var(--signal-strong);
font-size: var(--text-xs);
}
.operation-flow strong {
display: block;
margin-block-end: var(--space-2);
font-size: var(--text-sm);
}
.operation-flow span {
color: var(--ink-muted);
font-size: var(--text-xs);
line-height: 1.65;
}
.specimen-action {
display: flex;
justify-content: flex-end;
margin-block-start: var(--space-6);
}
.catalog-source {
padding-block: var(--space-6);
color: var(--ink-soft);
font-size: var(--text-xs);
}
.catalog-source a {
display: inline-block;
min-height: 1.5rem;
line-height: 1.5rem;
text-underline-offset: 0.2em;
}
@media (max-width: 62rem) {
.catalog-hero-grid,
.specimen-heading,
.detail-grid {
grid-template-columns: 1fr;
}
.catalog-lede {
max-width: 34rem;
}
.technical-panel {
position: static;
}
.principle-list,
.operation-flow ol {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 43rem) {
.catalog-page .site-head {
position: relative;
}
.catalog-hero {
min-height: 0;
padding-block: var(--space-7);
}
.catalog-hero h1 {
font-size: clamp(1.8rem, 9.5vw, 3rem);
}
.catalog-index,
.vital-grid,
.operation-flow ol {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.catalog-index a:nth-child(3),
.vital-grid div:nth-child(3),
.operation-flow li:nth-child(3) {
border-inline-start: 0;
}
.catalog-index a:nth-child(n + 3),
.vital-grid div:nth-child(n + 3),
.operation-flow li:nth-child(n + 3) {
border-block-start: var(--hairline) solid var(--line);
}
.specimen {
padding-block: var(--space-8);
}
.specimen h2 {
font-size: clamp(3rem, 17vw, 5rem);
}
.capability-list li {
grid-template-columns: 3.5rem minmax(0, 1fr);
}
.capability-list p {
grid-column: 2;
}
.operation-flow li {
min-height: 9rem;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,117 +1,151 @@
/* ==========================================================================
트웬티온스 (TWENTYOZ) — 회사 홈페이지 리디자인 · 디자인 토큰 SSOT
/*
TWENTYOZ · precision-spatial token source of truth
One grotesk, one semantic signal, square DOM geometry. Curves belong to the core.
*/
컨셉 : 네 개의 현장 — 회사 소개가 아니라, 같은 기술이 서로 다른 현장에서
무엇을 하고 있는지의 목록이 이 사이트의 본체다
프리셋: field-record (신규 정의. swiss-minimal 을 뼈대로 삼되 본문을 키웠다)
강조색: 신호 적색 1색. 라이트/다크는 규칙으로 정의된 한 쌍이므로 1종으로 센다
── 0단계 감사 · 현행 twentyoz.kr 실측 (2026-08-24, 1249px computed style)
유지할 자산
· radius 0px 742회 — 형태 어휘가 이미 통일돼 있다. 그대로 가져간다
· 무채색 기조와 모노스페이스(JetBrains Mono 356회) — 정밀함의 어휘는 맞다
· 실제 프로젝트 49건 · 파트너 19곳 · 제품 4종의 기술 스택 표기
고쳐야 할 것
· 대비 실패 **172개 요소** — rgb(102,102,102) 가 배경 rgb(2,2,2) 위에서 3.61:1,
그것도 9~11px 로 284곳에 쓰였다. WCAG AA 미달이고 읽기 자체가 어렵다
· font-family 가 Inter 뿐이라 **한글 폰트가 지정돼 있지 않다**.
한국 회사의 한국어 사이트에서 한글이 시스템 기본값으로 떨어진다
· h1 174.86px 에 letter-spacing −10.49px = **−0.06em**. 한글 상한(−0.02em)의 세 배다
· 배경 #020202 — 순흑에 가깝다
· 'Digital Genetics' 은유가 전면에 있다(CULTIVATING · DROPS · Sativa/Indica ·
Germination · Wholesale Desk · ACQUIRE GENETICS · Open Specimens).
SK하이닉스·LG디스플레이·한화솔루션·GS칼텍스에 산업용 IoT 를 파는 회사의
어휘로는 사업을 가린다. 은유를 걷어내고 한 일을 앞에 둔다
── 레퍼런스 실측 (2026-08-24, 1440px)
R1 구조 · samsara.com (커넥티드 오퍼레이션 / 산업 IoT — 같은 업종)
배경 #FFFFFF · FK Grotesk + FK Grotesk Mono 2패밀리
h1 72px/700 · 본문 16px(404회) · 최대 80px ÷ 본문 = 5.0배
radius 0px 2399회 지배 · 강조색 #FEAE0F 이 버튼 1곳
컨테이너 1425 전폭 ↔ 1345 ↔ 427 칼럼 · 섹션 13
→ 가져온 원리: 섹션 제목이 '무엇을 증명하는가'를 직접 말한다
(Proven where it counts / A track record / Proudly rated #1).
B2B 는 주장이 아니라 기록으로 설득한다
→ 안 가져온 것: 전체 대문자 h1 과 대문자 eyebrow 5종(슬롭 지문 2위),
순백·순흑, 섹션 13개, 앰버 pill 버튼
R2 톤 · lars-mueller-publishers.com (출판사 — 다른 업종)
텍스트 #414141 (순흑 아님) · NB Akademie Std 한 패밀리의 두 웨이트
h1 34px/500 · **본문 20px(190회)** · line-height 30px = 1.5
최대 ÷ 본문 = 1.7배 · radius 0px 1709회 지배 · 컨테이너 1240px
→ 가져온 원리: **본문을 크게 쓰고 제목을 작게 둔다.** 위계를 크기 하나로
만들지 않고 여백과 순서로도 만든다. 한 패밀리의 두 웨이트로 절제한다
→ 안 가져온 것: 강조색 #542BFF(보라 계열 — 슬롭 지문),
최대÷본문 1.7배(평평한 스케일은 안티패턴)
두 레퍼런스의 합성: 본문은 R2 쪽으로 키우고(17px), 최대÷본문은 R1 쪽으로
벌린다(4.0배). 한쪽만 따르면 평평하거나 본문이 작아진다.
========================================================================== */
@font-face {
font-family: "Pretendard Variable";
font-style: normal;
font-weight: 45 920;
font-display: swap;
src: url("../assets/pretendard-twentyoz.woff2") format("woff2-variations");
}
:root {
/* ── 타이포그래피 — 5단계 + 스케일 밖 디스플레이 1개 ── */
--step--1: 0.8125rem; /* 13px — 표 머리·메타 */
--step-0: 1.0625rem; /* 17px — 본문. R2 의 큰 본문을 한글에 맞춰 옮겼다 */
--step-1: 1.25rem; /* 20px — 리드 */
--step-2: clamp(1.375rem, 1.15rem + 1.1vw, 1.9375rem); /* 22 → 31px */
--step-3: clamp(1.75rem, 1.25rem + 2.5vw, 2.875rem); /* 28 → 46px */
--display: clamp(2.25rem, 1.3rem + 4.6vw, 4.25rem); /* 36 → 68px */
/* 최대 ÷ 본문 = 68 ÷ 17 = 4.0배 */
color-scheme: light dark;
--leading-tight: 1.2;
--leading-normal: 1.7;
--leading-loose: 1.85;
--measure: 33em;
/* Type */
--font-sans: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
--text-xs: 0.75rem;
--text-sm: 0.8125rem;
--text-body: clamp(1.0625rem, 1.02rem + 0.16vw, 1.125rem);
--text-lead: clamp(1.125rem, 1.02rem + 0.38vw, 1.3125rem);
--text-h3: clamp(1.5rem, 1.25rem + 0.75vw, 1.875rem);
--text-h2: clamp(2rem, 1.75rem + 0.8vw, 2.5rem);
--text-display: clamp(2rem, 1.36rem + 2.7vw, 4.5rem);
--leading-tight: 1.04;
--leading-heading: 1.15;
--leading-body: 1.7;
--tracking-display: -0.018em;
--tracking-heading: -0.012em;
--tracking-label: 0.08em;
--measure: 36rem;
--measure-narrow: 28rem;
--font-body: Pretendard, "Pretendard Variable", -apple-system, system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
/* Light theme */
--page: #e9e7e2;
--surface: #f6f4ef;
--surface-muted: #d5d1ca;
--surface-quiet: #dfdcd6;
--ink: #151616;
--ink-muted: #5a5954;
--ink-soft: #6a6862;
--line: #b8b5ae;
--line-strong: #74736e;
--signal: #b9362b;
--signal-strong: #8f251d;
--signal-ink: #fff8f0;
--selection: #d9aaa1;
--focus: #8f251d;
/* ── 색 · 종이(라이트) ── */
--surface: #fafaf8;
--surface-2: #f0f0ec;
--surface-3: #e5e5e0;
--line: #dcdcd6;
--line-strong: #b9b9b2;
--ink: #111214; /* 17.9:1 */
--ink-muted: #54585c; /* 6.97:1 */
--ink-faint: #686d72; /* 5.03:1 */
--accent: #c4341f; /* 5.21:1 · 흰 글자 얹으면 5.44:1 */
--accent-hover: #9e2817;
--accent-ink: #ffffff;
--accent-wash: #f6e7e3;
/* Inverse surface */
--inverse: #111313;
--inverse-raised: #1a1d1c;
--inverse-ink: #f2f1ec;
--inverse-muted: #b4b5b0;
--inverse-line: #414442;
--inverse-signal: #ed6a58;
--inverse-signal-ink: #180b08;
/* ── 색 · 잉크(다크 반전 밴드) — 위 값들의 규칙적 반전 ── */
--dark-surface: #111214;
--dark-surface-2: #191b1e;
--dark-surface-3: #212428;
--dark-line: #2c3034;
--dark-line-strong: #40454a;
--dark-ink: #f2f2f0; /* 16.7:1 */
--dark-ink-muted: #a2a6a9; /* 7.67:1 */
--dark-ink-faint: #84898d; /* 5.31:1 */
--dark-accent: #e8563c; /* 5.17:1 */
--dark-accent-hover: #f2705a;
--dark-accent-ink: #160906;
--dark-accent-wash: #33170f;
/* 3D material roles */
--core-metal: #c9c6be;
--core-metal-dark: #343534;
--core-glass: #8c9898;
--core-spectrum: #4f7d88;
--core-shadow: #232423;
--core-light: #fffdf6;
--core-scrim: linear-gradient(90deg, #e9e7e2 0%, #e9e7e2e8 26%, #e9e7e200 58%);
--core-vignette: radial-gradient(circle at 74% 44%, #ffffff00 30%, #15161614 100%);
--shadow-core: 0 2rem 5rem #15161624;
/* ── 형태 — 현행 사이트가 radius 0 으로 통일돼 있다. 유지할 자산이다 ── */
--radius: 0;
/* ── 간격 — 저장소 SSOT 표준 ── */
/* Space · grid */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 1rem;
--space-4: 1.5rem;
--space-5: 2.5rem;
--space-6: 4rem;
--space-3: 0.75rem;
--space-4: 1.25rem;
--space-5: 2rem;
--space-6: 3.5rem;
--space-7: 6rem;
--space-8: clamp(4.5rem, 3rem + 6vw, 9rem);
--space-8: clamp(6rem, 4rem + 7vw, 10rem);
--space-9: clamp(8rem, 5rem + 10vw, 13rem);
--page-pad: clamp(1.25rem, 0.7rem + 2.4vw, 4rem);
--wide: 90rem;
--content: 75rem;
--header-h: 4.5rem;
--control-min: 2.75rem;
--hairline: 1px;
--focus-width: 2px;
--radius: 0px;
--container: 1120px;
--pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem);
/* ── 모션 ── */
--dur-quick: 150ms;
--dur-normal: 380ms;
--ease: cubic-bezier(0.2, 0, 0, 1);
/* Motion */
--dur-instant: 120ms;
--dur-quick: 220ms;
--dur-normal: 420ms;
--dur-slow: 760ms;
--ease-out: cubic-bezier(0.22, 0.75, 0.16, 1);
--ease-in: cubic-bezier(0.55, 0.08, 0.68, 0.53);
--ease-soft: cubic-bezier(0.33, 1, 0.68, 1);
--shift-sm: 0.5rem;
--shift-lg: 1.5rem;
--stagger: 60ms;
}
@media (prefers-color-scheme: dark) {
:root {
--page: #0d0f0f;
--surface: #171a1a;
--surface-muted: #2c302f;
--surface-quiet: #202423;
--ink: #f1f0eb;
--ink-muted: #b8bab6;
--ink-soft: #a8aaa7;
--line: #3b3e3d;
--line-strong: #6e7270;
--signal: #d99a38;
--signal-strong: #f0b454;
--signal-ink: #15120c;
--selection: #654a27;
--focus: #f0b454;
--inverse: #edeae4;
--inverse-raised: #f6f4ef;
--inverse-ink: #171817;
--inverse-muted: #5b5b57;
--inverse-line: #b9b5ae;
--inverse-signal: #a92f25;
--inverse-signal-ink: #fff8f0;
--core-metal: #555b5b;
--core-metal-dark: #090b0b;
--core-glass: #838d8b;
--core-spectrum: #7fb8c3;
--core-shadow: #030404;
--core-light: #f5ead3;
--core-scrim: linear-gradient(90deg, #0d0f0f 0%, #0d0f0fe8 26%, #0d0f0f00 58%);
--core-vignette: radial-gradient(circle at 74% 44%, #00000000 30%, #0000005c 100%);
--shadow-core: 0 2rem 5rem #00000066;
}
}
@media (prefers-reduced-motion: reduce) {
:root {
--shift-sm: 0px;
--shift-lg: 0px;
--stagger: 0ms;
--dur-normal: var(--dur-instant);
--dur-slow: var(--dur-instant);
--ease-out: ease-out;
--ease-in: ease-out;
--ease-soft: ease-out;
}
}