CLIEN

본문 바로가기 메뉴 바로가기 보기설정 테마설정
톺아보기 공감글
커뮤니티 커뮤니티전체 C 모두의광장 F 모두의공원 I 사진게시판 Q 아무거나질문 D 정보와자료 N 새로운소식 T 유용한사이트 P 자료실 E 강좌/사용기 L 팁과강좌 U 사용기 · 체험단사용기 W 사고팔고 J 알뜰구매 S 회원중고장터 B 직접홍보 · 보험상담실 H 클리앙홈
소모임 소모임전체 ·굴러간당 ·아이포니앙 ·MaClien ·일본산당 ·주식한당 ·자전거당 ·개발한당 ·야구당 ·안드로메당 ·소시당 ·테스트당 ·노젓는당 ·나스당 ·이륜차당 ·AI당 ·방탄소년당 ·바다건너당 ·가상화폐당 ·VR당 ·디아블로당 ·전기자전거당 ·캠핑간당 ·e북본당 ·WOW당 ·골프당 ·사과시계당 ·레고당 ·콘솔한당 ·꼬들한당 ·리눅서당 ·시계찬당 ·육아당 ·소리당 ·보드게임당 ·위스키당 ·활자중독당 ·3D메이킹 ·X세대당 ·ADHD당 ·AI그림당 ·날아간당 ·배드민턴당 ·농구당 ·블랙베리당 ·곰돌이당 ·비어있당 ·FM당구당 ·블록체인당 ·볼링친당 ·냐옹이당 ·문명하셨당 ·클래시앙 ·클다방 ·요리한당 ·쿠키런당 ·대구당 ·DANGER당 ·뚝딱뚝당 ·개판이당 ·동숲한당 ·날아올랑 ·갖고다닌당 ·이브한당 ·패셔니앙 ·물고기당 ·도시어부당 ·FM한당 ·맛있겠당 ·포뮬러당 ·젬워한당 ·걸그룹당 ·안경쓴당 ·차턴당 ·총쏜당 ·땀흘린당 ·하스스톤한당 ·히어로즈한당 ·인스타한당 ·IoT당 ·KARA당 ·키보드당 ·덕질한당 ·어학당 ·가죽당 ·LOLien ·Mabinogien ·임시소모임 ·미드당 ·밀리터리당 ·땅판당 ·헌팅한당 ·오른당 ·영화본당 ·MTG한당 ·노키앙 ·적는당 ·방송한당 ·PC튜닝한당 ·찰칵찍당 ·그림그린당 ·소풍간당 ·심는당 ·패스오브엑자일당 ·라즈베리파이당 ·품앱이당 ·리듬탄당 ·달린당 ·Sea마당 ·SimSim하당 ·심야식당 ·윈태블릿당 ·미끄러진당 ·축구당 ·나혼자산당 ·스타한당 ·스팀한당 ·파도탄당 ·퐁당퐁당 ·테니스친당 ·빨콩이당 ·공대시계당 ·여행을떠난당 ·터치패드당 ·트윗당 ·창업한당 ·WebOs당 ·소셜게임한당 ·와인마신당 ·윈폰이당
임시소모임
고객지원
  • 게시물 삭제 요청
  • 불법촬영물등 신고
  • 쪽지 신고
  • 닉네임 신고
  • 제보 및 기타 제안
© CLIEN.NET
공지[점검] 잠시후 서비스 점검을 위해 약 30분간 접속이 차단됩니다. (금일 18:15 ~ 18:45)

MaClien

맥당이야기 (Userscript) 유튜브 메인페이지 UI를 게시판처럼

2026-09-30 03:15:57 수정일 : 2026-09-30 03:18:00 172.♡.94.40
보리쨩

0930-03.16.46.Safari.jpg


자극적인 썸네일로 피로했는데 나름 괜찮네요. 무의미한 영상시청이 줄었고요.

취향에 맞게 커스텀한거라 필요하신분은 스크립트 전체 ai에 복붙해서 세부규칙 조정해서 사용하시면 됩니다


// ==UserScript==

// @name         YouTube Focus UI - Minimal

// @namespace    local.youtube.focus.ui

// @version      12.3.0

// @description  YouTube 홈 피드를 조회수 기준의 한 줄 목록으로 정리합니다.

// @match        https://www.youtube.com/*

// @match        https://m.youtube.com/*

// @run-at       document-start

// @grant        none

// ==/UserScript==


