๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Dev ๐Ÿ’ป/Front-end

[CSS/JS] ํ‹ฐ์Šคํ† ๋ฆฌ ๋ธ”๋กœ๊ทธ์— ํƒœ๊ทธ ํ•„ํ„ฐ๋ง ๋ฐ ์ˆ˜ํ•™์‹ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ํ•˜๊ธฐ

by GeekSean 2026. 7. 8.
๋ฐ˜์‘ํ˜•

 

๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ๋ฅผ ํ•˜๋‹ค ๋ณด๋‹ˆ, ๊ธ€์ด ์Œ“์ผ ์ˆ˜๋ก ์นดํ…Œ๊ณ ๋ฆฌ๋งŒ์œผ๋กœ๋Š” ๋ถˆํŽธํ•˜๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํŠน์ • ํƒœ๊ทธ(์‚ฌ์šฉ ์–ธ์–ด)๋กœ ๋ฌถ์–ด์„œ ๋ณด๋Š” ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์–ด ๋ณด๋ ค ํ•œ๋‹ค.

 

๋˜ํ•œ, ์ˆ˜ํ•™์‹ ํ‘œ๊ธฐ๋‚˜ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ๋“ฑ์„ ๋งŒ๋“ค์–ด ๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

 

 

ํƒœ๊ทธ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ

 

๋จผ์ € ๊ฒŒ์‹œ๊ธ€์— [Java], [Python]์ฒ˜๋Ÿผ ๋ถ„๋ฅ˜ ํƒœ๊ทธ๋ฅผ ๋‹ฌ๊ณ ,

ํƒœ๊ทธ ํด๋ฆญ ์‹œ, ํ•ด๋‹น ๊ธ€๋งŒ ํ•„ํ„ฐ๋งํ•ด์„œ ๋„์›Œ์ฃผ๋Š” ๊ฑธ ๋ชฉํ‘œ๋กœ ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

 

๋จผ์ € ๋Œ€๋ถ„๋ฅ˜์— ์–ธ์–ด๋ณ„/๊ณต๋ถ€๋ณ„๋กœ ์Šค์œ„์นญ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๊ณ 

function switchTab(type) {
    document.querySelectorAll('.tab-item').forEach(tab => tab.classList.remove('active'));
    document.getElementById('tab-' + type).classList.add('active');
    renderTags(type);
}
 

 

์‚ฌ์šฉํ•  ํƒœ๊ทธ๋“ค๊ณผ, ๋™์ ์œผ๋กœ ํƒœ๊ทธ๋“ค์„ ์ƒ์„ฑ ์‹œํ‚ค๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

const tagGroups = {
    lang: ["CSS", "JS", "React", "Spring", "Python", "C#", "Swift", "AppleScript", "MySQL", "Linux", "OS", "etc"],
    study: ["์ •๋ณด์ฒ˜๋ฆฌ๊ธฐ์‚ฌ", "SQLD", "๋ฆฌ๋ˆ…์Šค๋งˆ์Šคํ„ฐ", "TOEIC", "JLPT"]
};

function renderTags(type) {
    const tagContainer = document.querySelector('.main-tags');
    if (!tagContainer) return;

    tagContainer.innerHTML = tagGroups[type].map(tag => 
        `<button class="tag-btn" onclick="filterByTag('${tag}')">${tag}</button>`
    ).join('');

    updateActiveTagStatus();
}
 

 

์ด์ œ, ํƒœ๊ทธ๋ณ„๋กœ ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€๋งŒ ๊ฒ€์ƒ‰๋˜๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ

๋ณดํ†ต ํ‹ฐ์Šคํ† ๋ฆฌ์—์„œ๋Š” /search/"๊ฒ€์ƒ‰์–ด"๋กœ ๊ฒŒ์‹œ๊ธ€์„ ํ•„ํ„ฐ๋ง ํ•ด ์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

๋”ฐ๋ผ์„œ, ํƒœ๊ทธ๋ฅผ ์„ ํƒ ํ–ˆ์„ ๋•Œ,

์ผ๋ฐ˜ ํƒœ๊ทธ๋Š” ํ‹ฐ์Šคํ† ๋ฆฌ ๋‚ด์žฅ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์ธ /search/ํƒœ๊ทธ๋ช… ์ฃผ์†Œ๋ฅผ ํ™œ์šฉํ•˜๊ณ ,

๋Œ€๊ด„ํ˜ธ๊ฐ€ ์—†๋Š” ๊ธ€๋“ค์„ ๋ชจ์•„๋ณด๋Š” ์˜ˆ์™ธ ์ผ€์ด์Šค์ธ etc๋Š” /category ์ฃผ์†Œ์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ถ™์—ฌ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•ด์ฃผ์—ˆ๋‹ค.

function filterByTag(keyword) {
    if (keyword === 'etc') {
        window.location.href = window.location.origin + "/category?t_filter=etc";
        return;
    }
    window.location.href = window.location.origin + "/search/" + encodeURIComponent(keyword) + "?t_filter=true";
}
 

 

