4 Commits
v1.0.1 ... main

Author SHA1 Message Date
239f61c506 ESG 스크롤 복귀와 기술 역량 이미지 정렬·지도 표시 개선
- ESG 푸터에서 위로 스크롤하면 문서 영역이 먼저 복귀하도록 처리
- 섹션 전환 중 문서 내부 스크롤을 막아 상단 잘림 방지
- 기술 역량 이미지의 상단 여백과 가용 높이를 본문 기준으로 정렬
- 이미지 진입 애니메이션을 고려해 텍스트 겹침과 화면 이탈 방지
- 기술 역량 프로젝트 순서·설명 및 개별 이미지 배치 설정 정리
- 기술 역량 데이터에 맞춰 검색용 정적 HTML 동기화
- 지도 검색용 도로명 주소와 층·호수 안내를 분리해 건물 위치 핀 표시
- 지도 기본 확대 수준을 16으로 설정하고 한국어 표시 적용
- 회사 소개·조직도와 개인정보 동의 거부 안내 문구 정리

검증:
- JavaScript 구문 검사 및 git diff --check 통과
- ESG 세 문서의 푸터 복귀·내부 스크롤·키보드 이동 확인
- 기술 역량 29개 슬라이드의 데스크톱 이미지 정렬 및 모바일 이동 확인
- 본사·지사 지도 위치 핀, 상세 주소, 외부 지도 링크 확인
2026-09-30 17:55:10 +09:00
51932269c7 기술 역량 카테고리 메뉴 상단 배치 및 간격 개선
- 카테고리 선택 메뉴를 상단 헤더 아래로 이동
- 카테고리 메뉴와 본문의 좌우 여백을 공통 기준으로 정렬
- 메뉴와 아이브로우 사이 여백 확대
- 제목, 부제, 본문의 간격과 줄간격 조정
- 자동 재생 제어 버튼은 하단 위치 유지
- 모바일 카테고리를 4열로 정렬하고 본문과 좌우 여백 통일

검증: git diff --check 통과. 브라우저 연결 제한으로 화면 검증은 수행하지 못함.
2026-09-29 15:17:58 +09:00
484216b3e3 회사 소개 콘텐츠와 다운로드 자료 정리
회사 소개 구성 변경
- 첫 번째 회사 개요 섹션 삭제
- 회사 소개 페이지 푸터의 고객센터 연락처와 운영 시간 삭제

자료 및 연결 정보 변경
- 2026-09-29 회사소개서 PDF 추가 및 다운로드 링크 갱신
- PDF 파일명과 링크의 한글 정규화 형식을 통일
- 삭제된 회사 개요 섹션으로 연결되던 사이트맵 항목 제거
- 오시는 길 지도 확대 수준을 16에서 15로 조정

검증: JavaScript 구문, 회사 소개 링크와 사이트맵 앵커, PDF 경로 및 Git LFS 포인터 확인
2026-09-29 15:17:44 +09:00
bcde9f1022 이미지 최적화 및 변환 작업 개선
메인: 홈 배경 WebP 추가 및 CSS 이미지 경로 전환

기술 역량: 솔루션 04 오브젝트 이미지 교체, 배치 설정 정리 및 썸네일 재생성

도구: WebP 누락 파일 우선 처리, 진행 표시, 파일명 필터와 강제 덮어쓰기 옵션 추가
2026-09-21 18:25:10 +09:00
24 changed files with 170 additions and 241 deletions

View File