/*

 * 작동 규칙

 *

 * 1. 조회수 10,000회 미만 영상은 화면에서 숨긴다.

 * 2. 쇼츠, 재생목록, 믹스, 라이브 영상은 처리하지 않는다.

 * 3. 일반 영상은 썸네일을 숨기고 제목·게시 시점·채널명만 표시한다.

 * 4. 조회수 증가 속도·누적 조회수·영상 길이·최신성을 이용해 상대 중요도를 계산한다.

 * 5. 중요도가 높은 영상은 제목을 굵게 표시한다.

 * 6. 중요도가 낮은 영상은 제목을 조금 흐리게 표시한다.

 * 7. 새 영상이 추가되거나 YouTube 페이지를 이동하면 자동으로 다시 적용한다.

 * 8. 영상 정보가 늦게 표시되면 잠시 기다렸다가 다시 확인한다.

 */


(() => {

  'use strict';


  const ROOT_CLASS = 'yt-focus-minimal';

  const DONE_ATTR = 'data-yt-focus-done';

  const RETRY_ATTR = 'data-yt-focus-retries';


  const CONFIG = Object.freeze({

    MIN_VIEWS: 10000,

    MIN_AGE_FOR_VELOCITY_HOURS: 1,

    AGE_HALF_LIFE_DAYS: 21,


    VELOCITY_WEIGHT: 0.42,

    VIEW_WEIGHT: 0.28,

    LENGTH_WEIGHT: 0.10,

    FRESHNESS_WEIGHT: 0.20,


    TOP_TIER: 0.95,

    IMPORTANT_TIER: 0.80,

    LOW_TIER: 0.20,

    VERY_LOW_TIER: 0.05,


    BASE_WEIGHT: 360,

    IMPORTANT_WEIGHT: 470,

    TOP_WEIGHT: 590,

    LOW_OPACITY: 0.78,

    VERY_LOW_OPACITY: 0.50,


    RETRY_DELAY_MS: 500,

    MAX_RETRIES: 12,

    ROW_HEIGHT: 36

  });


  const CARD_SELECTOR = [

    'ytd-rich-grid-renderer ytd-rich-item-renderer',

    'ytd-rich-grid-renderer ytd-video-renderer',

    'ytd-rich-grid-renderer ytd-grid-video-renderer'

  ].join(',');


  const TITLE_SELECTOR = [

    'a#video-title',

    'a#video-title-link',

    'h3 a',

    'yt-lockup-metadata-view-model a'

  ].join(',');


  const CHANNEL_SELECTOR = [

    'ytd-channel-name a',

    '#channel-name a',

    'yt-content-metadata-view-model a[href^="/@"]'

  ].join(',');


  const AGE_SELECTOR = [

    '#metadata-line span',

    '.inline-metadata-item',

    'yt-content-metadata-view-model span'

  ].join(',');


  const css = `

    html.${ROOT_CLASS} {

      --yt-focus-text: #f1f1f1;

      --yt-focus-muted: #8b8b8b;

      --yt-focus-line: rgba(255,255,255,.085);

      --yt-focus-accent: #f1f1f1;

    }


    html.${ROOT_CLASS} ytd-rich-grid-renderer {

      --ytd-rich-grid-items-per-row: 1*;

      --ytd-rich-grid-posts-per-row: 1*;

      --ytd-rich-grid-row-margin: 0*;

    }


    html.${ROOT_CLASS} ytd-rich-grid-renderer ytd-rich-item-renderer,

    html.${ROOT_CLASS} ytd-rich-grid-renderer ytd-video-renderer,

    html.${ROOT_CLASS} ytd-rich-grid-renderer ytd-grid-video-renderer {

      display: block*;

      width: 100%*;

      max-width: none*;

      height: ${CONFIG.ROW_HEIGHT}px*;

      min-height: ${CONFIG.ROW_HEIGHT}px*;

      max-height: ${CONFIG.ROW_HEIGHT}px*;

      margin: 0*;

      padding: 0*;

      overflow: hidden*;

    }


    html.${ROOT_CLASS} .yt-focus-filtered {

      display: none*;

    }


    html.${ROOT_CLASS} ytd-thumbnail,

    html.${ROOT_CLASS} yt-thumbnail-view-model,

    html.${ROOT_CLASS} .yt-thumbnail-container {

      display: none*;

    }


    html.${ROOT_CLASS} .yt-focus-row {

      display: grid*;

      grid-template-columns: minmax(0, 1fr) 70px minmax(90px, .20fr)*;

      align-items: center*;

      width: 100%*;

      height: ${CONFIG.ROW_HEIGHT}px*;

      box-sizing: border-box*;

      padding: 8px 12px*;

      border-bottom: 1px solid var(--yt-focus-line)*;

      font-size: 13px*;

      line-height: 20px*;

      transition: background .18s ease*;

    }


    html.${ROOT_CLASS} .yt-focus-row:hover {

      background: rgba(255,255,255,.055)*;

    }


    html.${ROOT_CLASS} .yt-focus-title {

      grid-column: 1*;

      min-width: 0*;

      height: 20px*;

      overflow: hidden*;

      color: var(--yt-focus-text)*;

      white-space: nowrap*;

      text-overflow: ellipsis*;

      font-size: 13px*;

      line-height: 20px*;

      font-weight: var(--yt-focus-weight, ${CONFIG.BASE_WEIGHT})*;

      letter-spacing: -.012em*;

      opacity: var(--yt-focus-opacity, 1)*;

      transition: font-weight .3s ease, opacity .3s ease*;

    }


    html.${ROOT_CLASS} .yt-focus-title a {

      color: inherit*;

      text-decoration: none*;

    }


    html.${ROOT_CLASS} .yt-focus-age {

      grid-column: 2*;

      width: 70px*;

      height: 20px*;

      box-sizing: border-box*;

      overflow: hidden*;

      padding-right: 10px*;

      color: var(--yt-focus-muted)*;

      white-space: nowrap*;

      text-overflow: ellipsis*;

      text-align: right*;

      font-size: 11px*;

      line-height: 20px*;

      opacity: .66*;

    }


    html.${ROOT_CLASS} .yt-focus-today {

      color: var(--yt-focus-accent)*;

      opacity: .94*;

    }


    html.${ROOT_CLASS} .yt-focus-channel {

      grid-column: 3*;

      min-width: 0*;

      height: 20px*;

      overflow: hidden*;

      padding-left: 10px*;

      color: var(--yt-focus-muted)*;

      white-space: nowrap*;

      text-overflow: ellipsis*;

      font-size: 11px*;

      line-height: 20px*;

      opacity: .62*;

    }


    html.${ROOT_CLASS} .yt-focus-channel a {

      color: inherit*;

      text-decoration: none*;

    }

  `;


  const style = document.createElement('style');

  style.textContent = css;

  document.documentElement.appendChild(style);

  document.documentElement.classList.add(ROOT_CLASS);


  const cleanText = value =>

    String(value || '').replace(/\s+/g, ' ').trim();


  const clamp01 = value =>

    Math.max(0, Math.min(1, value));


  const removeDubText = value =>

    cleanText(value)

      .replace(/자동\s*더빙/gi, '')

      .replace(/auto[-\s]?dubbed/gi, '')

      .trim();


  function percentile(values, value) {

    const sorted = values

      .filter(Number.isFinite)

      .slice()

      .sort((a, b) => a - b);


    if (sorted.length < 2) return 0.5;


    let low = 0;

    let high = sorted.length;


    while (low < high) {

      const middle = (low + high) >> 1;

      if (sorted[middle] <= value) low = middle + 1;

      else high = middle;

    }


    return clamp01((low - 1) / (sorted.length - 1));

  }


  function parseViews(raw) {

    const value = cleanText(raw)

      .replace(/조회수/g, '')

      .replace(/views?/gi, '')

      .replace(/,/g, '');


    if (!value) return null;


    const match = value.match(/([\d.]+)\s*(억|만|천|[KMB])/i);


    if (match) {

      const number = parseFloat(match[1]);

      const unit = match[2].toLowerCase();

      const factor = {

        억: 1e8,

        만: 1e4,

        천: 1e3,

        k: 1e3,

        m: 1e6,

        b: 1e9

      }[unit];


      return Number.isFinite(number) && factor

        ? Math.round(number * factor)

        : null;

    }


    const number = parseFloat(value.match(/[\d.]+/)?.[0]);

    return Number.isFinite(number) ? Math.round(number) : null;

  }


  function parseDuration(raw) {

    const value = cleanText(raw).replace(/,/g, '');


    let match = value.match(/^(?:(\d+):)?(\d{1,2}):(\d{2})$/);


    if (match) {

      return (

        (match[1] ? Number(match[1]) * 3600 : 0) +

        Number(match[2]) * 60 +

        Number(match[3])

      );

    }


    match = value.match(

      /(?:(\d+)\s*시간)?\s*(?:(\d+)\s*분)?\s*(?:(\d+)\s*초)?/

    );


    return match && (match[1] || match[2] || match[3])

      ? (Number(match[1]) || 0) * 3600 +

        (Number(match[2]) || 0) * 60 +

        (Number(match[3]) || 0)

      : null;

  }


  function getDuration(card) {

    const selector = [

      '#text.ytd-thumbnail-overlay-time-status-renderer',

      'ytd-thumbnail-overlay-time-status-renderer span',

      'badge-shape .yt-badge-shape__text',

      '[aria-label*="분"]',

      '[aria-label*="시간"]',

      '[aria-label*="minute"]',

      '[aria-label*="hour"]'

    ].join(',');


    for (const node of card.querySelectorAll(selector)) {

      for (const candidate of [

        node.textContent,

        node.getAttribute('aria-label'),

        node.getAttribute('title')

      ]) {

        const duration = parseDuration(candidate);

        if (duration !== null) return duration;

      }

    }


    return null;

  }


  function parseAge(raw) {

    const value = cleanText(raw)

      .replace(/게시됨/g, '')

      .replace(/전$/g, '')

      .trim();


    if (!value) return null;


    const short =

      value.match(/(\d+)\s*(초|분|시간)\s*전?$/) ||

      value.match(

        /\b(\d+)\s*(second|seconds|sec|secs|minute|minutes|min|mins|hour|hours|hr|hrs)\b/i

      );


    if (short) {

      const number = Number(short[1]);

      const unit = short[2].toLowerCase();


      const hours =

        unit === '시간' || unit.startsWith('hour') || unit.startsWith('hr')

          ? number

          : unit === '분' || unit.startsWith('min')

            ? number / 60

            : number / 3600;


      return {

        label: '오늘',

        days: hours / 24,

        hours,

        isToday: true

      };

    }


    const patterns = [

      [/([\d]+)\s*일/, 1, '일'],

      [/([\d]+)\s*주/, 7, '주'],

      [/([\d]+)\s*(?:개월|달)/, 30.4375, '달'],

      [/([\d]+)\s*년/, 365.25, '년'],

      [/([\d]+)\s*d\b/i, 1, '일'],

      [/([\d]+)\s*w\b/i, 7, '주'],

      [/([\d]+)\s*mo\b/i, 30.4375, '달'],

      [/([\d]+)\s*y\b/i, 365.25, '년']

    ];


    for (const [regex, multiplier, unit] of patterns) {

      const match = value.match(regex);

      if (!match) continue;


      const number = Number(match[1]);

      const days = number * multiplier;


      return {

        label: number === 1 && unit === '일'

          ? '어제'

          : `${number}${unit}`,

        days,

        hours: days * 24,

        isToday: false

      };

    }


    return null;

  }


  function getAgeSource(card) {

    for (const node of card.querySelectorAll(AGE_SELECTOR)) {

      const age = parseAge(node.textContent);

      if (age) return { age };

    }


    return { age: null };

  }


  function getVideoType(card) {

    if (card.querySelector('a[href*="/shorts/"]')) return null;


    for (const link of card.querySelectorAll('a[href]')) {

      const href = link.getAttribute('href') || '';


      if (

        href.includes('/playlist?') ||

        href.includes('?list=') ||

        href.includes('&list=')

      ) {

        return null;

      }


      if (href.includes('/watch?')) {

        try {

          const url = new URL(href, location.origin);


          if (

            url.pathname === '/watch' &&

            url.searchParams.has('v')

          ) {

            return 'video';

          }

        } catch {}

      }

    }


    return null;

  }


  function isLiveVideo(card) {

    if (card.querySelector(

      '[overlay-style="LIVE"], [overlay-style="live"], [is-live-video]'

    )) {

      return true;

    }


    return Array.from(card.querySelectorAll('[aria-label], [title]'))

      .some(node => {

        const value = cleanText([

          node.getAttribute('aria-label'),

          node.getAttribute('title')

        ].filter(Boolean).join(' '));


        return /\b(LIVE|라이브|생방송)\b/i.test(value);

      });

  }


  function getTitle(card) {

    const source = card.querySelector(TITLE_SELECTOR);


    return {

      text: removeDubText(source?.textContent || ''),

      href: source?.href || ''

    };

  }


  function getChannel(card) {

    const source = card.querySelector(CHANNEL_SELECTOR);


    if (source) {

      return {

        text: removeDubText(source.textContent),

        href: source.href || ''

      };

    }


    const fallback = card.querySelector('ytd-channel-name, #channel-name');


    return {

      text: removeDubText(fallback?.textContent || ''),

      href: ''

    };

  }


  function createCell(className, text = '') {

    const element = document.createElement('div');

    element.className = className;

    element.textContent = text;

    return element;

  }


  function createTitleElement(title) {

    const element = createCell('yt-focus-title');


    if (title.href) {

      const link = document.createElement('a');

      link.href = title.href;

      link.textContent = title.text;

      element.appendChild(link);

    } else {

      element.textContent = title.text;

    }


    return element;

  }


  function createChannelElement(channel) {

    const element = createCell('yt-focus-channel');


    if (channel.href) {

      const link = document.createElement('a');

      link.href = channel.href;

      link.textContent = channel.text;

      element.appendChild(link);

    } else {

      element.textContent = channel.text;

    }


    return element;

  }


  function getLengthSignal(seconds) {

    if (seconds === null) return 0.5;


    const minutes = seconds / 60;

    return clamp01(

      0.20 + 0.80 * (1 - Math.exp(-minutes / 10))

    );

  }


  function getSignals(views, age, duration) {

    const days = Math.max(

      age.days,

      CONFIG.MIN_AGE_FOR_VELOCITY_HOURS / 24

    );


    const viewsPerDay = views / days;


    return {

      velocity: Math.log1p(viewsPerDay),

      views: Math.log1p(views),

      freshness: Math.exp(-age.days / CONFIG.AGE_HALF_LIFE_DAYS),

      length: getLengthSignal(duration)

    };

  }


  function recalculate() {

    const rows = Array.from(

      document.querySelectorAll('.yt-focus-row[data-analyzed]')

    );


    if (!rows.length) return;


    const data = rows.map(row => ({

      row,

      velocity: Number(row.dataset.velocity),

      views: Number(row.dataset.viewsLog),

      freshness: Number(row.dataset.freshness),

      length: Number(row.dataset.length)

    }));


    const velocityValues = data.map(item => item.velocity);

    const viewValues = data.map(item => item.views);

    const freshnessValues = data.map(item => item.freshness);

    const lengthValues = data.map(item => item.length);


    const scores = data.map(item => {

      const score =

        CONFIG.VELOCITY_WEIGHT * percentile(velocityValues, item.velocity) +

        CONFIG.VIEW_WEIGHT * percentile(viewValues, item.views) +

        CONFIG.LENGTH_WEIGHT * percentile(lengthValues, item.length) +

        CONFIG.FRESHNESS_WEIGHT * percentile(freshnessValues, item.freshness);


      item.score = score;

      return score;

    });


    for (const item of data) {

      const p = percentile(scores, item.score);


      let weight = CONFIG.BASE_WEIGHT;

      let opacity = 1;


      if (p >= CONFIG.TOP_TIER) {

        const t = clamp01(

          (p - CONFIG.TOP_TIER) / (1 - CONFIG.TOP_TIER)

        );


        weight =

          CONFIG.IMPORTANT_WEIGHT +

          (CONFIG.TOP_WEIGHT - CONFIG.IMPORTANT_WEIGHT) * t;

      } else if (p >= CONFIG.IMPORTANT_TIER) {

        const t = clamp01(

          (p - CONFIG.IMPORTANT_TIER) /

          (CONFIG.TOP_TIER - CONFIG.IMPORTANT_TIER)

        );


        weight =

          CONFIG.BASE_WEIGHT +

          (CONFIG.IMPORTANT_WEIGHT - CONFIG.BASE_WEIGHT) * t;

      } else if (p < CONFIG.VERY_LOW_TIER) {

        const t = clamp01(p / CONFIG.VERY_LOW_TIER);


        opacity =

          CONFIG.VERY_LOW_OPACITY +

          (CONFIG.LOW_OPACITY - CONFIG.VERY_LOW_OPACITY) * t;

      } else if (p < CONFIG.LOW_TIER) {

        const t = clamp01(

          (p - CONFIG.VERY_LOW_TIER) /

          (CONFIG.LOW_TIER - CONFIG.VERY_LOW_TIER)

        );


        opacity =

          CONFIG.LOW_OPACITY +

          (1 - CONFIG.LOW_OPACITY) * t;

      }


      item.row.style.setProperty(

        '--yt-focus-weight',

        String(Math.round(weight))

      );


      item.row.style.setProperty(

        '--yt-focus-opacity',

        opacity.toFixed(3)

      );

    }

  }


  function render(card, title, age, channel, signals) {

    let row = card.querySelector('.yt-focus-row');


    if (!row) {

      row = document.createElement('div');

      row.className = 'yt-focus-row';

      card.prepend(row);

    }


    row.dataset.analyzed = '1';

    row.dataset.velocity = signals.velocity;

    row.dataset.viewsLog = signals.views;

    row.dataset.freshness = signals.freshness;

    row.dataset.length = signals.length;


    const ageElement = createCell('yt-focus-age', age.label);


    if (age.isToday) {

      ageElement.classList.add('yt-focus-today');

    }


    row.replaceChildren(

      createTitleElement(title),

      ageElement,

      createChannelElement(channel)

    );

  }


  function finish(card) {

    card.setAttribute(DONE_ATTR, '1');

  }


  function classify(card) {

    if (!card || card.getAttribute(DONE_ATTR) === '1') return;


    if (getVideoType(card) === null || isLiveVideo(card)) {

      finish(card);

      return;

    }


    const views = parseViews(card.textContent);

    const age = getAgeSource(card).age;


    if (views === null || age === null) {

      const retries = Number(

        card.getAttribute(RETRY_ATTR) || 0

      );


      if (retries < CONFIG.MAX_RETRIES) {

        card.setAttribute(

          RETRY_ATTR,

          String(retries + 1)

        );


        window.setTimeout(() => classify(card), CONFIG.RETRY_DELAY_MS);

      }


      return;

    }


    if (views < CONFIG.MIN_VIEWS) {

      card.classList.add('yt-focus-filtered');

      finish(card);

      return;

    }


    finish(card);


    render(

      card,

      getTitle(card),

      age,

      getChannel(card),

      getSignals(views, age, getDuration(card))

    );

  }


  function scan(root = document) {

    if (

      root.nodeType === Node.ELEMENT_NODE &&

      root.matches?.(CARD_SELECTOR)

    ) {

      classify(root);

    }


    root.querySelectorAll?.(CARD_SELECTOR)

      .forEach(classify);

  }


  let queued = false;


  function queueScan(delay = 0) {

    if (queued) return;


    queued = true;


    const run = () => {

      queued = false;

      scan(document);

      recalculate();

    };


    if (delay > 0) {

      window.setTimeout(run, delay);

    } else {

      requestAnimationFrame(run);

    }

  }


  const observer = new MutationObserver(mutations => {

    if (mutations.some(

      mutation =>

        mutation.type === 'childList' &&

        mutation.addedNodes.length

    )) {

      queueScan();

    }

  });


  function start() {

    scan(document);

    recalculate();


    observer.observe(document.documentElement, {

      childList: true,

      subtree: true

    });

  }


  window.addEventListener(

    'yt-navigate-finish',

    () => queueScan(220)

  );


  window.addEventListener(

    'popstate',

    () => queueScan(320)

  );


  if (document.readyState === 'loading') {

    document.addEventListener('DOMContentLoaded', start, {

      once: true

    });

  } else {

    start();

  }

})();





