포커스 및 선택 (Focus & Active Row)

셀 클릭과 selectedRowKey를 연결해 현재 선택된 행을 시각적으로 강조하는 방법을 학습합니다.

#selectedRowKey#focus#row-click#active-row
검토일: 2026-08-23
LIVE DEMO포커스 및 선택 (Focus & Active Row) 인터랙티브 예제
인터랙티브 데모를 불러오는 중입니다…
GitHub
import { t } from './i18n';
import * as React from 'react';
import { BGrid, BGridColumn, BGridDataItem } from 'beautiful-grid';
import DataGridContainer from '../components/DataGridContainer';
import { useContainerSize } from '../hooks/useContainerSize';

interface KnowledgeArticle {
  articleId: number;
  category: string;
  title: string;
  owner: string;
  status: string;
  updatedAt: string;
}

const articleTitles = [
  t('신규 입사자 계정 발급 절차', 'New Employee Account Issuance Procedure'),
  t('법인카드 비용 정산 가이드', 'Corporate Card Expense Settlement Guide'),
  t('고객 데이터 보안 등급 정책', 'Customer Data Security Level Policy'),
  t('원격 근무 VPN 접속 방법', 'Remote Work VPN Access Method'),
  t('장애 상황 긴급 연락 체계', 'Emergency Contact System for Outages'),
  t('구매 요청 및 승인 프로세스', 'Purchase Request and Approval Process'),
];
const categories = [t('인사', 'HR'), t('재무', 'Finance'), t('보안', 'Security'), t('IT 운영', 'IT Operations'), t('고객지원', 'Customer Support')];
const owners = [t('김서준', 'Seojun Kim'), t('이하린', 'Harin Lee'), t('박도윤', 'Doyun Park'), t('최지우', 'Jiwoo Choi')];

const data: BGridDataItem<KnowledgeArticle>[] = Array.from({ length: 120 }, (_, index) => ({
  values: {
    articleId: index + 1,
    category: categories[index % categories.length],
    title: articleTitles[index % articleTitles.length],
    owner: owners[index % owners.length],
    status: index % 7 === 0 ? t('초안', 'Draft') : index % 4 === 0 ? t('검토 중', 'Under Review') : t('게시', 'Publish'),
    updatedAt: `2026-08-${String((index % 23) + 1).padStart(2, '0')}`,
  },
}));

export default function FocusExample() {
  const [selectedRowKey, setSelectedRowKey] = React.useState<number>();
  const [columns, setColumns] = React.useState<BGridColumn<KnowledgeArticle>[]>([
    { key: 'articleId', label: t('문서번호', 'Document Number'), width: 90, align: 'center' },
    { key: 'category', label: t('분류', 'Category'), width: 100, align: 'center' },
    { key: 'title', label: t('문서 제목', 'Document Title'), width: 320 },
    { key: 'owner', label: t('담당자', 'Assignee'), width: 100, align: 'center' },
    { key: 'status', label: t('게시 상태', 'Publish Status'), width: 100, align: 'center' },
    { key: 'updatedAt', label: t('최종 수정일', 'Last Modified Date'), width: 120, align: 'center', sortDisable: true },
  ]);
  const containerRef = React.useRef<HTMLDivElement>(null);
  const { width, height } = useContainerSize(containerRef);
  const selectedArticle = data.find(item => item.values.articleId === selectedRowKey)?.values;

  return (
    <>
      <div data-testid='selected-article' style={{ marginBottom: 10 }}>
        <strong>선택 문서:</strong> {selectedArticle ? `${selectedArticle.articleId}. ${selectedArticle.title}` : t('없음', 'None')}
      </div>
      <DataGridContainer ref={containerRef}>
        <BGrid<KnowledgeArticle>
          width={width}
          height={height}
          headerHeight={35}
          data={data}
          columns={columns}
          rowKey='articleId'
          selectedRowKey={selectedRowKey}
          onChangeColumns={(_columnIndex, { columns }) => setColumns(columns)}
          onClick={({ item }) => setSelectedRowKey(item.articleId)}
        />
      </DataGridContainer>
    </>
  );
}

1. 언제 사용하며 왜 필요한가요?

목록과 상세 영역을 연결할 때처럼 사용자가 클릭한 행을 계속 강조해야 하는 경우 selectedRowKey를 사용합니다. onClick에서 원본 행의 키를 상태로 저장하고, 그 값을 selectedRowKey로 다시 전달하는 제어형 패턴입니다.


2. 실무 완성형 예제: 선택 행 강조 및 상세 뷰어 연동

import React, { useState } from 'react';
import { BGrid, type BGridColumn, type BGridDataItem } from 'beautiful-grid';

interface ArticleItem {
  id: number;
  title: string;
  author: string;
  createdAt: string;
}

export default function FocusGrid() {
  const [selectedKey, setSelectedKey] = useState<string | number>(2);

  const [data] = useState<BGridDataItem<ArticleItem>[]>([
    { values: { id: 1, title: 'BeautifulGrid v1.11 출시 안내', author: '관리자', createdAt: '2026-08-10' } },
    { values: { id: 2, title: '고성능 가상 스크롤 렌더링 최적화 팁', author: '기술팀', createdAt: '2026-08-12' } },
    { values: { id: 3, title: 'React 19 호환성 및 타입스크립트 지원', author: '프론트엔드', createdAt: '2026-08-15' } },
  ]);

  const columns: BGridColumn<ArticleItem>[] = [
    { key: 'id', label: '번호', width: 70, align: 'center' },
    { key: 'title', label: '제목', width: 320 },
    { key: 'author', label: '작성자', width: 100, align: 'center' },
    { key: 'createdAt', label: '등록일', width: 120, align: 'center' },
  ];

  return (
    <div>
      <BGrid<ArticleItem>
        width={650}
        height={220}
        columns={columns}
        data={data}
        rowKey="id"
        selectedRowKey={selectedKey} // 선택된 행의 고유 키 (Active 스타일 적용)
        onClick={({ item }) => {
          setSelectedKey(item.id);
        }}
      />
    </div>
  );
}