์ด์–ด์„œ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ ๋˜์—ˆ์„ ๋•Œ, t_filter ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ™•์ธํ•˜๊ณ 

๊ธ€ ๋ชฉ๋ก์„ ์‹ค์ œ๋กœ ์†Ž์•„๋‚ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ๋‹ค.

document.addEventListener('DOMContentLoaded', function() {
    ...
    if (filterType) {
        postItems.forEach(item => {
            const titleElement = item.querySelector('.title, .link_post, strong, h3');
            if (!titleElement) return;
            const title = titleElement.innerText.trim();
            
            if (isEtcMode) {
                if (/\[.*?\]/.test(title)) item.remove();
            } else {
                const safeKeyword = currentKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                const regex = new RegExp(`\\[[^\\]]*${safeKeyword}[^\\]]*\\]`, 'i');
                if (!regex.test(title)) item.remove();
            }
        });
        ...
    }
});
 

 

css ์ž‘์—…์€ ํ•„ํ„ฐ ์˜์—ญ๊ณผ, ํƒœ๊ทธ ์˜์—ญ์„ ๊ตฌ์„ฑํ•˜๊ณ 

ํ‹ฐ์Šคํ† ๋ฆฌ์˜ ๋ ˆ์ด์•„์›ƒ ํŠน์„ฑ ๋•Œ๋ฌธ์— UI๊ฐ€ ๋ฐ€๋ฆฌ๋Š”๊ฑธ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, block์œผ๋กœ ๊ณ ์ •

.custom-filter-wrap {
    display: block !important;
    position: relative !important;
    visibility: visible !important;
    opacity: 1 !important;
    transform: none !important;
    margin: 20px 0 !important;
    z-index: 100;
    text-align: center;
}

.filter-tag-list {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 8px !important; 
    justify-content: center !important;
    width: 100% !important;
}
 

 

์–ธ์–ด๋ณ„, ๊ณต๋ถ€๋ณ„ ์นดํ…Œ๊ณ ๋ฆฌ ์ „ํ™˜์„ ์œ„ํ•œ ๋””์ž์ธ ๋ถ€๋ถ„๋„ ๊ตฌํ˜„

.tab-item {
    cursor: pointer;
    transition: all 0.2s ease;
    opacity: 0.4; 
}

.tab-item.active {
    opacity: 1;
    color: #555 !important;
}

.tab-divider {
    font-weight: normal;
    color: #444;
    font-size: 0.8em;
    opacity: 0.5;
}
 

 

๊ทธ ์™ธ์— ๋ฒ„ํŠผ ๋””์ž์ธ๊ณผ ๋‹คํฌ๋ชจ๋“œ ๋Œ€์‘ ์ž‘์—…๊นŒ์ง€ ์™„๋ฃŒํ•˜๋ฉด ์ž‘์—…์€ ๋์ด๋‹ค.

 

ํƒœ๊ทธ ์œ„์น˜๋Š” ์ธ๊ธฐ ๊ธ€ ์œ„์— ๋ฐฐ์น˜ ํ–ˆ๊ณ ,

๋ฏธ๋ฆฌ ๋งŒ๋“  ํƒœ๊ทธ ๋ฆฌ์ŠคํŠธ์— ๋งž๊ฒŒ ์ •๋ ฌ๋˜์–ด ๋ฐฐ์น˜ ๋๋‹ค.

 

Spring ํƒœ๊ทธ๋ฅผ ๋ˆ„๋ฅด๋ฉด, ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€๋“ค ํ•„ํ„ฐ๋ง๊ณผ,

ํƒ€์ดํ‹€์— ๋Œ€๊ด„ํ˜ธ ํƒœ๊ทธ๊ฐ€ ์—†์„ ๋•Œ ๋‚˜์˜ค๋Š” ๊ฒŒ์‹œ๊ธ€์€ ์ž๋™ ํ•„ํ„ฐ๋งํ•ด์„œ ์•ˆ๋ณด์ด๊ฒŒ ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

 

 

์ˆ˜ํ•™์‹ ํ‘œ๊ธฐ ๊ธฐ๋Šฅ

 

์ด์ œ ๊ฐ„ํ˜น, ์ด๋ก  ์„ค๋ช…์—์„œ ์ˆ˜ํ•™์‹์ด ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ๋Š”๋ฐ

์ˆ˜ํ•™์‹์„ ๊ทธ๋Œ€๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์ด๋Ÿฐ์‹์œผ๋กœ ์•Œ์•„๋ณด๊ธฐ ํž˜๋“ค๊ฒŒ ๋‚˜์˜จ๋‹ค.

 

๋”ฐ๋ผ์„œ, MathJax๋ผ๋Š” ์ˆ˜ํ•™์‹ ๋ Œ๋”๋ง ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•  ๊ฒƒ์ธ๋ฐ.

$์‚ฌ์ธ์œผ๋กœ ์ˆ˜์‹์„ ๊ฐ์‹ธ๋ฉด ์ˆ˜ํ•™ ๊ณต์‹์œผ๋กœ ๋ณ€ํ™˜

