๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป ํ”„๋กœ์ ํŠธ/๐Ÿ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๐Ÿ 

[Vue.js] ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ, localStorage๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์•„์ด๋””๊ฐ€ ๋ฉ”์ธํ™”๋ฉด์— ๋ณด์ด๋„๋ก ์„ค์ •ํ•˜๊ธฐ!

by ._.sori 2025. 9. 2.

 

 

๋กœ๊ทธ์ธ๊นŒ์ง€ ๋งŒ๋“ค์—ˆ๋‹ค.
์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ•˜๊ฒŒ๋˜๋ฉด
๋ฉ”์ธํ™”๋ฉด์— ์‚ฌ์šฉ์ž ์•„์ด๋””๊ฐ€ ๋ณด์ด๋„๋ก
์„ค์ •ํ•ด๋ณด์ž!

 

 

 

 

[ ๋กœ๊ทธ์ธ ๋งŒ๋“ค๊ธฐ ]

๋ธ”๋กœ๊ทธ์— ์ ์—ˆ๋˜ vue์ฝ”๋“œ๊ฐ€ ์กฐ๊ธˆ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค

 

[SpringBoot, Vue.js] ๋กœ๊ทธ์ธ ํ™”๋ฉด ๋งŒ๋“ค๊ธฐ, passwordEncoder.matches๋ฅผ ํ†ตํ•ด ์•”ํ˜ธํ™”๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋น„๊ตํ•˜๊ธฐ.

ํšŒ์›๊ฐ€์ž…๊นŒ์ง€ ๋งŒ๋“ค์—ˆ๋‹ค.์ด์ œ ํšŒ์›๊ฐ€์ž…ํ•œ ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ๋กœ๊ทธ์ธ์„ ํ•ด๋ณด์ž! [ ํšŒ์›๊ฐ€์ž… 1ํŽธ + 2ํŽธ ] [SpringBoot] (IntelliJ, vue.js, H2) ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ 1ํŽธ : dto ๋งŒ๋“ค๊ณ  ์ด๋ฆ„, ํŒจ์Šค์›Œ๋“œ, ์ „ํ™”

post-this.tistory.com

 

 

 

โ€ป

์ด ์ฝ”๋“œ๋Š” ๊ทธ๋ƒฅ ์—ฐ์Šต์šฉ์œผ๋กœ ๊ฒ‰๋ชจ์Šต๋งŒ ๋กœ๊ทธ์ธ ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ๋งŒ๋“  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ์‹ค์ œ๋กœ ๋กœ๊ทธ์ธ๋œ ํ™”๋ฉด์ด๋ผ๊ณ  ๋ณด๊ธด ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์ œ๋Œ€๋กœ๋œ ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด,

์Šคํ”„๋ง์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜๋ฉฐ ํ† ํฐ ํ˜น์€ ์„ธ์…˜์„ ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ฑธ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

 

 


 

 

 

1. ํ™”๋ฉด ๋™์ž‘๊ณผ ์ „์ฒด ์ฝ”๋“œ

  • ํ™”๋ฉด ๋™์ž‘

 

 

 

  • ์ฝ”๋“œ๋Š” ๋‹ค๋ฅธ ๋ถ€๋ถ„ ๋•Œ๋ฌธ์— ์ˆ˜์ • ์ค‘์ด๋ผ ํ›„์— ์™„์„ฑ๋˜๋ฉด ์˜ฌ๋ฆฌ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

 


 

 

 

 

2. ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค๊นŒ?

  • ๋ฉ”์ธํ™”๋ฉด

 

์ฒ˜์Œ์— ๊ตฌ์ƒํ–ˆ๋˜ ๊ฒƒ์€ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กญ๊ฒŒ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ ๋กœ๊ทธ์ธ์ด ๋˜๋ฉด ํ•ด๋‹น ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ€๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์ž์›์„ ๋” ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ ๊ฐ™์•„ ํ›„์— ์ˆ˜์ •ํ–ˆ๋‹ค. (๋งŒ์•ฝ ๋ฉ”์ธ ํŽ˜์ด์ง€์— ๊ฒŒ์‹œ๊ธ€์ด ๋ณด์ด๋„๋ก ๋˜์–ด์žˆ์œผ๋ฉด ๋กœ๊ทธ์ธ ํ›„ ๋“ค์–ด๊ฐ„ ํŽ˜์ด์ง€์—๋„ ๊ฐ™์€ ๊ฒŒ์‹œ๊ธ€์ด ๋ณด์ด๋„๋ก ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ทธ๋งŒํผ ์ž์›์ด ๋‚ญ๋น„๋œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Œ)

 