@@ -42,50 +42,6 @@
</nav>
<main class="about-page about-refresh">
<section class="about-hero" id="overview" data-page-title="회사 개요">
<div class="about-hero-copy">
<p class="eyebrow">Company Overview</p>
<img
class="overview-logo"
src="assets/images/mobipin-logo.png"
alt="MOBIPIN · Mobile Pinnacle Technology"
/>
<h1>모비핀테크놀러지</h1>
<p>
모비핀테크놀러지는 스마트 플랫폼과 AI 로봇 개발 경험을 기반으로
AUTOSAR 전장, 관제 솔루션, 로봇 SW, 웹·앱 SI까지 연결하는 개발
조직입니다.
</p>
</div>
<div class="overview-facts">
<dl>
<div>
<dt>회사명</dt>
<dd>주식회사 모비핀테크놀러지</dd>
</div>
<div>
<dt>설립일</dt>
<dd>2015년 3월</dd>
</div>
<div>
<dt>대표이사</dt>
<dd>권오규</dd>
</div>
<div>
<dt>종업원 수</dt>
<dd>40명 (2026년 3월 기준)</dd>
</div>
<div>
<dt>주소</dt>
<dd>
대구 북구 경대로17길 47, 8층 803호<br />서울시 강남구 논현로 416
운기빌딩 6층
</dd>
</div>
</dl>
</div>
</section>
<section class="about-section capability" id="capability" data-page-title="기술 역량">
<p class="eyebrow">Integrated Capability</p>
<h2>경험을 기술로, 기술을 성과로 연결합니다.</h2>
@@ -119,11 +75,10 @@
</article>
</div>
<div class="company-profile-actions">
<!-- Replace href with the final company profile PDF path. -->
<a
class="button button-primary"
href="assets/docs/MOBIPIN_회사소개서_20260918.pdf"
download="MOBIPIN_회사소개서_20260918.pdf"
href="assets/docs/MOBIPIN_회사소개서_260929.pdf"
download="MOBIPIN_회사소개서_260929.pdf"
>회사소개서 다운로드</a>
</div>
</section>
@@ -266,7 +221,7 @@
</ul>
</article>
<article>
<span>Technology Teams</span><strong>개발실</strong>
<span>Development Teams</span><strong>개발실</strong>
<ul class="org-teams">
<li>전장개발팀</li>
<li>솔루션개발팀</li>
@@ -393,20 +348,11 @@
<footer class="site-footer">
<div>
<span
>고객센터 <a href="tel:0532140592">053-214-0592</a> | 평일 09:00 ~
18:00</span
>
<strong>(주)모비핀테크놀러지</strong>
<span class="footer-copyright"
>Copyright 2015 – 2026 | Mobipin Technology | All Rights
Reserved</span
>
<span class="footer-copyright">Copyright 2015 – 2026 | Mobipin Technology | All Rights Reserved</span>
</div>
<nav class="footer-links" aria-label="사이트 정책">
<button type="button" data-site-modal="privacy">
<strong>개인정보 처리방침</strong>
</button>
<button type="button" data-site-modal="privacy"><strong>개인정보 처리방침</strong></button>
<button type="button" data-site-modal="sitemap">사이트맵</button>
</nav>
</footer>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -74,6 +74,15 @@
alt=""
aria-hidden="true"
/>
<div class="capabilities-toolbar" aria-label="기술 역량 분류">
<button type="button" class="is-active" data-filter="automotive">
AUTOMOTIVE
</button>
<button type="button" data-filter="solution">SOLUTION</button>
<button type="button" data-filter="si">SI</button>
<button type="button" data-filter="robotics">ROBOTICS</button>
<!-- <button type="button" data-filter="certifications">PATENTS</button> -->
</div>
<div class="feature-content">
<p class="eyebrow" data-feature-category>Automotive</p>
<h1 data-feature-title>전장 기술 역량</h1>
@@ -86,14 +95,6 @@
</p>
</div>
<div class="feature-table-wrap" data-feature-table hidden></div>
<div class="capabilities-toolbar" aria-label="기술 역량 분류">
<button type="button" class="is-active" data-filter="automotive">
AUTOMOTIVE
</button>
<button type="button" data-filter="solution">SOLUTION</button>
<button type="button" data-filter="si">SI</button>
<button type="button" data-filter="robotics">ROBOTICS</button>
<!-- <button type="button" data-filter="certifications">PATENTS</button> -->
<button
type="button"
class="autoplay-toggle"
@@ -110,7 +111,6 @@
<span data-autoplay-label>멈춤</span>
</button>
</div>
</div>
<nav
class="project-dots"
aria-label="프로젝트 목록"
@@ -156,16 +156,16 @@
<p>H-VAC Controller Application Software</p>
<p>기존 Non-AUTOSAR 기반으로 개발된 차량용 공조제어기 소프트웨어를 AUTOSAR 기반의 표준화된 구조로 전환하고, 소프트웨어 아키텍처 설계부터 기능 구현 및 검증까지 수행하였습니다. 기존 소프트웨어의 기능과 구조를 분석하여 AUTOSAR 환경에 적합하도록 ASW(Application Software) 영역의 아키텍처를 새롭게 설계하고, 제어기 소프트웨어의 구성 요소를 체계적으로 재구성하였습니다. AUTOSAR ASW 구조에 따라 SWC(Software Component)를 생성하고 각 Component에 필요한 PORT와 Interface를 정의하였으며, Event 및 Runnable을 구성하여 소프트웨어 기능 간의 관계와 실행 구조를 설계하였습니다. RTE( Runtime Environment)를 Generate하고 BSW 영역과 연계하여 Application Software와 하위 소프트웨어 계층 간의 정상적인 기능 호출 및 데이터 통신이 가능하도록 통합 작업을 수행하였습니다. 전환 과정에서 발생하는 기능 결함과 연계 오류에 대한 대응 업무를 수행하고, SW Test를 통해 각 기능의 정상 동작 여부를 검증하였습니다. Non-AUTOSAR 기반의 기존 공조제어기 소프트웨어를 AUTOSAR 표준 구조로 성공적으로 전환하고, ASW 아키텍처 설계부터 SWC 구성, RTE Generate 및 BSW 연계, SW Test와 결함 분석·Debugging까지 전반적인 AUTOSAR 전환 및 검증 업무를 수행하였습니다.</p>
</article>
<article id="seo-autonomous-vehicle-fcm-controller">
<h4>Autonomous Vehicle FCM 제어기 개발</h4>
<p>Front Camera Module Controller</p>
<p>자율주행 차량의 핵심 전장 기능을 안정적으로 지원할 수 있도록 AUTOSAR 기반 FCM 제어기의 소프트웨어 아키텍처 설계 및 핵심 모듈 통합 개발을 수행하였습니다. AUTOSAR BSW 아키텍처를 기반으로 제어기 소프트웨어 구조를 설계하고 주요 BSW 모듈을 통합하여 차량 전장 환경에 적합한 소프트웨어 플랫폼을 구성하였습니다. 차량 진단 기능을 위한 Application을 개발하고 Cyber Security 관련 사양과 연계하여 ASK 등의 보안 기능을 적용하였으며, CAN 및 CAN-FD 기반 차량 통신 기능을 구현하여 차량 네트워크와의 안정적인 데이터 연계가 가능하도록 구성하였습니다. 또한 DCM을 비롯한 일부 하위 CAN 및 Ethernet AUTOSAR Layer Stack을 개발하였습니다. ISO 및 OEM 요구사항을 기반으로 DoCAN 및 DoIP Stack을 개발하여 CAN 및 Ethernet 환경에서의 진단 통신 기능을 구현하였으며, Bootloader 진단 사양과 Reprogramming 기능을 개발하여 제어기의 안정적인 소프트웨어 업데이트 환경을 구축하였습니다. 이와 함께 Application 영역의 진단 사양을 개발하여 제어기 내부 기능과 진단 시스템 간의 연계성을 확보하였습니다. 이를 통해 AUTOSAR 기반 BSW 아키텍처 설계 및 모듈 통합부터 차량 통신, 진단 Application, Cyber Security, Bootloader 및 DoCAN·DoIP 통신 Stack까지 FCM 제어기 개발에 필요한 핵심 소프트웨어 영역을 종합적으로 구현하였습니다.</p>
</article>
<article id="seo-hvac-autosar-bsw-development">
<h4>차량용 공조제어기 SW 개발</h4>
<p>H-VAC Controller Basic Software</p>
<p>차량용 공조제어기의 안정적인 소프트웨어 동작과 차량 전장 시스템과의 원활한 연계를 위해 AUTOSAR 기반의 BSW 및 Middleware를 개발하고, 제어기의 핵심 기능과 진단·보안·업데이트 기능을 통합 구현하였습니다. FBL(Flash Boot Loader) 기능을 구현하고 Sleep &amp; Wake-up 사양을 개발하여 차량의 전원 상태 변화에 따른 제어기의 안정적인 동작 환경을 확보하였습니다. BSW Configuration 및 Implementation을 수행하고 Middleware를 구현하였으며, M-CAL Port를 비롯하여 ADC, PWM, ICU, IoHwAb, OS 등 주요 AUTOSAR 모듈을 설정하고 제어기 사양에 맞게 통합하였습니다. 또한 CAN 요구사항을 반영하여 관련 DB를 Import하고 Generate 및 Harmonize 과정을 수행함으로써 차량 네트워크 환경과 제어기 소프트웨어 간의 통신 연계성을 구현하였습니다. 보안 기능 강화를 위해 HSM, ASK, SFM 및 Crypto Library를 포팅하고 기능 검증을 수행하여 차량용 제어기에 요구되는 보안 기능을 안정적으로 적용하였습니다. 진단 영역에서는 DiagDCM 및 DEM Configuration을 수행하고 관련 기능을 검증하여 차량 진단 시스템과 제어기 간의 안정적인 진단 환경을 구축하였습니다. OTA(Over-The-Air) 기반 Background 및 Reprogramming 기능을 개발하고 검증하여 차량 소프트웨어를 안정적으로 업데이트할 수 있는 환경을 구현하였습니다. Watch-Dog 요구사항을 반영 개발하였습니다.</p>
</article>
<article id="seo-autonomous-vehicle-fcm-controller">
<h4>Autonomous Vehicle FCM 제어기 개발</h4>
<p>Front Camera Module Controller</p>
<p>자율주행 차량의 핵심 전장 기능을 안정적으로 지원할 수 있도록 AUTOSAR 기반 FCM 제어기의 소프트웨어 아키텍처 설계 및 핵심 모듈 통합 개발을 수행하였습니다. AUTOSAR BSW 아키텍처를 기반으로 제어기 소프트웨어 구조를 설계하고 주요 BSW 모듈을 통합하여 차량 전장 환경에 적합한 소프트웨어 플랫폼을 구성하였습니다. 차량 진단 기능을 위한 Application을 개발하고 Cyber Security 관련 사양과 연계하여 ASK 등의 보안 기능을 적용하였으며, CAN 및 CAN-FD 기반 차량 통신 기능을 구현하여 차량 네트워크와의 안정적인 데이터 연계가 가능하도록 구성하였습니다. 또한 DCM을 비롯한 일부 하위 CAN 및 Ethernet AUTOSAR Layer Stack을 개발하였습니다. ISO 및 OEM 요구사항을 기반으로 DoCAN 및 DoIP Stack을 개발하여 CAN 및 Ethernet 환경에서의 진단 통신 기능을 구현하였으며, Bootloader 진단 사양과 Reprogramming 기능을 개발하여 제어기의 안정적인 소프트웨어 업데이트 환경을 구축하였습니다. 이와 함께 Application 영역의 진단 사양을 개발하여 제어기 내부 기능과 진단 시스템 간의 연계성을 확보하였습니다. 이를 통해 AUTOSAR 기반 BSW 아키텍처 설계 및 모듈 통합부터 차량 통신, 진단 Application, Cyber Security, Bootloader 및 DoCAN·DoIP 통신 Stack까지 FCM 제어기 개발에 필요한 핵심 소프트웨어 영역을 종합적으로 구현하였습니다.</p>
</article>
<article id="seo-a-spice-swe5-integration-verification">
<h4>A-SPICE 기반 SWE5 통합검증</h4>
<p>Software Engineering Process Integration Test</p>