์ถฉ๋Œ์‹œ ์„œ๋ธŒ๊ทœ์น™์€ ((์ˆ˜์‹))์œผ๋กœ ์ง€์ •ํ–ˆ๋‹ค.

<script type="text/x-mathjax-config">
   MathJax.Hub.Config({ 
       tex2jax: {
           inlineMath: [['$','$'], ['\((','\))']]
       } 
   });  
</script>
 

 

์ด์ œ ์ˆ˜ํ•™์‹ ๋ถ„์„ ๋ฐ ๊ฐ€์‹œํ™” ์—ฐ์‚ฐ์„ ์ง์ ‘ ์—…๋กœ๋“œ ํ•˜๊ธฐ์—” ๋ฌด๊ฑฐ์šฐ๋ฏ€๋กœ

CDN์„ ์ด์šฉํ•ด์„œ ์ฒ˜๋ฆฌ ํ–ˆ๋‹ค.

<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML"></script>
 

 

์ด์˜๊ฒŒ ์ˆ˜์‹์œผ๋กœ ๋‚˜์˜ค๋Š” ๋ชจ์Šต

 

 

๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ

 

์ถ”๊ฐ€๋กœ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๋ฉด์„œ ํ•„์š”ํ•œ ๊ฒƒ์ด ์ƒ๊ฐ๋‚ฌ๋Š”๋ฐ

๊ฒŒ์‹œ๊ธ€๋งˆ๋‹ค, ์‹œ๋ฆฌ์ฆˆ ๋งํฌ๋ฅผ ์ƒ๋‹จ์— ๋‹ค๋‹ˆ๊นŒ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ๋งํฌ๋กœ ๋‹ค ๊ฐ€๋ ค์ง€๊ณ  ์žˆ์—ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ๋งํฌ ๋ถ€๋ถ„์„ ์ œ๊ฑฐ ํ•  ํ•„ํ„ฐ๋ง์„ ๋งŒ๋“ค์–ด ๋ณด๋„๋ก ํ•˜์ž.

 

๋Œ€์ƒ ํƒ€๊ฒŸํŒ…์„ ํ•˜๊ณ , ์ •๊ทœํ‘œํ˜„์‹์„ ์ด์šฉํ•ด [ํƒœ๊ทธ]-์‹œ๋ฆฌ์ฆˆ๋ช…-ํšŒ์ฐจ๋ฒˆํ˜ธ ํ˜•ํƒœ๋กœ ๋งค์นญ

๊ทธ๋ฆฌ๊ณ  ๋งค์นญ๋œ ํ…์ŠคํŠธ๋ฅผ ์ •์ œํ•˜์—ฌ ๋ณด์ด์ง€ ์•Š๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ํ–ˆ๋‹ค.

document.addEventListener('DOMContentLoaded', function() {
    const postItems = document.querySelectorAll('.post-item, .article-list li, .list-row, .cover-thumbnail-2 li');
    
    postItems.forEach(item => {
        const excerptElement = item.querySelector('.excerpt');
        
        if (excerptElement) {
            let text = excerptElement.innerText;
            const pattern = /\[.*?\]\s*-\s*.*?\s*-\s*\d+/g;
            let cleanedText = text.replace(pattern, '').trim();
            
            if (cleanedText.length > 0) {
                excerptElement.innerText = cleanedText;
            }
        }
    });
});
 

 

์ด์ œ ๋ถˆํ•„์š”ํ•œ ๋งํฌ๋„ ์•ˆ๋ณด์ด๊ฒŒ ๋˜์—ˆ๋‹ค.

 

์ด๋กœ์จ, ํ•„์š”ํ•œ ์ž‘์—…์€ ๋ชจ๋‘ ๋๋‚ฌ๋‹ค.

๋‹น๋ถ„๊ฐ„์€ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์€ ํ•„์š” ์—†์–ด ๋ณด์—ฌ์„œ ์ด๋Œ€๋กœ ์˜ค๋ž˜ ์œ ์ง€ํ•˜์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค.

 

 

์›๋ณธ ๊ฒŒ์‹œ๊ธ€

https://blog.naver.com/101artspace/224338628914

 

[CSS/JS] ํ‹ฐ์Šคํ† ๋ฆฌ ๋ธ”๋กœ๊ทธ์— ํƒœ๊ทธ ํ•„ํ„ฐ๋ง ๋ฐ ์ˆ˜ํ•™์‹ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ํ•˜๊ธฐ

๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ๋ฅผ ํ•˜๋‹ค ๋ณด๋‹ˆ, ๊ธ€์ด ์Œ“์ผ ์ˆ˜๋ก ์นดํ…Œ๊ณ ๋ฆฌ๋งŒ์œผ๋กœ๋Š” ๋ถˆํŽธํ•˜๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŠน์ • ํƒœ๊ทธ(...

blog.naver.com

๋ฐ˜์‘ํ˜•