보리쨩 님의 게시글 댓글
  • 주소복사
  • Facebook
  • X(Twitter)
댓글 • [0]
새로운 댓글이 없습니다.
이미지 최대 업로드 용량 15 MB / 업로드 가능 확장자 jpg,gif,png,jpeg,webp
지나치게 큰 이미지의 크기는 조정될 수 있습니다.
목록으로
글쓰기
글쓰기
목록으로 댓글보기 이전글 다음글
아이디  ·  비밀번호 찾기 회원가입
이용규칙 운영알림판 운영소통 재검토요청 도움말 버그신고
개인정보처리방침 이용약관 책임의 한계와 법적고지 청소년 보호정책
©   •  CLIEN.NET
보안 강화를 위한 이메일 인증
안전한 서비스 이용을 위해 이메일 인증을 완료해 주세요. 현재 회원님은 이메일 인증이 완료되지 않은 상태입니다.
최근 급증하는 해킹 및 도용 시도로부터 계정을 보호하기 위해 인증 절차가 강화되었습니다.

  • 이메일 미인증 시 글쓰기, 댓글 작성 등 게시판 활동이 제한됩니다.
  • 이후 새로운 기기에서 로그인할 때마다 반드시 이메일 인증을 거쳐야 합니다.
  • 2단계 인증 사용 회원도 최초 1회는 반드시 인증하여야 합니다.
  • 개인정보에서도 이메일 인증을 할 수 있습니다.
지금 이메일 인증하기
등록된 이메일 주소를 확인하고 인증번호를 입력하여
인증을 완료해 주세요.