View File

@@ -54,7 +54,8 @@
type="button"
class="office-map-button"
data-map-title="대구 본사"
data-map-address="대구광역시 북구 경대로17길 47 IT융합산업빌딩"
data-map-address="대구광역시 북구 경대로17길 47 IT융합산업빌딩 8층 803호"
data-map-query="대구광역시 북구 경대로17길 47"
aria-label="대구 본사 지도 보기"
title="지도 보기"
>
@@ -71,7 +72,8 @@
type="button"
class="office-map-button"
data-map-title="서울 지사"
data-map-address="서울특별시 강남구 논현로 416 운기빌딩"
data-map-address="서울특별시 강남구 논현로 416 운기빌딩 6층"
data-map-query="서울특별시 강남구 논현로 416"
aria-label="서울 지사 지도 보기"
title="지도 보기"
>

View File

@@ -376,7 +376,7 @@ body.mobile-navigation-open {
background-image:
linear-gradient(90deg, rgba(7, 9, 13, .94) 0%, rgba(7, 9, 13, .66) 38%, rgba(7, 9, 13, .18) 72%),
linear-gradient(180deg, rgba(7, 9, 13, .1), rgba(7, 9, 13, .9)),
url("../assets/images/home-background.png");
url("../assets/images-webp/home-background.webp");
animation: slow-zoom 18s ease-in-out infinite alternate;
}
@@ -791,12 +791,12 @@ p {
.feature-content {
position: absolute;
top: 108px;
left: clamp(56px, 7vw, 132px);
top: var(--capabilities-content-top);
left: var(--capabilities-gutter);
z-index: 2;
align-self: flex-start;
width: min(720px, 54%);
max-height: calc(100dvh - 204px);
max-height: calc(100dvh - var(--capabilities-content-top) - 96px);
overflow-y: auto;
overscroll-behavior: contain;
scrollbar-width: thin;
@@ -804,24 +804,24 @@ p {
.feature-content h1 {
max-width: 760px;
margin: 14px 0 8px;
margin: 18px 0 12px;
font-size: 42px;
line-height: 1.16;
line-height: 1.2;
}
.feature-content p {
white-space: pre-line;
font-size: 15px;
line-height: 1.68;
line-height: 1.8;
}
.feature-content .feature-subtitle {
margin: 0 0 44px;
margin: 0 0 40px;
max-width: 660px;
color: rgba(255, 255, 255, .62);
font-size: 16px;
font-weight: 800;
line-height: 1.35;
line-height: 1.5;
white-space: normal;
}
@@ -829,23 +829,23 @@ p {
position: absolute;
z-index: 1;
right: clamp(190px, 17vw, 330px);
top: calc(50% + 6px);
top: calc((100% + var(--capabilities-content-top) - 96px) / 2);
bottom: auto;
width: min(44vw, 720px);
height: auto;
max-height: calc(100dvh - 228px);
max-height: max(0px, calc(100dvh - var(--capabilities-content-top) - 96px));
object-fit: contain;
opacity: 0;
pointer-events: none;
filter: drop-shadow(0 28px 46px rgba(0, 0, 0, .48));
transform: translate(0, -50%);
translate: calc(var(--object-fit-x, 0px) - 36px) 0;
translate: calc(var(--object-fit-x, 0px) - 36px) var(--object-fit-y, 0px);
transition: opacity .28s var(--ease), translate .28s var(--ease);
}
.feature-object.is-visible {
opacity: .96;
translate: var(--object-fit-x, 0px) 0;
translate: var(--object-fit-x, 0px) var(--object-fit-y, 0px);
transform: translate(0, -50%) scale(1);
}
@@ -905,7 +905,7 @@ p {
}
.feature-object.is-motion-bottom:not(.is-visible) {
translate: var(--object-fit-x, 0px) 36px;
translate: var(--object-fit-x, 0px) calc(var(--object-fit-y, 0px) + 36px);
}
.feature-object.is-repositioning {
@@ -981,16 +981,17 @@ p {
.capabilities-toolbar {
position: absolute;
z-index: 2;
left: clamp(24px, 5vw, 72px);
right: clamp(24px, 5vw, 72px);
bottom: 28px;
left: var(--capabilities-gutter);
right: var(--capabilities-gutter);
top: 90px;
display: flex;
gap: 8px;
padding-top: 18px;
border-top: 1px solid rgba(255, 255, 255, .24);
padding-bottom: 18px;
border-bottom: 1px solid rgba(255, 255, 255, .24);
}
.capabilities-toolbar button {
.capabilities-toolbar button,
.autoplay-toggle {
min-width: 86px;
min-height: 40px;
padding: 0 16px;
@@ -1008,8 +1009,11 @@ p {
font-weight: 800;
}
.capabilities-toolbar .autoplay-toggle {
margin-left: auto;
.workbench-stage > .autoplay-toggle {
position: absolute;
z-index: 2;
right: clamp(24px, 5vw, 72px);
bottom: 28px;
color: var(--text);
background: rgba(255, 255, 255, .12);
}
@@ -1080,6 +1084,8 @@ p {
}
.capabilities-workbench {
--capabilities-gutter: clamp(56px, 7vw, 132px);
--capabilities-content-top: 212px;
position: fixed;
inset: 0;
height: 100dvh;
@@ -1096,7 +1102,7 @@ p {
display: flex;
align-items: center;
overflow: hidden;
padding: 108px clamp(24px, 5vw, 72px) 96px clamp(56px, 7vw, 132px);
padding: var(--capabilities-content-top) var(--capabilities-gutter) 96px;
}
.project-dots {
@@ -2266,7 +2272,7 @@ html.has-site-dialog,
display: none;
}
.capabilities-toolbar .autoplay-toggle {
.workbench-stage > .autoplay-toggle {
display: none;
}
@@ -2747,6 +2753,7 @@ h1, h2, h3, p, a, button, label, span, strong, small, dt, dd, li, td, th {
}
.capabilities-body .capabilities-workbench {
--capabilities-gutter: 20px;
position: fixed;
inset: 72px 0 0;
height: calc(100dvh - 72px);
@@ -2772,19 +2779,20 @@ h1, h2, h3, p, a, button, label, span, strong, small, dt, dd, li, td, th {
min-height: 0;
max-height: none;
width: 100%;
padding: 24px 20px 84px;
padding: 32px var(--capabilities-gutter) 84px;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
}
.capabilities-body .feature-content h1 {
margin-top: 16px;
font-size: 28px;
line-height: 1.3;
}
.capabilities-body .feature-subtitle {
margin-bottom: 24px;
margin-bottom: 28px;
font-size: 14px;
}
@@ -2794,7 +2802,7 @@ h1, h2, h3, p, a, button, label, span, strong, small, dt, dd, li, td, th {
min-width: 0;
width: 100%;
margin: 0;
padding: 24px 16px 84px;
padding: 32px var(--capabilities-gutter) 84px;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
@@ -2837,9 +2845,9 @@ h1, h2, h3, p, a, button, label, span, strong, small, dt, dd, li, td, th {
grid-row: 1;
inset: auto;
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 4px;
padding: 10px 12px;
padding: 14px var(--capabilities-gutter);
background: #101419;
overflow: visible;
}
@@ -2852,7 +2860,7 @@ h1, h2, h3, p, a, button, label, span, strong, small, dt, dd, li, td, th {
border-radius: 4px;
}
.capabilities-body .capabilities-toolbar .autoplay-toggle {
.capabilities-body .workbench-stage > .autoplay-toggle {
display: none;
}

View File

@@ -73,7 +73,7 @@
<section class="section intro" id="company" data-page-title="회사 소개">
<div class="section-label">About</div>
<div class="intro-copy">
<h2>Network, Data, Human을 연결하는 Total SW 개발 조직입니다.</h2>
<h2>Network, Data, Human을 연결하는 Total SW 개발 회사입니다.</h2>
<p>
AUTOSAR 기반 자동차 전장 개발, AI 기반 관제 스마트 플랫폼, 로봇 SW 개발 및 AI 플랫폼,
웹·앱 SI 개발까지 다양한 R&amp;D 및 협력 개발을 통해 양질의 기술 지원을 제공합니다.

View File

@@ -16,7 +16,7 @@ MATLAB Simulink를 활용한 Model 기반 Application Software 설계 및 검증
ISO 26262 기능 안전 개발 프로세스 기반 업무 (ASIL, FMEA, DFA) 를 수행하였습니다.
`,
scope: "Safety mechanism · Platform",
scope: "Side Body Control Module",
output: "SW module · Verification",
image: "assets/images/automotive/automotive_01_background.jpeg",
objectImage: "assets/images/automotive/automotive_01_object.png",
@@ -44,6 +44,27 @@ RTE( Runtime Environment)를 Generate하고 BSW 영역과 연계하여 Applicati
output: "Issue report · Tool flow",
image: "assets/images/automotive/automotive_02_background.png",
objectImage: "assets/images/automotive/automotive_02_object.png",
},
// P.15
{
id: "hvac-autosar-bsw-development",
type: "automotive",
category: "AUTOSAR BSW DEVELOPMENT",
title: "차량용 공조제어기 SW 개발",
subtitle: "H-VAC Controller Basic Software",
description: `차량용 공조제어기의 안정적인 소프트웨어 동작과 차량 전장 시스템과의 원활한 연계를 위해 AUTOSAR 기반의 BSW 및 Middleware를 개발하고, 제어기의 핵심 기능과 진단·보안·업데이트 기능을 통합 구현하였습니다.
FBL(Flash Boot Loader) 기능을 구현하고 Sleep & Wake-up 사양을 개발하여 차량의 전원 상태 변화에 따른 제어기의 안정적인 동작 환경을 확보하였습니다. BSW Configuration 및 Implementation을 수행하고 Middleware를 구현하였으며, M-CAL Port를 비롯하여 ADC, PWM, ICU, IoHwAb, OS 등 주요 AUTOSAR 모듈을 설정하고 제어기 사양에 맞게 통합하였습니다.
또한 CAN 요구사항을 반영하여 관련 DB를 Import하고 Generate 및 Harmonize 과정을 수행함으로써 차량 네트워크 환경과 제어기 소프트웨어 간의 통신 연계성을 구현하였습니다.
보안 기능 강화를 위해 HSM, ASK, SFM 및 Crypto Library를 포팅하고 기능 검증을 수행하여 차량용 제어기에 요구되는 보안 기능을 안정적으로 적용하였습니다. 진단 영역에서는 DiagDCM 및 DEM Configuration을 수행하고 관련 기능을 검증하여 차량 진단 시스템과 제어기 간의 안정적인 진단 환경을 구축하였습니다.
OTA(Over-The-Air) 기반 Background 및 Reprogramming 기능을 개발하고 검증하여 차량 소프트웨어를 안정적으로 업데이트할 수 있는 환경을 구현하였습니다. Watch-Dog 요구사항을 반영 개발하였습니다.`,
scope: "H-VAC Controller Basic Software",
output: "Control module · QA",
image: "assets/images/automotive/automotive_04_background.jpeg",
objectImage: "assets/images/automotive/automotive_04_object.png",
},
// P.14
{
@@ -67,27 +88,6 @@ ISO 및 OEM 요구사항을 기반으로 DoCAN 및 DoIP Stack을 개발하여 CA
image: "assets/images/automotive/automotive_03_background.png",
objectImage: "assets/images/automotive/automotive_03_object.png",
},
// P.15
{
id: "hvac-autosar-bsw-development",
type: "automotive",
category: "AUTOSAR BSW DEVELOPMENT",
title: "차량용 공조제어기 SW 개발",
subtitle: "H-VAC Controller Basic Software",
description: `차량용 공조제어기의 안정적인 소프트웨어 동작과 차량 전장 시스템과의 원활한 연계를 위해 AUTOSAR 기반의 BSW 및 Middleware를 개발하고, 제어기의 핵심 기능과 진단·보안·업데이트 기능을 통합 구현하였습니다.
FBL(Flash Boot Loader) 기능을 구현하고 Sleep & Wake-up 사양을 개발하여 차량의 전원 상태 변화에 따른 제어기의 안정적인 동작 환경을 확보하였습니다. BSW Configuration 및 Implementation을 수행하고 Middleware를 구현하였으며, M-CAL Port를 비롯하여 ADC, PWM, ICU, IoHwAb, OS 등 주요 AUTOSAR 모듈을 설정하고 제어기 사양에 맞게 통합하였습니다.
또한 CAN 요구사항을 반영하여 관련 DB를 Import하고 Generate 및 Harmonize 과정을 수행함으로써 차량 네트워크 환경과 제어기 소프트웨어 간의 통신 연계성을 구현하였습니다.
보안 기능 강화를 위해 HSM, ASK, SFM 및 Crypto Library를 포팅하고 기능 검증을 수행하여 차량용 제어기에 요구되는 보안 기능을 안정적으로 적용하였습니다. 진단 영역에서는 DiagDCM 및 DEM Configuration을 수행하고 관련 기능을 검증하여 차량 진단 시스템과 제어기 간의 안정적인 진단 환경을 구축하였습니다.
OTA(Over-The-Air) 기반 Background 및 Reprogramming 기능을 개발하고 검증하여 차량 소프트웨어를 안정적으로 업데이트할 수 있는 환경을 구현하였습니다. Watch-Dog 요구사항을 반영 개발하였습니다.`,
scope: "H-VAC Controller Basic Software",
output: "Control module · QA",
image: "assets/images/automotive/automotive_04_background.jpeg",
objectImage: "assets/images/automotive/automotive_04_object.png",
},
// P.16
{
id: "a-spice-swe5-integration-verification",
@@ -407,14 +407,6 @@ GPS 기반의 위치 정보를 활용하여 대중교통의 이동 상황을 실
output: "Web platform",
image: "assets/images/solution/solution_04_background.png",
objectImage: "assets/images/solution/solution_04_object.png",
objectLayout: {
x: "100%",
y: "calc(100% - 86px)",
anchorX: "-98%",
anchorY: "-100%",
height: "auto",
maxHeight: "none",
},
},
// P.32
{
@@ -435,13 +427,6 @@ GPS 기반의 위치 정보를 활용하여 대중교통의 이동 상황을 실
output: "Control room · Alert",
image: "assets/images/solution/solution_05_background.png",
objectImage: "assets/images/solution/solution_05_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
// P.33
{
@@ -462,13 +447,6 @@ GPS 기반의 위치 정보를 활용하여 대중교통의 이동 상황을 실
output: "Capture flow · Viewer",
image: "assets/images/solution/solution_06_background.jpeg",
objectImage: "assets/images/solution/solution_06_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
// P.34
{
@@ -489,13 +467,6 @@ GPS 기반의 위치 정보를 활용하여 대중교통의 이동 상황을 실
output: "Pipeline · Dashboard",
image: "assets/images/solution/solution_07_background.jpeg",
objectImage: "assets/images/solution/solution_07_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
// P.35
{
@@ -516,13 +487,7 @@ GPS 기반의 위치 정보를 활용하여 대중교통의 이동 상황을 실
output: "Recognition module",
image: "assets/images/solution/solution_08_background.jpg",
objectImage: "assets/images/solution/solution_08_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
// Certifications
{
@@ -597,13 +562,6 @@ AUTOSAR 표준 기반의 플랫폼 환경에서 ECU 기능에 필요한 모듈
output: "Admin · Approval flow",
image: "assets/images/si/si_02_background.jpg",
objectImage: "assets/images/si/si_02_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
// P.40
{
@@ -650,13 +608,6 @@ AUTOSAR 표준 기반의 플랫폼 환경에서 ECU 기능에 필요한 모듈
output: "iOS/Android · API",
image: "assets/images/si/si_04_background.png",
objectImage: "assets/images/si/si_04_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
// P.42
{
@@ -719,13 +670,13 @@ GPS 기반의 자녀 안심존 관리 기능을 통해 지정된 안전 구역
output: "Backend · Docs",
image: "assets/images/si/si_07_background.png",
objectImage: "assets/images/si/si_07_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
// objectLayout: {
// x: "50%",
// y: "50%",
// anchorX: "-50%",
// anchorY: "-50%",
// maxHeight: "560px",
// },
},
// P.45
{
@@ -748,12 +699,5 @@ GPS 기반의 자녀 안심존 관리 기능을 통해 지정된 안전 구역
output: "Backend · Docs",
image: "assets/images/si/si_08_background.png",
objectImage: "assets/images/si/si_08_object.png",
objectLayout: {
x: "50%",
y: "50%",
anchorX: "-50%",
anchorY: "-50%",
maxHeight: "560px",
},
},
];

View File

@@ -176,6 +176,10 @@
function canScrollPolicy(target, direction) {
const panel = target.closest(".esg-policy-panel");
if (!panel || panel.hidden) return false;
const workspace = panel.closest(".esg-workspace");
// Restore the whole reader below the header before scrolling its document.
if (workspace && Math.abs(window.scrollY - sectionStop(workspace)) > 4) return false;
if (performance.now() < transitionUntil) return false;
const remaining = panel.scrollHeight - panel.clientHeight - panel.scrollTop;
return direction > 0 ? remaining > 2 : panel.scrollTop > 2;
}
@@ -238,10 +242,8 @@
<p>수집된 개인정보는 문의 처리 완료 후 1년간 보관하며, 보유 기간이 지나면 지체 없이 파기합니다.</p>
<h3>4. 정보 제공 및 처리 위탁</h3>
<p>제공된 정보는 문의 응대 목적으로 사용합니다. 외부 서비스에 처리를 위탁하는 경우 해당 서비스와 처리 범위를 운영 방침에 명시합니다.</p>
<h3>5. 동의 거부 및 정보 확인</h3>
<p>개인정보 수집 및 이용에 동의하지 않을 수 있습니다. 동의하지 않으면 온라인 문의를 전송할 수 없으며, 고객센터로 직접 연락할 수 있습니다. 제공한 정보의 확인, 수정, 삭제 요청도 고객센터로 문의할 수 있습니다.</p>
<h3>6. 개인정보 관련 문의</h3>
<p>주식회사 모비핀테크놀러지 · 고객센터 <a href="tel:0532140592">053-214-0592</a><br />평일 09:00 ~ 18:00</p>`,
<h3>5. 동의 거부</h3>
<p>개인정보 수집 및 이용에 동의하지 않을 수 있습니다. 다만, 동의하지 않을 경우 온라인 문의 서비스를 이용할 수 없습니다.</p>`,
},
sitemap: {
title: "사이트맵",
@@ -251,7 +253,6 @@
</section>
<section>
<h3><a href="about.html">회사소개</a></h3>
<a href="about.html#overview">회사 개요</a>
<a href="about.html#capability">기술 역량</a>
<a href="about.html#history">연혁</a>
<a href="about.html#organization">조직도</a>
@@ -351,10 +352,11 @@
trigger.addEventListener("click", () => {
const office = trigger.dataset.mapTitle;
const address = trigger.dataset.mapAddress;
const query = encodeURIComponent(address);
// Search for the building; floor/unit details can prevent a map pin from resolving.
const query = encodeURIComponent(trigger.dataset.mapQuery || address);
title.textContent = `${office} 오시는 길`;
frame.title = `${office} 위치 지도`;
frame.src = `https://maps.google.com/maps?q=${query}&z=16&output=embed`;
frame.src = `https://maps.google.com/maps?q=${query}&z=16&hl=ko&output=embed`;
addressLabel.textContent = address;
mapLink.href = `https://www.google.com/maps/search/?api=1&query=${query}`;
dialog.showModal();
@@ -753,29 +755,43 @@
const titleBottom = featureTitle.getBoundingClientRect().bottom - stageBounds.top;
capabilitiesWorkbench.style.setProperty("--certificate-top", `${titleBottom + 24}px`);
}
const contentRight = featureContent.getBoundingClientRect().right + 32;
const contentBounds = featureContent.getBoundingClientRect();
const contentRight = contentBounds.right + 32;
const contentTop = contentBounds.top;
const contentBottom = stageBounds.bottom - parseFloat(window.getComputedStyle(stage).paddingBottom);
[featureObject, featureObjectSecondary].forEach((element) => {
if (!element) return;
element.style.removeProperty("width");
element.style.removeProperty("height");
element.style.removeProperty("--object-fit-x");
element.style.removeProperty("--object-fit-y");
if (!desktop || !hasDescription || !element.getAttribute("src")) return;
const style = window.getComputedStyle(element);
const width = parseFloat(style.width);
const height = parseFloat(style.height);
const available = Math.max(0, stageBounds.right - contentRight);
const availableHeight = Math.max(0, contentBottom - contentTop);
if (!width || !height) return;
// Fit the actual image ratio, not the potentially letterboxed CSS rectangle.
const naturalWidth = element.naturalWidth;
const naturalHeight = element.naturalHeight;
if (!naturalWidth || !naturalHeight) return;
const ratio = Math.min(width / naturalWidth, height / naturalHeight, available / naturalWidth);
const ratio = Math.min(width / naturalWidth, height / naturalHeight,
available / naturalWidth, availableHeight / naturalHeight);
element.style.width = `${naturalWidth * ratio}px`;
element.style.height = `${naturalHeight * ratio}px`;
const bounds = element.getBoundingClientRect();
const motionX = parseFloat(window.getComputedStyle(element).translate) || 0;
const settledLeft = bounds.left - motionX;
const fittedStyle = window.getComputedStyle(element);
const [motionX = 0, motionY = 0] = fittedStyle.translate.split(" ").map(parseFloat);
const transform = new DOMMatrixReadOnly(fittedStyle.transform);
const [originX, originY] = fittedStyle.transformOrigin.split(" ").map(parseFloat);
// Measure the final position, excluding entry translation and scale.
const settledLeft = bounds.left - motionX + (transform.a - 1) * originX;
const settledTop = bounds.top - motionY + (transform.d - 1) * originY;
const settledBottom = settledTop + naturalHeight * ratio;
element.style.setProperty("--object-fit-x", `${Math.max(0, contentRight - settledLeft)}px`);
element.style.setProperty("--object-fit-y", `${Math.max(contentTop - settledTop,
Math.min(0, contentBottom - settledBottom))}px`);
});
}

View File

@@ -1,5 +1,5 @@
// 기술 역량 원본 이미지를 웹 전송용 WebP로 변환합니다.
// 실행: node scripts/generate-capability-webp.mjs [--force]
// 실행: node scripts/generate-capability-webp.mjs [파일명 일부] [--force]
import fs from "node:fs";
import path from "node:path";
import vm from "node:vm";
@@ -8,6 +8,7 @@ import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const force = process.argv.includes("--force");
const filters = process.argv.slice(2).filter((argument) => !argument.startsWith("--"));
const context = { window: {} };
vm.runInNewContext(fs.readFileSync(path.join(root, "js", "capabilities-data.js"), "utf8"), context);
@@ -34,21 +35,31 @@ function optimizedPath(source) {
.replace(/\.(?:png|jpe?g)$/i, ".webp");
}
let sourceBytes = 0;
let outputBytes = 0;
let generated = 0;
for (const [relativeSource, type] of sources) {
const assets = Array.from(sources, ([relativeSource, type]) => {
const source = path.join(root, relativeSource);
const target = path.join(root, optimizedPath(relativeSource));
const sourceStat = fs.statSync(source);
sourceBytes += sourceStat.size;
fs.mkdirSync(path.dirname(target), { recursive: true });
const targetStat = fs.existsSync(target) ? fs.statSync(target) : null;
return { relativeSource, type, source, target, sourceStat, targetStat };
}).filter(({ relativeSource }) =>
!filters.length || filters.some((filter) => relativeSource.includes(filter)));
if (!force && fs.existsSync(target) && fs.statSync(target).mtimeMs >= sourceStat.mtimeMs) {
outputBytes += fs.statSync(target).size;
continue;
}
if (!assets.length) {
throw new Error(`일치하는 기술 역량 이미지가 없습니다: ${filters.join(", ")}`);
}
// 삭제된 결과물을 먼저 복구하고, 나머지는 데이터에 정의된 순서대로 처리합니다.
assets.sort((a, b) => Number(Boolean(a.targetStat)) - Number(Boolean(b.targetStat)));
const pending = assets.filter(({ sourceStat, targetStat }) =>
force || !targetStat || targetStat.mtimeMs < sourceStat.mtimeMs);
let sourceBytes = assets.reduce((total, { sourceStat }) => total + sourceStat.size, 0);
let outputBytes = assets.reduce((total, asset) =>
pending.includes(asset) ? total : total + asset.targetStat.size, 0);
for (const [index, { relativeSource, type, source, target }] of pending.entries()) {
fs.mkdirSync(path.dirname(target), { recursive: true });
console.log(`[${index + 1}/${pending.length}] ${relativeSource}`);
const { width, height } = dimensions(source);
const maxWidth = type === "background" ? 2560 : 2400;
@@ -61,11 +72,10 @@ for (const [relativeSource, type] of sources) {
args.push(source, "-o", target);
execFileSync("cwebp", args, { stdio: "inherit" });
outputBytes += fs.statSync(target).size;
generated += 1;
}
const savedPercent = Math.round((1 - outputBytes / sourceBytes) * 100);
console.log(
`${generated ? `Generated ${generated}` : "Checked"} WebP assets: ` +
`${pending.length ? `Generated ${pending.length}` : "Checked"} WebP assets: ` +
`${(sourceBytes / 1048576).toFixed(1)}MB -> ${(outputBytes / 1048576).toFixed(1)}MB (${savedPercent}% reduction)`,
);