์›๋ž˜ ๊ฐ€์ง€๊ณ  ์žˆ๋˜ MainView ํŽ˜์ด์ง€๋Š” ์˜ค๋ฅธ์ชฝ ์•„์ด์ฝ˜์„ ๋ˆ„๋ฅด๋ฉด ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ๋˜๋Š” ๋ฒ„ํŠผ๊ณผ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ๋˜๋Š” ๋ฒ„ํŠผ์ด ์žˆ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ ๋ถ€๋ถ„์„ ๋ณด์—ฌ์ฃผ๋Š” vue๊ฐ€ RightSide.vue์˜€๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ–ˆ๊ณ , ๋กœ๊ทธ์ธ ํ–ˆ๋‹ค๋Š” ๊ธฐ๋ก(?)์ด ๋“ค์–ด์˜ค๋ฉด RightSide.vue๊ฐ€ ๋‹ค๋ฅธ vue๋กœ ๋ฐ”๋€Œ๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.

 

 

 

 


 

 

 

 

3. LoginView.vue

<script> ์ฝ”๋“œ

  methods: {
    async login() {
      try {
        const res = await axios.post("http://localhost:8080/api/login", {
          userId: this.userId,
          pw: this.pw
        });
        localStorage.setItem("displayName", this.userId());
        alert("๋กœ๊ทธ์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
        this.$router.replace("/main");
      } catch (e) {
        alert(e.response.data);
      }
    },
๋กœ๊ทธ์ธ ๋งŒ๋“œ๋Š” ํฌ์ŠคํŒ…์—์„œ ๋ณด์—ฌ์คฌ๋˜ ์ฝ”๋“œ๋ž‘ ์กฐ๊ธˆ ๋‹ฌ๋ผ์กŒ๋‹ค. 
 localStorage.setItem("displayName", this.userId);
        /* ๋กœ๊ทธ์ธ ์„ฑ๊ณตํ•˜๋ฉด path์— ์ ํžŒ ๊ฒฝ๋กœ๋กœ ๋„˜๊น€, query์— ์ ์€ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ */
        this.$router.push({
          path: "/customer-view",
          query: { userId: this.userId }
        });


์ด ์ฝ”๋“œ๊ฐ€ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์ „์ด๋‹ค. ๋กœ๊ทธ์ธ์ด ์„ฑ๊ณตํ•˜๋ฉด ํŽ˜์ด์ง€๊ฐ€ /customer-view๋กœ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๋ฉด์„œ, userId๊ฐ€ ์ฟผ๋ฆฌ๋กœ ๊ฐ™์ด ๊ฐ€๊ฒŒ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋งŒ๋“œ๋‹ˆ ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์•˜๋˜ ์ ์ด url์— ์‚ฌ์šฉ์ž ์•„์ด๋””๊ฐ€ ๋ณด์—ฌ์ง„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ํ›„์— ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.

์ˆ˜์ •๋œ ์ฝ”๋“œ๋ฅผ ๋ณด๊ฒ ๋‹ค. localStorage๋ฅผ ์ผ๋Š”๋ฐ, ์ด๊ฑด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. vue๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. localStorage๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์— key-value ๊ฐ’์„ Storage์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์ €์žฅํ•œ ๋ฐ์ดํ„ฐ๋Š” ์„ธ์…˜ ๊ฐ„์— ๊ณต์œ ๋œ๋‹ค. ์ฆ‰, ์„ธ์…˜์ด ๋ฐ”๋€Œ์–ด๋„ ์ €์žฅํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ์ง€๋œ๋‹ค. localStorage๋Š” setItem(์•„์ดํ…œ ์ถ”๊ฐ€), getItem(์•„์ดํ…œ ์ฝ๊ธฐ), removeItem(item ์‚ญ์ œ), clear(๋„๋ฉ”์ธ ๋‚ด์˜ localStrage ๊ฐ’ ์‚ญ์ œ), length(์ „์ œ ์•„์ดํ…œ ๊ฐฏ์ˆ˜), key(index๋กœ key ๊ฐ’ ์ฐพ๊ธฐ)๊ฐ€ ์žˆ๋‹ค. ๊ทธ ์ค‘ setItem์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž ์•„์ด๋””๋ฅผ ์ €์žฅํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค. key์— ๋“ค์–ด๊ฐ€๋Š”๊ฒŒ displayName์ด ๋˜๊ณ  value์— ๋“ค์–ด๊ฐ€๋Š”๊ฒŒ userId๊ฐ€ ๋œ๋‹ค. 

this.$router.push๋ฅผ this.$router.replace๋กœ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ–ˆ๋‹ค. push๋Š” ๋ธŒ๋ผ์šฐ์ € ํžˆ์Šคํ† ๋ฆฌ์— ์ƒˆ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋’ค๋กœ ๊ฐ€๊ธฐ๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ถ€๋ถ„์ด ๋งˆ์Œ์— ์•ˆ๋“ค์–ด์„œ replace๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค. replace๋Š” ํ˜„์žฌ ํžˆ์Šคํ† ๋ฆฌ ํ•ญ๋ชฉ์„ ๋Œ€์ฒดํ•œ๋‹ค. ๋’ค๋กœ ๊ฐ€๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ๋„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์—†๋‹ค. ๋ณดํ†ต replace๋ฅผ ์จ์„œ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„์— ๋’ค๋กœ ๊ฐ€๊ธฐ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.

 

 

 

 


 

 

 

4. MainView.vue

<script> ์ฝ”๋“œ  

data() {
    return {
      isRightSideOpen: false,
      isLeftSideOpen: false,
      /* ๋กœ๊ทธ์ธ ์‹œ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ผ ์‚ฌ์šฉ์ž ์•„์ด๋”” ํ˜น์ธ ๋‹‰๋„ค์ž„ */
      displayName: null,
    }
  },
localStorage์— ์ €์žฅํ–ˆ๋˜ displayName ํ‚ค๋ฅผ null๋กœ ์„ค์ •ํ–ˆ๋‹ค.

 

 

<script>์˜ computed ์ฝ”๋“œ 

  loggedIn() {
      /* ๋กœ๊ทธ์ธ ์—ฌ๋ถ€, displayname์ด ์žˆ์œผ๋ฉด ๋กœ๊ทธ์ธ ์ƒํƒœ๋กœ ๊ฐ„์ฃผ */
      return Boolean(this.displayName);
    },
displayName์— ๋ฌธ์ž์—ด์ด ๋“ค์–ด์™€์„œ null์ด ์•„๋‹ˆ๊ฒŒ ๋˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋งŒ์•ฝ null์ด๋ฉด, false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

 

<script> ์ฝ”๋“œ ์ค‘ methods

    // ๋กœ๊ทธ์•„์›ƒ ํ•˜๋Š”๊ฑฐ.
    loggedOut() {
      localStorage.removeItem('displayName');  // ์ €์žฅ์†Œ ๋น„์šฐ๊ธฐ
      this.displayName = null;                 // null๋กœ ๋งŒ๋“ค์–ด์„œ ์˜ค๋ฅธ์ชฝ ์‚ฌ์ด๋“œ๋ฐ” ๋ฐ”๊พธ๊ณ 
      this.$router.replace('/main');           // main ํ™”๋ฉด
    },
๋กœ๊ทธ์ธ์„ ํ•˜๊ณ  ๋‚˜๋ฉด RightSide.vue๊ฐ€ CustomerRight.vue๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค. ์•„์ง CustomerRight.vue์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ  ๊ทธ ์•ˆ์—๋Š” ํšŒ์›์˜ ์•„์ด๋””๋ฅผ ๋‚˜ํƒ€๋‚ด๊ณ  ๋กœ๊ทธ์•„์›ƒ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ฆญ์„ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค. ๋กœ๊ทธ์•„์›ƒ ํ…์ŠคํŠธ๋ฅผ ๋ˆ„๋ฅด๋ฉด CustomerRight.vue๊ฐ€ ๋ถ€๋ชจ์—๊ฒŒ ๋กœ๊ทธ์•„์›ƒ์„ ์•Œ๋ฆฐ๋‹ค.(์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ์„ ๋ˆŒ๋ €์–ด์š”~) ๊ทธ๋ž˜์„œ ๊ทธ ๋กœ๊ทธ์•„์›ƒ ๋กœ์ง์„ ๋ถ€๋ชจ์ธ MainView.vue์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

displayName์— ๋“ค์–ด์˜จ key์™€ value ๊ฐ’์„ removeItem์œผ๋กœ ์ง€์›Œ์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  displayName ๊ฐ’์„ null๋กœ ์„ค์ •ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  main ํ™”๋ฉด์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. ์•„๊นŒ๋„ ์„ค๋ช…ํ–ˆ์ง€๋งŒ this.$router.push๋ฅผ ์“ฐ๋ฉด ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ˆŒ๋ €์„ ๋•Œ ๋กœ๊ทธ์ธ ์ƒํƒœ๊ฐ€ ๋‚˜ํƒ€๋‚œ๋‹ค. ๊ทธ๋ž˜์„œ replace๋กœ ์ž‘์„ฑํ–ˆ๋‹ค.

 

 

<template> ์ฝ”๋“œ

<RightSide v-if="!loggedIn" :open="isRightSideOpen" />
<CustomerRight v-else :open="isRightSideOpen" 
               :display-name="displayName" @logged-out="loggedOut" />
์—ฌ๊ธฐ์„œ ๊ฐ ์กฐ๊ฑด์— ๋งž์ถฐ RightSide๋ฅผ ๋ณด์ด๊ฒŒ ํ• ์ง€, CustomerRight๋ฅผ ๋ณด์ด๊ฒŒ ํ•  ์ง€ ๊ฒฐ์ •ํ•  ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ์˜ ์กฐ๊ฑด์€ ๋กœ๊ทธ์ธ์ด ๋˜์—ˆ์„ ๋•Œ CustomerRight์ด ๋ณด์ด๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋กœ๊ทธ์ธ์ด ๋œ ๊ฑธ ์–ด๋–ป๊ฒŒ ์•Œ๊ฒŒ ํ–ˆ๋Š”์ง€ ๋˜๋Œ์•„๋ณด๋ฉด, ํ‰์†Œ์—” displayName์— null์„ ๋„ฃ์—ˆ๋‹ค๊ฐ€ ๋กœ๊ทธ์ธ์ด ๋˜๋ฉด displayName์— key์™€ value๊ฐ€ ์˜ค๋ฉด์„œ loggenIn( )์œผ๋กœ ์•ˆ์— ๊ฐ’์˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ–ˆ๋‹ค. 

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž. ๋งŒ์•ฝ์—(v-if) loggedIn์˜ return ๊ฐ’์ด false์ด๋ฉด RightSide ๋ทฐ๋ฅผ isRightSideOpenํ•œ๋‹ค๊ณ  ํ–ˆ๋‹ค. isRightSideOpen์€ ์—ด๋ฆผ/๋‹ซํž˜ ์ƒํƒœ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๋งŒ์•ฝ์—(v-else) v-if์—์„œ ์ง€์ •ํ•œ ๊ฐ’ ์™ธ์˜ ๋‹ค๋ฅธ ๊ฐ’์ด ๋‚˜์˜ค๋ฉด CustomerRight์ด open๋œ๋‹ค. :display-name="displayName"์œผ๋กœ ์‚ฌ์šฉ์ž id ๊ฐ’์ด ๋„˜์–ด๊ฐ€๋„๋ก ํ–ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ž˜ ์•Œ์•„๋‘ฌ์•ผํ•  ๊ฒƒ์€ ์‚ฌ์šฉ์ž id๊ฐ€ ํ˜„์žฌ vue์ธ MainView.vue์—์„œ CustomerRight.vue๋กœ ๋„˜์–ด๊ฐ„๋‹ค. ์‚ฌ์šฉ์ž id๋ฅผ ๋ณด์—ฌ์ค„ ๊ณณ์€ MainView๊ฐ€ ์•„๋‹Œ CustomerRight์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๋‹ค. ๊ทธ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž. CustomerRight์—์„œ ๋กœ๊ทธ์•„์›ƒ์„ ํด๋ฆญํ•˜๋Š” ๋™์ž‘์ด ์ˆ˜ํ–‰๋˜๋ฉด, ๊ทธ ์‚ฌ์‹ค์„ MainView๊ฐ€ ์•Œ๋„๋ก ์„ค์ •ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ @logged-out์„ ํ†ตํ•ด MainView๋Š” ๋กœ๊ทธ์•„์›ƒ์„ ์ˆ˜ํ–‰ํ–ˆ๋Š”์ง€ ์•ˆํ–ˆ๋Š”์ง€ ์•Œ๊ฒŒ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ์„ ๋ˆ„๋ฅด๋ฉด loggedOut์ด๋ž€ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉฐ ๋กœ๊ทธ์•„์›ƒ์ด ์ฒ˜๋ฆฌ๋œ๋‹ค.

+) ์‚ดํŽด๋ณด๋ฉด display-name์ด๋ผ๊ณ  ๋˜์–ด์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋‹ค. HTML์€ ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ณ„์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋Ÿฐ๋ฐ props(์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ)๋Š” ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•œ๋‹ค. ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด HTML๊ณผ props๋Š” ์„œ๋กœ ์ด๋ฆ„์„ ์ •ํ•˜๋Š” ๊ทœ์น™์ด ๋‹ค๋ฅธ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ HTML์— displayName์ด๋ผ๊ณ  ์ ์œผ๋ฉด ๋‚ด๋ถ€์—์„  displayname์œผ๋กœ ๋Œ์•„๊ฐ€์„œ props์˜ ์ด๋ฆ„๊ณผ ์ž๋™์œผ๋กœ ๋งคํ•‘์„ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ HTML์„ ์ ์„ ๋• kebab-case๋กœ ์ ๊ณ  props๋Š” camelCase๋กœ ์ ๋Š”๊ฒŒ ์ข‹๋‹ค.

 

 

Q. HTML์—์„œ๋„ props์—์„œ๋„ displayname์ด๋ผ๊ณ  ํ•˜๋ฉด?

A. ์ž˜ ๋Œ์•„๊ฐ„๋‹ค. ํ˜„์žฌ ์ฝ”๋“œ์—์„œ ๋ฌธ์ œ๋˜๋Š” ๊ฑด ์—†๋Š”๋ฐ, Vue๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ํ˜•์‹์ด ์•„๋‹ˆ๋‹ค. ์•„๋งˆ ๊ถŒ์žฅ ํ˜•์‹๋Œ€๋กœ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๋ถ„๊ณผ ํ˜‘์—…์„ ํ•˜๊ฒŒ๋œ๋‹ค๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ˆ, ๋‹น์žฅ์€ ์“ฐ์ง€ ์•Š๋”๋ผ๋„ ํ•ด๋‹น ๋‚ด์šฉ์„ ์ผ๋‹จ ์•Œ์•„๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ฆฌ๊ณ  Extraneous non-props attributes... ์ด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ์„œ๋กœ ๋งคํ•‘์ด ์ œ๋Œ€๋กœ ๋๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž.

 

 

 

 


 

 

 

5. CustomerRight.vue

<script> ์ฝ”๋“œ

props: {
    open: {
      type: Boolean,
      required: true,
    },
    displayName: {
      type: String,
      default: '',
    }
  },
๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜€๋˜ MainView.vue๊ฐ€ ๋ณด๋‚ธ ์ •๋ณด๋ฅผ props์—์„œ ๋ฐ›๋Š”๋‹ค. ํŒจ๋„์ด ์—ด๋ ธ๋Š”์ง€ ์•„๋‹Œ์ง€์— ๋Œ€ํ•œ ๊ฒƒ์ด open. ์‚ฌ์šฉ์ž id๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ณณ์ด displayName์ด ๋œ๋‹ค. ์•„๊นŒ ์„ค๋ช…ํ•ด์„œ HTML์˜ ์ด๋ฆ„ ํ˜•์‹๊ณผ props์˜ ์ด๋ฆ„ ํ˜•์‹์— ๋Œ€ํ•ด ๋งํ–ˆ๋Š”๋ฐ, props๊ฐ€ ์ด ๋ถ€๋ถ„์ด ๋˜๊ฒ ๋‹ค. ํƒ€์ž…์€ String์ด๊ณ  ๋ถ€๋ชจ์—๊ฒŒ์„œ ๋ฐ›์•„์˜จ ๊ฒƒ์ด ์—†๋‹ค๋ฉด ๊ธฐ๋ณธ๊ฐ’์€ ๋นˆ ๋ฌธ์ž์—ด๋กœ ํ•œ๋‹ค.

 

 

<script> ์ฝ”๋“œ

computed: {
    // ์ด๋ฆ„์„ ๋ณด์—ฌ์ค€๋‹ค.
    nameToShow() {
      return this.displayName;
    }
  },
computed๋Š” ๊ฐ’์ด ๋ฐ”๋€Œ๋ฉด ์ž๋™์œผ๋กœ ์žฌ๊ณ„์‚ฐํ•ด์„œ ํ…œํ”Œ๋ ›์ด ์ฆ‰์‹œ ๋ณ€๊ฒฝ๋˜๋„๋ก ํ•ด์ค€๋‹ค. ์ด๋ฆ„์ด ๋ฐ”๋€Œ๋ฉด ์ƒˆ๋กœ ์—ฐ์‚ฐ์„ ํ•ด์•ผํ•˜๋‹ˆ computed์— ์จ๋ดค๋‹ค. nameToShow๋Š” props๋กœ ๋ฐ›์•„์˜จ displayName์„ ๋ณด์—ฌ์ค€๋‹ค.

 

 

<script> ์ฝ”๋“œ

methods: {
    // ๋ถ€๋ชจ์—๊ฒŒ ๋กœ๊ทธ์•„์›ƒ ์•Œ๋ฆฌ๊ธฐ
    logout() {
      this.$emit('logged-out');
    }
    
    
    
<template> ์ฝ”๋“œ

<p class="logout" @click="logout">logout</p>
props๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด emit๋Š”? ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์•„๊นŒ MainView์—์„œ ๋กœ๊ทธ์•„์›ƒ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์„ ๋งŒ๋“ค์—ˆ๋‹ค. 
   // ๋กœ๊ทธ์•„์›ƒ ํ•˜๋Š”๊ฑฐ.
    loggedOut() {
      localStorage.removeItem('displayName');  // ์ €์žฅ์†Œ ๋น„์šฐ๊ธฐ
      this.displayName = null;                 // null๋กœ ๋งŒ๋“ค์–ด์„œ ์˜ค๋ฅธ์ชฝ ์‚ฌ์ด๋“œ๋ฐ” ๋ฐ”๊พธ๊ณ 
      this.$router.replace('/main');           // main ํ™”๋ฉด
    },โ€‹


logout ํ…์ŠคํŠธ๋ฅผ ๋ˆ„๋ฅด๋ฉด logout์ด๋ž€ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ , logout ๋ฉ”์„œ๋“œ๋Š” $emit์„ ํ†ตํ•ด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๋กœ๊ทธ์•„์›ƒ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์š”๊ตฌํ•œ๋‹ค.

'๐Ÿ’ป ํ”„๋กœ์ ํŠธ > ๐Ÿ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๐Ÿ ' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Spring, Vue.js] ์นด์นด์˜ค ๊ฐ„ํŽธ ๋กœ๊ทธ์ธ ๋งŒ๋“ค๊ธฐโ‘ก - Vue๋กœ ํ”„๋ก ํŠธ์—”๋“œ ์ž‘์„ฑํ•˜๊ธฐ (REST API)  (1) 2025.09.27
[Spring,Vue.js] ์นด์นด์˜ค ๊ฐ„ํŽธ ๋กœ๊ทธ์ธ ๋งŒ๋“ค๊ธฐ โ‘  - ๊ตฌ์กฐ์™€ ํ๋ฆ„ ํŒŒ์•…ํ•˜๊ณ  ์นด์นด์˜ค ๋””๋ฒจ๋กœํผ์Šค ์„ค์ •ํ•˜๊ธฐ (REST API)  (0) 2025.09.25
[SpringBoot, Vue.js] ๋กœ๊ทธ์ธ ํ™”๋ฉด ๋งŒ๋“ค๊ธฐ, passwordEncoder.matches๋ฅผ ํ†ตํ•ด ์•”ํ˜ธํ™”๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋น„๊ตํ•˜๊ธฐ.  (5) 2025.08.31
[SpringSecurity] Vue์™€ Spring์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ.(CORS ์—๋Ÿฌ ํ•ด๊ฒฐํ•˜๊ธฐ)  (3) 2025.08.30
[Vue.js] ๋ฒ„ํŠผ ๋กœ์ง์ด ์ œ๋Œ€๋กœ ๋™์ž‘์„ ์•ˆํ•˜๋Š” ๊ฒƒ ๊ฐ™์„ ๋•Œ, chunk-VZXQDS5F.js?v=5f04997f:2125 [Vue warn]: Data property "idDuplicate" is already defined in Methods.  (0) 2025.08.20