<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>playhong 님의 블로그</title>
    <link>https://playhong.tistory.com/</link>
    <description>playhong 님의 블로그 입니다.</description>
    <language>ko</language>
    <pubDate>Fri, 10 Apr 2026 08:50:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>playhong</managingEditor>
    <item>
      <title>JS) 배열 회전시키기</title>
      <link>https://playhong.tistory.com/100</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  링크&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120844&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/120844&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정수가&amp;nbsp;담긴&amp;nbsp;배열&amp;nbsp;numbers와&amp;nbsp;문자열&amp;nbsp;direction가&amp;nbsp;매개변수로&amp;nbsp;주어집니다.&amp;nbsp;배열&amp;nbsp;numbers의&amp;nbsp;원소를&amp;nbsp;direction방향으로&amp;nbsp;한&amp;nbsp;칸씩&amp;nbsp;회전시킨&amp;nbsp;배열을&amp;nbsp;return하도록&amp;nbsp;solution&amp;nbsp;함수를&amp;nbsp;완성해주세요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  어떻게 풀까&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. right일 경우 맨 앞에 numbers의 맨 마지막 인덱스의 원소를 넣어줌 &lt;br /&gt;(push로 넣어줄거라 left일 경우 맨 첫 인덱스의 원소를 미리 넣으면 안됨)&lt;br /&gt;2. right인 경우엔 numbers를 그대로 push해주고 left인 경우엔 인덱스에 +1 해서 push&lt;br /&gt;3. left인 경우 맨 뒤에 numbers의 맨 첫번째 원소를 넣어줌&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  뭘 써야 할까&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;push 등..&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  답&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1740016186597&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(numbers, direction) {
    let answer = [];
    if(direction === &quot;right&quot;){
        answer.push(numbers[numbers.length-1])
    }
    for(let i=0; i&amp;lt;numbers.length-1; i++){
        if(direction === &quot;right&quot;){
            answer.push(numbers[i])
        }else if(direction === &quot;left&quot;){
            answer.push(numbers[i+1])
        }
    }
    if(direction === &quot;left&quot;){
        answer.push(numbers[0])
    }
    
    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 처럼 해도 문제가 풀리긴 하지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;&lt;b&gt;* 메서드들을 활용하면 더 간단한 코드로 작성할 수 있다.&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;unshift()&lt;/b&gt; 배열의 맨 앞에 값을 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;pop()&lt;/b&gt; 배열의 맨 끝 값을 제거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;push()&lt;/b&gt; 배열의 맨 끝에 값을 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;shift()&lt;/b&gt; 배열의 맨 앞 값을 제거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. answer에 스프레드연산자로 numbers를 복사한다 (numbers를 직접수정하지 않기위해)&lt;br /&gt;2. direction이 right 인 경우, pop()을 사용해 answer의 끝값을 제거하고, 해당 값을 lastNum에 선언한다&lt;br /&gt;3. unshift()를 사용해 lastNum을 배열의 맨 앞에 추가한다.&lt;br /&gt;4. direction이 left인 경우, shift()를 사용해 answer의 첫번째 값을 제거하고, 해당 값을 firstNum에 선언한다&lt;br /&gt;5. push()를 사용해 firstNum을 배열의 맨 마지막에 추가한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740031915970&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(numbers, direction) {
    let answer = [...numbers];
    if(direction === &quot;right&quot;){
        let lastNum = answer.pop()
        answer.unshift(lastNum)
    }else{
        let firstNum = answer.shift()
        answer.push(firstNum)
    }
    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/100</guid>
      <comments>https://playhong.tistory.com/100#entry100comment</comments>
      <pubDate>Thu, 20 Feb 2025 15:14:02 +0900</pubDate>
    </item>
    <item>
      <title>JS) 삼각형의 완성조건 (1)</title>
      <link>https://playhong.tistory.com/99</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  링크&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120889#&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/120889#&lt;/a&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선분&amp;nbsp;세&amp;nbsp;개로&amp;nbsp;삼각형을&amp;nbsp;만들기&amp;nbsp;위해서는&amp;nbsp;다음과&amp;nbsp;같은&amp;nbsp;조건을&amp;nbsp;만족해야&amp;nbsp;합니다. &lt;br /&gt;&lt;br /&gt;가장&amp;nbsp;긴&amp;nbsp;변의&amp;nbsp;길이는&amp;nbsp;다른&amp;nbsp;두&amp;nbsp;변의&amp;nbsp;길이의&amp;nbsp;합보다&amp;nbsp;작아야&amp;nbsp;합니다. &lt;br /&gt;삼각형의&amp;nbsp;세&amp;nbsp;변의&amp;nbsp;길이가&amp;nbsp;담긴&amp;nbsp;배열&amp;nbsp;sides이&amp;nbsp;매개변수로&amp;nbsp;주어집니다.&amp;nbsp;세&amp;nbsp;변으로&amp;nbsp;삼각형을&amp;nbsp;만들&amp;nbsp;수&amp;nbsp;있다면&amp;nbsp;1,&amp;nbsp;만들&amp;nbsp;수&amp;nbsp;없다면&amp;nbsp;2를&amp;nbsp;return하도록&amp;nbsp;solution&amp;nbsp;함수를&amp;nbsp;완성해주세요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  어떻게 풀까&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 제일 큰 수를 변수에 담고&lt;br /&gt;2. 그 변수를 제외한 배열을 만듦&lt;br /&gt;3. 만든 배열의 [0]번째 원소와 [1]번째 원소를 더한 후&lt;br /&gt;4. 변수와 비교하는 조건문을 작성&lt;br /&gt;&lt;br /&gt;(수정)&lt;br /&gt;1.&amp;nbsp; sides를 내림(오름차순)으로 정렬&lt;br /&gt;2. 정렬한 배열의 [1]번째 원소와&amp;nbsp; [2]번째 원소를 더해 [0]번째 원소와 비교하는 조건문을 작성&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  뭘 써야 할까&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1724890383249&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Math.max.apply(null,sides)
filter

(수정)
sort&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;답 (오답)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1738899254480&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(sides) {
    const longest = Math.max.apply(null,sides)
    const filterSides = sides.filter((num)=&amp;gt; num !== longest)
    if(sides[0] === sides[1] &amp;amp;&amp;amp; sides[1] === sides[2]){
        return 0
    }else if(filterSides[0]+filterSides[1] &amp;gt; longest){
        return 1
    }else{
        return 2
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 sides가 [2,4,4] 인 경우 filterSides가 [2] 로 필터링되어 정상적으로 계산되지 않음&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  답&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1738915759743&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(sides) {
    const sortSides = sides.sort((a,b)=&amp;gt;b-a)
    if(sortSides[0] === sortSides[1] &amp;amp;&amp;amp; sortSides[1] === sortSides[2]){
        return 1
    }if(sortSides[0] &amp;lt; sortSides[1] + sortSides[2]){
        return 1
    }else{
        return 2
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sort를 사용해 내림차순으로 sides를 정렬한 후, index를 이용해 조건문 작성&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/99</guid>
      <comments>https://playhong.tistory.com/99#entry99comment</comments>
      <pubDate>Fri, 7 Feb 2025 17:11:07 +0900</pubDate>
    </item>
    <item>
      <title>JS) 짝수는 싫어요</title>
      <link>https://playhong.tistory.com/98</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  링크&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120813&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/120813&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정수&amp;nbsp;n이&amp;nbsp;매개변수로&amp;nbsp;주어질&amp;nbsp;때,&amp;nbsp;n&amp;nbsp;이하의&amp;nbsp;홀수가&amp;nbsp;오름차순으로&amp;nbsp;담긴&amp;nbsp;배열을&amp;nbsp;return하도록&amp;nbsp;solution&amp;nbsp;함수를&amp;nbsp;완성해주세요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  어떻게 풀까&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;홀수를 찾아서 찾은 홀수를 빈 배열 anwser에 넣기&lt;br /&gt;홀수만 담긴 answer를 오름차순으로 정렬&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  뭘 써야 할까&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;0이 될 때 까지 반복 =&amp;gt; for문 (let i=n; i&amp;gt;0; i--)&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;홀수 찾기 =&amp;gt; i%2 === 1&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;찾은 홀수 배열에 넣기 =&amp;gt; answer.push(i)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;오름차순으로 정렬 =&amp;gt; answer.sort((a,b)=&amp;gt;a-b)&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  답&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1736302797797&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(n) {
    var answer = [];
    for(let i=n; i&amp;gt;0; i--){
        if(i%2===1){
            answer.push(i)
        }
    }
    const sortArr = answer.sort((a,b)=&amp;gt;a-b)
    return sortArr;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/98</guid>
      <comments>https://playhong.tistory.com/98#entry98comment</comments>
      <pubDate>Wed, 8 Jan 2025 11:20:10 +0900</pubDate>
    </item>
    <item>
      <title>JS) 최빈값 구하기</title>
      <link>https://playhong.tistory.com/97</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  링크&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/120812?language=javascript&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/120812?language=javascript&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;  문제&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최빈값은&amp;nbsp;주어진&amp;nbsp;값&amp;nbsp;중에서&amp;nbsp;가장&amp;nbsp;자주&amp;nbsp;나오는&amp;nbsp;값을&amp;nbsp;의미합니다.&amp;nbsp;정수&amp;nbsp;배열&amp;nbsp;array가&amp;nbsp;매개변수로&amp;nbsp;주어질&amp;nbsp;때,&amp;nbsp;최빈값을&amp;nbsp;return&amp;nbsp;하도록&amp;nbsp;solution&amp;nbsp;함수를&amp;nbsp;완성해보세요.&amp;nbsp;최빈값이&amp;nbsp;여러&amp;nbsp;개면&amp;nbsp;-1을&amp;nbsp;return&amp;nbsp;합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  어떻게 풀까&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;// 각 배열의 원소 갯수를 세어서 객체로 만들어줌&lt;br /&gt;ex)&lt;br /&gt;[1,2,3,3,3,4]인 경우&lt;br /&gt;obj = { 1 : 1, 2 : 1, 3 : 3 , 4 : 1}&lt;br /&gt;// 값들을 모두 비교해 가장 큰 값의 키를 구함&lt;br /&gt;// 키가 1개면 해당 키를 출력, 아니라면 (2개 이상이라면) -1를 출력&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  뭘 써야 할까&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;array.forEach&lt;br /&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach&lt;/a&gt;&lt;br /&gt;배열을 돌면서 각 원소가 몇번 나왔는지 작성&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. Math.max&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/max&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/max&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 수 구하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Object.key (+filter)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/keys&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/keys&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최빈값의 키를 filter를 사용해 배열로 넣음&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  답&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1736243439239&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(array) {
    
    let countObj = {}
    
    array.forEach(num =&amp;gt; {
        countObj[num] = (countObj[num] || 0) + 1
    })
    // countObj가 있다면 그 값을 사용하고, 없다면(undefined) 0으로 설정
    
    const maxCount = Math.max(...Object.values(countObj))
    // 요소 중 값(value)이 가장 큰 숫자를 넣어줌
    
    const maxCountKey = Object.keys(countObj).filter(key =&amp;gt; countObj[key] === maxCount).map(Number)
	// maxCount를 가지고 있는 요소의 키를 찾아 넣어줌
	// 단, [&quot;1&quot;] 이런 형식으로 나오기 때문에 .map(Number)로 문자열이 아닌 숫자형식으로 변경해줘야함
    
    if(maxCountKey.length &amp;lt; 2){
        return maxCountKey[0]
    }else{
        return -1
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/97</guid>
      <comments>https://playhong.tistory.com/97#entry97comment</comments>
      <pubDate>Tue, 7 Jan 2025 18:59:10 +0900</pubDate>
    </item>
    <item>
      <title>241016</title>
      <link>https://playhong.tistory.com/96</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 프로필이미지 수정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원정보를 수정할 때 다른 정보는 회원가입시 사용했던 것으로 어떻게 만들어놨는데 프로필 이미지 변경이 안된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토리지에 이미지가 들어가지 않는 것으로 보아 로직 자체에 문제가 있는 것 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로직에 문제가 없다고 해도 (정상적으로 이미지가 선택된다고 해도) 회원가입때 사용했던 것을 그대로 사용하면 한사람이 프로필 이미지를 계속 바꾸면 이미지도 계속 쌓이게 되므로 수정은 필연적이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 회원가입할 때 이미지를 넣어줄 경로에 있는 기존 이미지를 삭제하고 새로 넣어주는 방법&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용자가 이미지를 선택했을 경우 &lt;br /&gt;2. user_image / user_id 경로의 모든 이미지를 삭제한 후 &lt;br /&gt;3. 선택한 이미지를 user_image / user_id 경로에 넣고 &lt;br /&gt;4. 이 이미지를 프로필 이미지로 등록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순으로 생각했는데 너무 비효율적?이라는 생각이 들었다&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새롭게 선택된 이미지로 업데이트 해줄 수 없는지 공식문서를 더 찾아보기로함.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. upsert&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힌트를 얻은 것은 이 문서였다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://supabase.com/docs/guides/storage/uploads/resumable-uploads&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://supabase.com/docs/guides/storage/uploads/resumable-uploads&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRgALL/btsJ7TPe7wV/deNt8uA1BHUKLnEvcKkvd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRgALL/btsJ7TPe7wV/deNt8uA1BHUKLnEvcKkvd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRgALL/btsJ7TPe7wV/deNt8uA1BHUKLnEvcKkvd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRgALL%2FbtsJ7TPe7wV%2FdeNt8uA1BHUKLnEvcKkvd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;592&quot; height=&quot;152&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;152&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;upsert : &amp;nbsp;Update와&amp;nbsp;Insert를&amp;nbsp;합친&amp;nbsp;것으로,&amp;nbsp;존재하지&amp;nbsp;않을&amp;nbsp;경우,&amp;nbsp;Insert하고&amp;nbsp;존재할&amp;nbsp;경우,&amp;nbsp;현재&amp;nbsp;내용을&amp;nbsp;덮어쓰는&amp;nbsp;유용한&amp;nbsp;쿼리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 한다! 저 내용만으로는 부족해 조금 더 찾아봤는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://supabase.com/docs/reference/javascript/storage-from-update&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://supabase.com/docs/reference/javascript/storage-from-update&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://supabase.com/docs/guides/storage/uploads/standard-uploads&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://supabase.com/docs/guides/storage/uploads/standard-uploads&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSK0WS/btsJ6EFwuWC/3GYthjp7xk1aExF1hyUQB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSK0WS/btsJ6EFwuWC/3GYthjp7xk1aExF1hyUQB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSK0WS/btsJ6EFwuWC/3GYthjp7xk1aExF1hyUQB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSK0WS%2FbtsJ6EFwuWC%2F3GYthjp7xk1aExF1hyUQB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1058&quot; height=&quot;420&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lJ6DK/btsJ7wUiX02/FVx0rOXqAFSn5xO5FMoiK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lJ6DK/btsJ7wUiX02/FVx0rOXqAFSn5xO5FMoiK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lJ6DK/btsJ7wUiX02/FVx0rOXqAFSn5xO5FMoiK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlJ6DK%2FbtsJ7wUiX02%2FFVx0rOXqAFSn5xO5FMoiK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;466&quot; height=&quot;85&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 사용해준다고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 코드를 반으로 줄일 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1729016349288&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 프로필 이미지 등록 핸들러
  const handleImgUpload = async (e: React.ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    const file = e.target.files?.[0];

    if (!file) {
      console.log('파일을 선택해 주세요.');
      return;
    }
    console.log(file);
    console.log(userId);

    const { data: imgData, error: imgError } = await browserClient.storage
      .from('user_image')
      .upload(`${userId}/${file.name}`, file, {
        cacheControl: '3600',
        upsert: true
      });
    if (imgError) {
      console.log('이미지 오류 =&amp;gt; ', imgError);
    }

    // 업로드된 이미지의 URL 가져오기
    const imageUrl = `${process.env.NEXT_PUBLIC_SUPABASE_URL}/storage/v1/object/public/user_image/${userId}/${file.name}`;

    setValue('image_url', imageUrl);
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 작성했는데 이미지를 선택할 때 에러가 난다&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;file 도 정상적으로 찍히고 userId도 잘 찍히는데 왜??&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@liabin124/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-React-with-typescript-Supabase4Storage%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%AC%EB%9F%AC%EC%9E%A5-%EB%84%A3%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@liabin124/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-React-with-typescript-Supabase4Storage%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%AC%EB%9F%AC%EC%9E%A5-%EB%84%A3%EA%B8%B0&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에 대한 답은 여기서 얻었는데, supabase storage에는 한글로 된 파일명은 업로드가 되지 않는다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원가입짤 때 몰랐던 이유는 한글파일로 테스트를 해보지 않아서..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 나도 똑같이&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1729017369335&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const profile_image_name = userUid;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UUID를 넣어줘봤다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가입할 때도 저런 유니크한 값으로 바꿔줘야 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 수파베이스 상에서 이미지가 바로바로 바뀐다!&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 -&lt;span&gt; 마이페이지/회원정보 편집 페이지 404 에러&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 문제를 해결하면서 알게 됐는데 분명 수파베이스에서는 수정한 정보가 반영되는데 브라우저에서는 반영되지 않는 것을&amp;nbsp; 확인함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마이페이지/회원정보 편집 페이지에서 새로고침을 할 때마다 404에러가 뜨고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수파베이스상의 변경된 내용을 실시간으로 불러오지 못하고 시크릿창으로 새로 열 때마다 변경된 내용이 반영됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 라우팅문제?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결이 안돼서 질문하러감&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 폴더 구조는 (auth) /&amp;nbsp; mypage, (auth) / mypage / edit&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 (auth) 가 문제될 수 있으니 (auth) 폴더 밖으로 꺼내보라고 하셨는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(auth)는 서브 사이드바에서 프로필 관련 메뉴만 표시할 수있도록 + 프로젝트 내에서 맡은 부분을 구분하기 위해 그룹화 해놓은 것이고, 다른 login이나 signup페이지도 같은식으로 묶여있는데 동일한 에러가 뜨지 않음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결정적으로 혹시나? 싶어서 꺼내봤는데도 동일한 문제가 생겨서 이 문제는 아닐거라고 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 스토리지문제?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 이미지 업데이트를 제외한 나머지를 구현했을 정상적으로 수정이 됐었는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 이미지 업데이트를 추가하고 나서 부터 안되기 시작했음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 스토리지 부분을 모두 주석처리하고 다시 시도해봤는데 여전히 프로필 수정사항이 반영되지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  현재 풀어야 할 문제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;1. 이미지 수정 / 이미지 등록 시 이름 변경&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 사이드바 버튼&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;3. 마이페이지, 회원정보편집페이지에서 404에러가 뜨는 문제&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 이력서, 면접목록 불러오기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 마이페이지 편집시 마이페이지로 리다이렉트 시키기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;➕ 추가 해야 할 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인시 포인트 지급 (하다 말음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/96</guid>
      <comments>https://playhong.tistory.com/96#entry96comment</comments>
      <pubDate>Wed, 16 Oct 2024 03:43:34 +0900</pubDate>
    </item>
    <item>
      <title>241015</title>
      <link>https://playhong.tistory.com/95</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 프로필 이미지 업로드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 등록 시 400 에러가 뜸&lt;/p&gt;
&lt;pre id=&quot;code_1728911846977&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 프로필 이미지 등록 핸들러
  const handleImgUpload = async (e: React.ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    const file = e.target.files?.[0];

    if (!file) {
      console.log('파일을 선택해 주세요.');
      return;
    }

    const { data: imgData, error: imgError } = await browserClient.storage
      .from('profile_img')
      .upload(`${user_id}/${file.name}`, file, {
        cacheControl: '3600',
        upsert: false
      });
    if (imgError) {
      console.log('이미지 오류 =&amp;gt; ', imgError);
    }
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 로직이 잘못됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;watch(&quot;&quot;)등 react-hook-form의 메서드를 활용해 수정해야 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. RLS 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원정보 2개씩 쌓이는 문제를 해결하면서 이 설정의 중요성을 느꼈다. 이게 설정되어 있지 않으면 회원가입 중에 테이블이나 storage에 접근할 수 없어 중요하다!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. RLS설정&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 RLS를 설정하려했는데 먼저 storage를 사용하고 있는 팀원분이 설정하신걸 보니 public으로 되어있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 만든 storage는 처음 만들 때 필요할 것 같아서 일단 만들어 설정하는 것을 전부 건너 뛰어 수정이 필요했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 public이 아닌 storage를 public으로 변경하는 방법을 찾지 못해 해당 storage를 삭제하고, 다시 만드는 방향으로 진행했다. (어차피 아무것도 들어있지 않았음!)&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIyJtj/btsJ4YYr2fq/PysE0K2c2IIJKFUSHbEjhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIyJtj/btsJ4YYr2fq/PysE0K2c2IIJKFUSHbEjhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIyJtj/btsJ4YYr2fq/PysE0K2c2IIJKFUSHbEjhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIyJtj%2FbtsJ4YYr2fq%2FPysE0K2c2IIJKFUSHbEjhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;290&quot; height=&quot;177&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 눌러서 추가하고&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;539&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l6Z9u/btsJ6UUBCs0/JluikrEPo1U3DGVtJMbU01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l6Z9u/btsJ6UUBCs0/JluikrEPo1U3DGVtJMbU01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l6Z9u/btsJ6UUBCs0/JluikrEPo1U3DGVtJMbU01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl6Z9u%2FbtsJ6UUBCs0%2FJluikrEPo1U3DGVtJMbU01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;539&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;539&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정한 뒤 이름을 적어 save하고&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwFisc/btsJ6RDAcj4/3qqAKKZzW7TveSVUkqTfI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwFisc/btsJ6RDAcj4/3qqAKKZzW7TveSVUkqTfI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwFisc/btsJ6RDAcj4/3qqAKKZzW7TveSVUkqTfI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwFisc%2FbtsJ6RDAcj4%2F3qqAKKZzW7TveSVUkqTfI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;856&quot; height=&quot;371&quot; data-origin-width=&quot;856&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;좌측 Policies -&amp;gt; 수정하려는 storage에서 New policy를 한다.&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN3B4p/btsJ6XjsqEx/aal2PdYSFe1OdDH7j8U0FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN3B4p/btsJ6XjsqEx/aal2PdYSFe1OdDH7j8U0FK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN3B4p/btsJ6XjsqEx/aal2PdYSFe1OdDH7j8U0FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN3B4p%2FbtsJ6XjsqEx%2Faal2PdYSFe1OdDH7j8U0FK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;544&quot; height=&quot;409&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;Get started quickly 는 뭔가 원치 않는 설정이 되는 경우도 있는 것 같아(어떤 상황에선 이 설정이 원치 않는 문제를 일으키키도 하고) For full customization을 이용해&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;807&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfdUG9/btsJ4grLL05/VQtVWGCvn2lBmyZdVAsTGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfdUG9/btsJ4grLL05/VQtVWGCvn2lBmyZdVAsTGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfdUG9/btsJ4grLL05/VQtVWGCvn2lBmyZdVAsTGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfdUG9%2FbtsJ4grLL05%2FVQtVWGCvn2lBmyZdVAsTGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;738&quot; height=&quot;807&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;807&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 이름 채우고, operation 선택하고 바로 Review를 클릭해 생성?했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 사용자가 프로필 이미지를 수정할 것 까지 고려해 insert, select, update를 생성해 주었다.&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. React-hook-form의 메서드를 활용해 이미지 url을 넣어줬다.&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 이미지 파일을 선택하지 않았을 때 표시해줄 디폴트 이미지 url을 설정한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728914274111&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리액트 훅 폼으로 유효성 검사
const { register, handleSubmit, formState, watch, setValue } = useForm({
mode: 'onChange',
defaultValues: {
  user_id: '',
  user_pw: '',
  user_type: 'mentee',
  email: '',
  user_name: '',
  image_url: 'http://~~디폴트프로필이미지.png'
},
resolver: zodResolver(signUpSchema)
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 react-hook-form 메서드를 이용한 로직으로 수정했다&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728914135287&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 프로필 이미지 등록 핸들러
  const handleImgUpload = async (e: React.ChangeEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
    const file = e.target.files?.[0];

    if (!file) {
      console.log('파일을 선택해 주세요.');
      return;
    }

    const userId = watch('user_id');

    const { data: imgData, error: imgError } = await browserClient.storage
      .from('user_image')
      .upload(`${userId}/${file.name}`, file, {
        cacheControl: '3600',
        upsert: false
      });
    if (imgError) {
      console.log('이미지 오류 =&amp;gt; ', imgError);
    }

    // 업로드된 이미지의 URL 가져오기
    const imageUrl = `${process.env.NEXT_PUBLIC_SUPABASE_URL}/storage/v1/object/public/user_image/${userId}/${file.name}`;

    setValue('image_url', imageUrl);
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const&amp;nbsp;imageUrl&amp;nbsp;=&amp;nbsp;`${process.env.NEXT_PUBLIC_SUPABASE_URL}/storage/v1/object/public/user_image/${userId}/${file.name}`;&lt;br /&gt;이미지 url을 profile_img에서 user_image로 변경했는데 변경한 내용이 적용되지 않고 profile_img/~~/~~ 이렇게 들어가는 문제가 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; &lt;b&gt;yarn build&lt;/b&gt;를 해보니 변경한 url로 정상적으로 들어오고 이미지를 선택하지 않은 경우, 디폴트 이미지가 제대로 적용됨!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지를 선택한 경우도 제대로 적용됨 !!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결!!!!!!!!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 마이페이지 (정보 불러오기)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useAuthStore에 있는 이름을 제외한 내용들 (사용자 타입, 프로필이미지, 현직 여부 등등)이 모두 null로 뜨는 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useAuthStore에 제대로 정보를 담아주지 못하나..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 먼저 useAuthStore를 console로 찍어봄.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과:&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;27&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mZiWD/btsJ5nQ5N0H/jEyNEyEqBa3FlEbb7FfQn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mZiWD/btsJ5nQ5N0H/jEyNEyEqBa3FlEbb7FfQn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mZiWD/btsJ5nQ5N0H/jEyNEyEqBa3FlEbb7FfQn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmZiWD%2FbtsJ5nQ5N0H%2FjEyNEyEqBa3FlEbb7FfQn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;350&quot; height=&quot;27&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;27&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. useAuthStore에 담긴 내용을 console로 찍어봄&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1728918729197&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(userId, userName, userType, userImg, mentoCurrent, mentoWorkExperience);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과:&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;21&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oNDH6/btsJ5qmGuvI/OiyAiQIwT8Mav8I6ZHZlD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oNDH6/btsJ5qmGuvI/OiyAiQIwT8Mav8I6ZHZlD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oNDH6/btsJ5qmGuvI/OiyAiQIwT8Mav8I6ZHZlD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoNDH6%2FbtsJ5qmGuvI%2FOiyAiQIwT8Mav8I6ZHZlD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;339&quot; height=&quot;21&quot; data-origin-width=&quot;339&quot; data-origin-height=&quot;21&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. useAuthStore에 값이 어떻게 들어가나 확인&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1728918991454&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (authData) {
      useAuthStore.setState({
        isLoggedIn: true,
        userId: formData.user_id
      });
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 페이지에서 authData가 있을 때 userId만 담고 있는 것을 확인했다 !!&lt;/p&gt;
&lt;pre id=&quot;code_1728919868461&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 폼 제출 함수
  const onSubmit: SubmitHandler&amp;lt;FormData&amp;gt; = async (formData) =&amp;gt; {
    const supabase = createClient();

    // auth 테이블에서 id와 일치하는 행의 이메일을 가져옴
    const { data: userData, error: userError } = await supabase
      .from('auth')
      .select('email')
      .eq('user_id', formData.user_id)
      .single();

    if (userError || !userData) {
      console.log('사용자정보가 없습니다. =&amp;gt; ', userError);
      return;
    }

    // 위에서 가져온 이메일로 로그인
    const { data: authData, error } = await supabase.auth.signInWithPassword({
      email: formData.user_id,
      password: formData.user_pw
    });

    if (error) console.error(error);
    if (authData) {
      useAuthStore.setState({
        isLoggedIn: true,
        userId: watch('user_id'),
        userName: watch('user_name'),
        userEmail: watch('email'),
        userImg: watch('image_url'),
        userType: watch('user_type'),
        mentoCurrent: watch('mento_current'),
        mentoWorkExperience: watch('mento_work_experience')
      });
    }
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 수정하고, console에 찍히는 데이터를 확인해보니&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;332&quot; data-origin-height=&quot;49&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c39X4p/btsJ5e04xPt/KZJwWWr0xPMHuqbkMKOLmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c39X4p/btsJ5e04xPt/KZJwWWr0xPMHuqbkMKOLmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c39X4p/btsJ5e04xPt/KZJwWWr0xPMHuqbkMKOLmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc39X4p%2FbtsJ5e04xPt%2FKZJwWWr0xPMHuqbkMKOLmK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;332&quot; height=&quot;49&quot; data-origin-width=&quot;332&quot; data-origin-height=&quot;49&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;userId 빼고는 그냥 아예 증발함&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 로그인 로직을 수정&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1728954485798&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; // 위에서 가져온 이메일로 로그인
    const { data: authData, error } = await supabase.auth.signInWithPassword({
      email: formData.user_id,
      password: formData.user_pw
    });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&amp;nbsp; 위 코드의 signInWithPassword는 email 기반으로 인증하는 함수인데 나는 user_id를 넘기고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 userData.email로 수정하고&lt;/p&gt;
&lt;pre id=&quot;code_1728954747343&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (authData) {
  useAuthStore.setState({
    isLoggedIn: true,
    userId: watch('user_id'),
    userName: watch('user_name'),
    userEmail: watch('email'),
    userImg: watch('image_url'),
    userType: watch('user_type'),
    mentoCurrent: watch('mento_current'),
    mentoWorkExperience: watch('mento_work_experience')
  });
  console.log(authData);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;watch(&quot;&quot;)는 회원가입에서는 적절했지만 로그인에선 적절하지 않았다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜냐면 input에 입력한 값을 추적해 가져오는건데 내가 하려는건&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용자가 아이디를 입력하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 그 아이디로 auth테이블에서 입력한 아이디가 일치하는 행을 찾아&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 그 행의 이메일로 로그인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 로그인하면 해당 행에 있는 user_id, user_type, email등을 authData에 넣어주기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이고, 인풋은 아이디와 비밀번호를 입력하는 인풋 뿐이다! 그러므로 watch(&quot;&quot;)를 사용하는 것은 잘못된 것.&lt;/p&gt;
&lt;pre id=&quot;code_1728954890671&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 폼 제출 함수
  const onSubmit: SubmitHandler&amp;lt;FormData&amp;gt; = async (formData) =&amp;gt; {
    const supabase = createClient();

    // auth 테이블에서 id와 일치하는 행의 이메일을 가져옴
    const { data: userData, error: userError } = await supabase
      .from('auth')
      .select('email, user_id, user_name, user_type, image_url, mento_current, mento_work_experience')
      .eq('user_id', formData.user_id)
      .single();

    if (userError || !userData) {
      console.log('사용자정보가 없습니다. =&amp;gt; ', userError);
      return;
    }

    // 위에서 가져온 이메일로 로그인
    const { data: authData, error } = await supabase.auth.signInWithPassword({
      email: userData.email,
      password: formData.user_pw
    });

    if (error) console.error(error);
    if (authData) {
      useAuthStore.setState({
        isLoggedIn: true,
        userId: userData.user_id,
        userName: userData.user_name,
        userEmail: userData.email,
        userImg: userData.image_url,
        userType: userData.user_type,
        mentoCurrent: userData.mento_current,
        mentoWorkExperience: userData.mento_work_experience
      });

      console.log(authData);
    }
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 수정하고 로그인하니&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEjAlQ/btsJ5AJqalI/NxzbaPKP43De5hPeKzcWn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEjAlQ/btsJ5AJqalI/NxzbaPKP43De5hPeKzcWn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEjAlQ/btsJ5AJqalI/NxzbaPKP43De5hPeKzcWn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEjAlQ%2FbtsJ5AJqalI%2FNxzbaPKP43De5hPeKzcWn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;282&quot; height=&quot;218&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 찍힌다 !! 그리고 마이페이지에서도 정보가 찍히나 확인했는데&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;44&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVBLSI/btsJ4nEtA5S/7pMb0TyMeLdrghQJ9mb4e0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVBLSI/btsJ4nEtA5S/7pMb0TyMeLdrghQJ9mb4e0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVBLSI/btsJ4nEtA5S/7pMb0TyMeLdrghQJ9mb4e0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVBLSI%2FbtsJ4nEtA5S%2F7pMb0TyMeLdrghQJ9mb4e0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;299&quot; height=&quot;44&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;44&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 url까지 잘 들어온다!! 이 로그인 정보는 user_type이 멘티여서 mento타입과 관련된 부분은 null로 표시되는 것이므로 정상적으로 들어오는것이 맞다!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  현재 풀어야 할 문제&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. 리다이렉트 (1순위)&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;로그인 한 사용자는 로그인/회원가입페이지에 접근할 수 없게 하는것 까진 했는데&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;마이페이지에도 접근을 못함&lt;/i&gt;&lt;/s&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;회원가입 할 때마다 정보가 두 개씩 쌓임&lt;/s&gt; + &lt;s&gt;userData에 null이 찍힘&lt;/s&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;미들웨어 로직을 짜놔서 , useEffect를 안써도 middleware에서 사용자를 감지해 자동으로 페이지를 리다이렉트 시켜주는 것인데 이 부분이 해결되지않음. 어제는 분명 됐던거같은데 오늘 다시시도하니까 리디렉션한 횟수가 너무 많다고 뜸&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 로그인상태일 때 페이지를 새로고침 하면 로그아웃 버튼이 페이지가 렌더링 되기 전까지 로그인으로 표시되다가 페이지가 렌더링된 이후 로그아웃으로 바뀌는 문제 + 마이페이지에서 새로고침하면 정보없음이 잠깐! 보이는문제(3순위)&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. &lt;s&gt;로그인 할 때 사용자에게 cookie를 set 해주는 로직 추가하기 + 사용자 정보 넣어주기&lt;/s&gt;&amp;nbsp; =&amp;gt; 해결&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;4. &lt;s&gt;마이페이지 만들고 사용자 정보 불러오기&lt;/s&gt; + 수정하기 기능&amp;nbsp; =&amp;gt; auth 테이블의 정보는 잘 불러오는데 다른 테이블의 정보도 연결해서 가져와야함&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;5. Authentication이랑 auth테이블에서 특정 유저 정보가 삭제되지 않는 문제&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;➕ 추가 해야 할 것&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. 회원가입시 포인트 지급 &amp;amp; 로그인시 포인트 지급&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/95</guid>
      <comments>https://playhong.tistory.com/95#entry95comment</comments>
      <pubDate>Tue, 15 Oct 2024 00:33:25 +0900</pubDate>
    </item>
    <item>
      <title>241014</title>
      <link>https://playhong.tistory.com/94</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 회원가입&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블에 정보가 두개씩 쌓임&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u6dyP/btsJ4XqxXNU/p7axKZ8JkuVtkXdk9TEBC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u6dyP/btsJ4XqxXNU/p7axKZ8JkuVtkXdk9TEBC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u6dyP/btsJ4XqxXNU/p7axKZ8JkuVtkXdk9TEBC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu6dyP%2FbtsJ4XqxXNU%2Fp7axKZ8JkuVtkXdk9TEBC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1305&quot; height=&quot;73&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;73&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1728865723687&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; // 폼 제출 함수
  const onSubmit: SubmitHandler&amp;lt;FormData&amp;gt; = async (formData) =&amp;gt; {
    // Supabase에 사용자 등록
    const { data, error: supabaseTableError } = await browserClient.auth.signUp({
      email: formData.email,
      password: formData.user_pw
    });

    if (supabaseTableError) {
      console.log('supabaseTableError =&amp;gt;', supabaseTableError);
      return;
    }

    if (!data.user) {
      console.error('이미 가입된 정보입니다.');
      return;
    }

    const { error } = await browserClient.from('auth').insert({
      user_id: formData.user_id,
      user_pw: formData.user_pw,
      user_type: 'mentee',
      email: formData.email,
      user_name: formData.user_name,
      image_url: formData.image_url,
      id: data.user.id
    });

    if (error) {
      console.log('error =&amp;gt; ', error);
    } else {
      console.log('success =&amp;gt;', data);
    }
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 폼제출 함수를 어딘가 잘못 작성한 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;시도1. 폼 제출 함수를 하나로 합쳐보자&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const { error } = ~~ 부분을 삭제하고 const { data, error ~ 부분에 해당 내용을 넣는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728894245840&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { data, error: supabaseTableError } = await browserClient.auth.signUp({
  email: formData.email,
  password: formData.user_pw,
  options: {
    data: {
      user_id: formData.user_id,
      user_pw: formData.user_pw,
      user_name: formData.user_name,
      user_type: formData.user_type,
      image_url: formData.image_url,
    }
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과: auth테이블에 하나씩만 쌓이긴 하는데, user_pw에 user_name값이 들어가고 user_name에 user_pw값이 쌓이고 user_id에 email값이 쌓임&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도2. 기존에 있던 const { error } ~ 부분을 수정하자&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inblog.ai/luke/supabase-%EC%B4%88%EA%B8%B0%EC%85%8B%ED%8C%85-%EB%B0%8F-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-22311&quot;&gt;https://inblog.ai/luke/supabase-%EC%B4%88%EA%B8%B0%EC%85%8B%ED%8C%85-%EB%B0%8F-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-22311&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기 나와있는 대로 따라해봤다.&lt;/p&gt;
&lt;pre id=&quot;code_1728894331081&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { data, error: supabaseTableError } = await browserClient.auth.signUp({
  email: formData.email,
  password: formData.user_pw
});

if (supabaseTableError) {
  console.log('supabaseTableError =&amp;gt;', supabaseTableError);
  return;
}

if (!data.user) {
  console.error('이미 가입된 정보입니다.');
  return;
}

const userData = await browserClient.from('auth').insert({
  user_id: formData.user_id,
  user_pw: formData.user_pw,
  user_type: 'mentee',
  email: data.user?.email,
  user_name: formData.user_name,
  image_url: formData.image_url,
  id: data.user?.id
});
console.log(userData);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;결과: 여전히 두개씩 쌓임, 특이점은 마지막에 console.log로 찍어본 userData에 아무런 값이 찍혀있지 않다는거 근데 테이블은 두개씩 쌓이는 중이다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;171&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvkSci/btsJ4XYpnWe/32EkrT7DsKkHLeMltdxaY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvkSci/btsJ4XYpnWe/32EkrT7DsKkHLeMltdxaY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvkSci/btsJ4XYpnWe/32EkrT7DsKkHLeMltdxaY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvkSci%2FbtsJ4XYpnWe%2F32EkrT7DsKkHLeMltdxaY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;426&quot; height=&quot;171&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;171&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도3. const { error } ~ 부분의 insert를 uuid를 찾아 update하는 방향으로 수정.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;튜터님께 질문해서 uuid가 일치하는 행을 선택해 수정하는 방향으로 다시 작성.&lt;/p&gt;
&lt;pre id=&quot;code_1728894389762&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  const onSubmit = async () =&amp;gt; {
    console.log(watch('user_id'));
    // Supabase에 사용자 등록
    const { data, error: supabaseTableError } = await browserClient.auth.signUp({
      email: formData.email,
  	  password: formData.user_pw
    });
    console.log(data);
    if (supabaseTableError) {
      console.log('supabaseTableError =&amp;gt;', supabaseTableError);
      return;
    }

    if (!data.user) {
      console.error('이미 가입된 정보입니다.');
      return;
    }
  const { data: userData, error: updateError } = await browserClient
    .from('auth')
    .update({
      user_id: formData.user_id,
      user_pw: formData.user_pw,
      user_type: 'mentee',
      email: formData.email,
      user_name: formData.user_name,
      image_url: formData.image_url
    })
    .eq('id', data.user.id);

  if (updateError) {
    console.log('회원가입에 실패했습니다 =&amp;gt; ', updateError);
  } else {
    console.log('회원가입에 성공했습니다 =&amp;gt;', userData);
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과:&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;36&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LKbhY/btsJ6esaN87/pMSg7vb5ZWL6xFDJoYztl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LKbhY/btsJ6esaN87/pMSg7vb5ZWL6xFDJoYztl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LKbhY/btsJ6esaN87/pMSg7vb5ZWL6xFDJoYztl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLKbhY%2FbtsJ6esaN87%2FpMSg7vb5ZWL6xFDJoYztl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1394&quot; height=&quot;36&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;36&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아이디에 이메일이 쌓이고 나머지에 아무것도 쌓이지 않음.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfYta3/btsJ4OgVBnz/wiV1qvKH8B3LZ1zngBh9k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfYta3/btsJ4OgVBnz/wiV1qvKH8B3LZ1zngBh9k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfYta3/btsJ4OgVBnz/wiV1qvKH8B3LZ1zngBh9k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfYta3%2FbtsJ4OgVBnz%2FwiV1qvKH8B3LZ1zngBh9k0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;389&quot; height=&quot;52&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;console에는 null이 찍힘&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도4. 해결!!!!!!!!!!!!!!!&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;i&gt;&lt;b&gt; react-hook-form&lt;/b&gt; &lt;/i&gt;문법에 대해 조금만 더 잘 알았더라면!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;i&gt;&lt;b&gt;RLS&lt;/b&gt;&lt;/i&gt;에 대해 조금만 더 잘 알았더라면!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 시도3에서 작성한 로직 자체는 문제가 없었음 !!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. RLS 로직 설정&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/miNdP/btsJ33sF9hz/3978N4eQAHaJki5Bduxsi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/miNdP/btsJ33sF9hz/3978N4eQAHaJki5Bduxsi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/miNdP/btsJ33sF9hz/3978N4eQAHaJki5Bduxsi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmiNdP%2FbtsJ33sF9hz%2F3978N4eQAHaJki5Bduxsi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;85&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;Auth policies에서&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chqXfE/btsJ4ibRgsz/ZwCQZxH46vXKO46TQTZvhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chqXfE/btsJ4ibRgsz/ZwCQZxH46vXKO46TQTZvhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chqXfE/btsJ4ibRgsz/ZwCQZxH46vXKO46TQTZvhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchqXfE%2FbtsJ4ibRgsz%2FZwCQZxH46vXKO46TQTZvhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;574&quot; height=&quot;357&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;UPDATE를 수정해 줘야 했음.&lt;/p&gt;
&lt;pre id=&quot;code_1728897075200&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;create policy &quot;Enable update for users based on email&quot;
on &quot;public&quot;.&quot;auth&quot;
for update using (
  (select auth.jwt()) -&amp;gt;&amp;gt; 'email' = email
) with check (
  (select auth.jwt()) -&amp;gt;&amp;gt; 'email' = email
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본으로 이렇게 적혀있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;auth 테이블의 이메일과 로그인 한 사용자의 이메일과 일치할 때만 수정 권한을 주고 있는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 수정이 되지 않아서 (아직 로그인 전 이니까!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728897128424&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;alter policy &quot;Enable update for users based on email&quot;
on &quot;public&quot;.&quot;auth&quot;
to public
using (
  true
with check (
  true
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정이 가능하도록 true로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 수정해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. react-hook-form 문법 바르게 사용하기&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728894602185&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리액트 훅 폼으로 유효성 검사
const { register, handleSubmit, formState, watch } = useForm({
mode: 'onChange',
defaultValues: {
  user_id: '',
  user_pw: '',
  user_type: 'mentee',
  email: '',
  user_name: '',
  image_url: ''
},
resolver: zodResolver(signUpSchema)
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 useForm을 하용해 register, handleSubmit, formState, watch를 불러왔는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;watch&lt;/b&gt; : watch('키값')으로 값을 뽑아낼 수 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;handleSubmit&lt;/b&gt; : 인자로 함수(폼제출함수)를 받는데, handleSubmit을 사용하고 있는 form태그 아래에 있는 input들이 유효하면&amp;nbsp; 인자로 있는 함수&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;(폼제출함수)&lt;/span&gt; 가 실행이 됨!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;register&lt;/b&gt; : 인자로 받는 input 요소를 React hook form과 연결시켜 검증 규칙을 적용할 수 있게 해줌!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; &amp;lt;input {...register('id')}/&amp;gt; 이런식으로 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;formState&lt;/b&gt; : form 전체의 state!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 메서드 들을 이용했다. (이것들의 활용 방법을 몰라서 많이 헤맸음!)&lt;/p&gt;
&lt;pre id=&quot;code_1728905346620&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 폼 제출 함수
  const onSubmit = async () =&amp;gt; {
    // Supabase에 사용자 등록
    const { data, error: supabaseTableError } = await browserClient.auth.signUp({
      email: watch('email'),
      password: watch('user_pw')
    });

    if (supabaseTableError) {
      console.log('supabaseTableError =&amp;gt;', supabaseTableError);
    }

    if (!data.user) {
      console.error('이미 가입된 정보입니다.');
      return;
    }

    const { data: userData, error: updateError } = await browserClient
      .from('auth')
      .update({
        user_id: watch('user_id'),
        user_pw: watch('user_pw'),
        user_type: 'mento',
        email: watch('email'),
        user_name: watch('user_name'),
        image_url: watch('image_url'),
        mento_current: watch('mento_current'),
        mento_work_experience: watch('mento_work_experience')
      })
      .eq('id', data.user.id);
    console.log(userData);

    if (updateError) {
      console.log('회원가입에 실패했습니다 =&amp;gt; ', updateError);
    } else {
      console.log('회원가입에 성공했습니다 =&amp;gt;', userData);
    }
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 watch(&quot;&quot;)로 인풋에 작성된 값들을 뽑아 사용할 수 있는것!&lt;/p&gt;
&lt;pre id=&quot;code_1728906447459&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;label htmlFor=&quot;user_id&quot;&amp;gt;아이디&amp;lt;/label&amp;gt;
      &amp;lt;input {...register('user_id')} id=&quot;user_id&quot; type=&quot;text&quot; required /&amp;gt;
      {formState.errors.user_id &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{formState.errors.user_id.message}&amp;lt;/span&amp;gt;}
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;label htmlFor=&quot;user_pw&quot;&amp;gt;비밀번호&amp;lt;/label&amp;gt;
      &amp;lt;input {...register('user_pw')} id=&quot;user_pw&quot; type=&quot;password&quot; required /&amp;gt;
      {formState.errors.user_pw &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{formState.errors.user_pw.message}&amp;lt;/span&amp;gt;}
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;label htmlFor=&quot;user_name&quot;&amp;gt;닉네임&amp;lt;/label&amp;gt;
      &amp;lt;input {...register('user_name')} id=&quot;user_name&quot; type=&quot;text&quot; required /&amp;gt;
      {formState.errors.user_name &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{formState.errors.user_name.message}&amp;lt;/span&amp;gt;}
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;label htmlFor=&quot;email&quot;&amp;gt;이메일&amp;lt;/label&amp;gt;
      &amp;lt;input {...register('email')} id=&quot;email&quot; type=&quot;email&quot; required /&amp;gt;
      {formState.errors.email &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{formState.errors.email.message}&amp;lt;/span&amp;gt;}
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;label htmlFor=&quot;image_url&quot;&amp;gt;프로필 이미지 업로드&amp;lt;/label&amp;gt;
      &amp;lt;input type=&quot;file&quot; accept=&quot;image/*&quot; onChange={handleImgUpload} /&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;Button
      onClick={() =&amp;gt; {
        console.log('회원가입 폼 제출됨');
      }}
      type=&quot;submit&quot;
    &amp;gt;
      회원가입
    &amp;lt;/Button&amp;gt;
  &amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 form태그에 onSubmit으로 handleSubmit을 넣어주는데 인자를 폼제출 함수인 onSubmit으로 넣어주면 된다!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 페이지 리다이렉트 (로그인/로그아웃/마이페이지 접근 막기)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 접근을 막는것은 미들웨어 설정만으로도 가능한것 같은데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 미들웨어 설정뿐만 아니라 useEffect와 route를 사용해 적용함 =&amp;gt; 페이지 깜빡임이 생김&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인된 사용자가 로그인 페이지에 이동하려다 다시 홈페이지로 이동하는 과정에서 로그인 페이지가 살짝! 보였다가 이동되는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 더해 미들웨어에 설정한 로그인상태의 사용자가 마이페이지로의 이동하면 다시 메인페이지로 리다이렉트되는것..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인상태의 사용자는 본인의 마이페이지에 접근할 수 있어야 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미들웨어의 설정이 잘못 되었나?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도1. 공식문서를 참고해 작성&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1728907144019&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function middleware1(request: NextRequest) {
  const currentUser = request.cookies.get('currentUser')?.value;

  // 리다이렉트 조건

  // 로그인 안된 상태면 login으로 리다이렉트
  if (!currentUser) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // 로그인된 사용자가 /login, /signup/mentee, /signup/mento에 접근하는 경우 홈으로 리다이렉트
  const redirectPaths = ['/login', '/signup/mentee', '/signup/mento'];
  if (currentUser &amp;amp;&amp;amp; redirectPaths.includes(request.nextUrl.pathname)) {
    return Response.redirect(new URL('/', request.url));
  }
  // 로그인인된 사용자만 마이페이지로 시작하는 url에 접근하도록 허용
  if (currentUser &amp;amp;&amp;amp; !request.nextUrl.pathname.startsWith('/mypage')) {
    return Response.redirect(new URL('/mypage', request.url)); // 마이페이지로 접근 허용
  }
}

export const config = {
  // 이 Middleware가 동작할 경로들을 추가해주면된다.
  matcher: ['/login', '/signup/mentee', '/signup/mento', '/mypage/:path*']
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과: 여전히 안됨! 이렇게 작성하면 useEffect 등을 삭제해도 리다이렉트 되는게 아닌가?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도2. 다른 사람의 글을 참고&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@ryanbae94/NEXT.JS-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%91%EA%B7%BC-%EC%A0%9C%ED%95%9Cmiddleware&quot;&gt;https://velog.io/@ryanbae94/NEXT.JS-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%91%EA%B7%BC-%EC%A0%9C%ED%95%9Cmiddleware&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;리다이렉트 될 때 페이지가 깜빡거린다는 점도 같아 이 블로그의 글을 참고해 다시 수정해봤다.&lt;/p&gt;
&lt;pre id=&quot;code_1728907192403&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const protectedRoutes = ['/mypage/:path*']; // 로그인 정보가 있어야만 접근할 수 있는 페이지
const publicRoutes = ['/login', '/logout'];
// 로그인 하지 않을 경우 접근할 수 있는 페이지

export function middleware(request: NextRequest) {
  const token = request.cookies.get('accessToken');
  const currentPath = request.nextUrl.pathname;
  console.log(token);

  if (!token &amp;amp;&amp;amp; protectedRoutes.includes(currentPath)) {
    const url = request.nextUrl.clone();
    url.pathname = '/login';
    return NextResponse.redirect(url);
  }

  if (token &amp;amp;&amp;amp; publicRoutes.includes(currentPath)) {
    const url = request.nextUrl.clone();
    url.pathname = '/';
    return NextResponse.redirect(url);
  }

  return NextResponse.next();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과: 여전히 안됨!&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 든 생각.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지금 위에 console.log로 찍어본 userData에 아무런 값이 찍혀있지 않는 것이 이것과 연관있지 않을까? 토큰이 없어서? 근데 isLoggedIn은 true로 찍히니까 로그인 버튼이 로그아웃으로 바뀌는거 아닌가? 정말 모르겠다..&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도3. use client를 뺀다!&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 깜빡임 현상은 클라이언트 컴포넌트에 문제되는 현상이라고 말씀해주셨음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼? SSR을 사용하면 되지 않나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 useEffect, router도 없겠다 'use client'도 삭제했는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react-hook-form에서 문제가 된 것&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/devzBg/btsJ6SvHeqt/cJk8r6Cu1ojBA7mrndmhsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/devzBg/btsJ6SvHeqt/cJk8r6Cu1ojBA7mrndmhsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/devzBg/btsJ6SvHeqt/cJk8r6Cu1ojBA7mrndmhsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdevzBg%2FbtsJ6SvHeqt%2FcJk8r6Cu1ojBA7mrndmhsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;525&quot; height=&quot;190&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;검색해봤더니 같은 문제를 겪은 내용이 나왔는데, 해결방법이&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDNUgD/btsJ5A3COjy/r0IbBeD9WTyKmZK9IjqmgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDNUgD/btsJ5A3COjy/r0IbBeD9WTyKmZK9IjqmgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDNUgD/btsJ5A3COjy/r0IbBeD9WTyKmZK9IjqmgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDNUgD%2FbtsJ5A3COjy%2Fr0IbBeD9WTyKmZK9IjqmgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;360&quot; height=&quot;71&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;아..&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시도 4. middleware의 위치를 변경 + tsconfig.json에 &quot;middleware.ts&quot; 추가&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;br /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새벽에 튜터님께서 도움을 주시고 가셧다!ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/routing/middleware&quot;&gt;https://nextjs.org/docs/app/building-your-application/routing/middleware&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG78Cb/btsJ6Iz4vL5/Lf3volu4A3veNsrPaAwIA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG78Cb/btsJ6Iz4vL5/Lf3volu4A3veNsrPaAwIA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG78Cb/btsJ6Iz4vL5/Lf3volu4A3veNsrPaAwIA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG78Cb%2FbtsJ6Iz4vL5%2FLf3volu4A3veNsrPaAwIA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;643&quot; height=&quot;118&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;미들웨어의 위치를 조금 더 밖으로 빼야 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우엔 src/utils/supabase폴더 안에 깊게 넣어놨었는데 이걸 src폴더로 옮겨주었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 tsconfig.json 파일에 가서&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728921456868&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &quot;include&quot;: [&quot;next-env.d.ts&quot;, &quot;**/*.ts&quot;, &quot;**/*.tsx&quot;, &quot;.next/types/**/*.ts&quot;, &quot;middleware.ts&quot;],&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 include부분에 middleware.ts를 넣어준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 하니 이제 깜빡임없이 잘 이동된다!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 문제는&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728921279412&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function middleware(request: NextRequest) {
  const currentUser = request.cookies.get('currentUser')?.value;
  console.log(currentUser);
  // 리다이렉트 조건

  // 로그인 안된 상태면 login으로 리다이렉트
  if (!currentUser) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // 로그인된 사용자가 /login, /signup/mentee, /signup/mento에 접근하는 경우 홈으로 리다이렉트
  const redirectPaths = ['/login', '/signup/mentee', '/signup/mento'];
  if (currentUser &amp;amp;&amp;amp; redirectPaths.includes(request.nextUrl.pathname)) {
    return NextResponse.redirect(new URL('/', request.url));
  }
  // 로그인인된 사용자만 마이페이지로 시작하는 url에 접근하도록 허용
  if (currentUser &amp;amp;&amp;amp; !request.nextUrl.pathname.startsWith('/mypage')) {
    return NextResponse.redirect(new URL('/mypage', request.url)); // 마이페이지로 접근 허용
  }

  return NextResponse.next();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드를 보면 로그인 한 사용자의 쿠키를 바탕으로 페이지를 이동시키는 것인데, 나는 로그인할 때 쿠키를 set 해주는 로직을 아직 짜지 않았다..&lt;/p&gt;
&lt;pre id=&quot;code_1728921347373&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { isLoggedIn } = useAuthStore();
  const router = useRouter();

  // 이미 로그인한 사용자인지 구분해서 접근막기
  useEffect(() =&amp;gt; {
    if (isLoggedIn) {
      router.replace('/');
    }
  }, [isLoggedIn, router]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 이 로직 때문에 제대로 움직이는 것 처럼 보이는게 아닐까 싶은데 이건 로그인 페이지 로직에서 수정을 해줘야 될 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아닌거같다 여전히 깜빡이는거같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 로그인할 때 쿠키를 set해주고 따져봐야겠다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  현재 풀어야 할 문제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 리다이렉트 (2순위)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 한 사용자는 로그인/회원가입페이지에 접근할 수 없게 하는것 까진 했는데 &lt;i&gt;마이페이지에도 접근을 못함&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이미지업로드 (4순위)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토리지에 이미지를 업로드하는 로직을 구성하긴 했는데 이미지가 정상적으로 올라가지지않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;s&gt;3. 회원가입시 정보가 두개씩 쌓이는 문제 (1순위)&lt;/s&gt;&lt;/i&gt;&amp;nbsp; =&amp;gt; 해결!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원가입 할 때마다 정보가 두 개씩 쌓임 + userData에 null이 찍힘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 로그인상태일 때 페이지를 새로고침 하면 로그아웃 버튼이 페이지가 렌더링 되기 전까지 로그인으로 표시되다가 페이지가 렌더링된 이후 로그아웃으로 바뀌는 문제 (3순위)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;➕ 추가 해야 할 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 마이페이지 만들고 수정하기 기능&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 회원가입시 포인트 지급 &amp;amp; 로그인시 포인트 지급&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❓ 궁금한점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서에 따르라고 해서 context를 만들고 provider로 감쌌는데 이걸 어디서 어떻게 활용하는건지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 이 부분은 로그인/회원가입에서 따로 사용할 일은 없다고 하셨음 ! 다만 다른 팀원 분들이 로그인 상태를 가지고 뭔가 로직을 짤 때 필요할 수 있으므로 만들어 두는게 적절함!!&lt;/p&gt;</description>
      <category>TIL</category>
      <category>가취뽀</category>
      <category>트러블슈팅</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/94</guid>
      <comments>https://playhong.tistory.com/94#entry94comment</comments>
      <pubDate>Mon, 14 Oct 2024 14:04:36 +0900</pubDate>
    </item>
    <item>
      <title>241013</title>
      <link>https://playhong.tistory.com/93</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 회원가입/로그인페이지에 이미 로그인한 사용자가 접근하는 것을 막기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1728827085415&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useRouter } from 'next/router';

const { isLoggedIn } = useAuthStore();
  const router = useRouter();

  // 이미 로그인한 사용자인지 구분해서 접근막기
  useEffect(() =&amp;gt; {
    if (isLoggedIn) {
      router.replace('/');
    }
  }, [isLoggedIn, router]);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/toAPD/btsJ4qUb9ll/kdOnEIaYt3aWuO7ESYSPck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/toAPD/btsJ4qUb9ll/kdOnEIaYt3aWuO7ESYSPck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/toAPD/btsJ4qUb9ll/kdOnEIaYt3aWuO7ESYSPck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtoAPD%2FbtsJ4qUb9ll%2FkdOnEIaYt3aWuO7ESYSPck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;522&quot; height=&quot;183&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;오류: NextRouter가 마운트되지 않았습니다. https://nextjs.org/docs/messages/next-router-not-mounted&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nextjs.org/docs/messages/next-router-not-mounted&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://nextjs.org/docs/messages/next-router-not-mounted&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위는 공식문서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4vMPd/btsJ4tiXqBf/Ri8NdZRpKng8C01HtJ8hvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4vMPd/btsJ4tiXqBf/Ri8NdZRpKng8C01HtJ8hvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4vMPd/btsJ4tiXqBf/Ri8NdZRpKng8C01HtJ8hvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4vMPd%2FbtsJ4tiXqBf%2FRi8NdZRpKng8C01HtJ8hvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;770&quot; height=&quot;241&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서에는 next/navigation으로 마이그레이션 하라고 되어있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;next/router로 되어있는 것을 navigation으로 수정하지 제대로 된다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고) &lt;a href=&quot;https://velog.io/@meek/Error-NextRouter-was-not-mounted-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@meek/Error-NextRouter-was-not-mounted-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <category>가취뽀</category>
      <category>트러블슈팅</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/93</guid>
      <comments>https://playhong.tistory.com/93#entry93comment</comments>
      <pubDate>Sun, 13 Oct 2024 23:25:37 +0900</pubDate>
    </item>
    <item>
      <title>241012</title>
      <link>https://playhong.tistory.com/92</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 로그인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 시, 정확한 정보를 입력해도 Invalid login credentials(잘못된 로그인 자격증명)이라고 뜨는 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제출 폼 함수의&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728717229470&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { data, error } = await supabase.auth.signInWithPassword({
      email: formData.user_id,
      password: formData.user_pw
    });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분이 문제가 되는게 아닐까 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 supabase에서 제공하는 이메일로 로그인 할 때 사용되는 로직인데, 나는 사용자의 id(uid가 아닌 가입시 사용자가 직접 입력하는 id)로 로그인하도록 하고 싶어서 email: user_id로 하면 알아서 아이디로 로그인 되지 않을까? 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러: 응안돼&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 너무 납작하게 생각했던 것이었고, 이메일을 아이디로 사용한다면 모를까 나처럼 이메일, 아이디를 따로 나눠 사용하는 경우엔 사용자가 입력한 아이디로 사용자의 이메일을 데이터베이스에서 조회해 해당 메일로 로그인을 해야 하는것!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 email: formData.user_id로는 안되는 것이다..&lt;/p&gt;
&lt;pre id=&quot;code_1728718301381&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { data: userData, error: userError } = await supabase
      .from('auth')
      .select('email')
      .eq('user_id', formData.user_id)
      .single();

    if (userError || !userData) {
      console.log('사용자정보가 없습니다. =&amp;gt; ', userError);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 auth테이블에 id로 사용자를 찾아서 사용자의 email 을 userData에 담는다.&lt;/p&gt;
&lt;pre id=&quot;code_1728718356917&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { data, error } = await supabase.auth.signInWithPassword({
      email: userData?.email,
      password: formData.user_pw
    });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 userData로 로그인을 시도한다&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 회원가입&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;zod와 react-hook-form을 사용해 유효성검사를 한 내용이 화면에 표시되지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 작성한 코드는 nextjs를 배우기 전, 리액트만 사용해 작성한 코드를 참고해서 폼 데이터를 useState로 관리하고 있었음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 react-hook-form과 충돌하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState를 삭제하고 react-hook-form으로 상태를 관리하기.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인, 멘티 회원가입, 멘토 회원가입 이 세 군데에서 사용하고 있었는데, 회원가입은 로직이 많아 복잡해 일단 로그인페이지부터 수정해봤다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728808925456&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// zod
  const signInSchema = z.object({
    user_id: z.string().min(1, '아이디는 필수입니다.'),
    user_pw: z.string().min(6, '비밀번호는 최소 6자리 이상이어야 합니다.')
  });

  // 리액트 훅 폼으로 유효성 검사
  const { register, handleSubmit, formState } = useForm({
    mode: 'onChange',
    defaultValues: {
      user_id: '',
      user_pw: ''
    },
    resolver: zodResolver(signInSchema)
  });
  
  type FormData = {
    user_id: string;
    user_pw: string;
    email?: string;
  };

// 폼 제출 함수
  const onSubmit: SubmitHandler&amp;lt;FormData&amp;gt; = async (formData) =&amp;gt; {
    const supabase = createClient();

    // auth 테이블에서 id와 일치하는 행의 이메일을 가져옴
    const { data: userData, error: userError } = await supabase
      .from('auth')
      .select('email')
      .eq('user_id', formData.user_id)
      .single();

    if (userError || !userData) {
      console.log('사용자정보가 없습니다. =&amp;gt; ', userError);
    }

    // 위에서 가져온 이메일로 로그인
    const { data: authData, error } = await supabase.auth.signInWithPassword({
      email: userData?.email,
      password: formData.user_pw
    });

    if (error) console.error(error);
    if (authData) {
      useAuthStore.setState({
        isLoggedIn: true,
        userId: formData.user_id
      });
    }
  };
  
  return (
    &amp;lt;section&amp;gt;
      &amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
        &amp;lt;input {...register('user_id')} type=&quot;text&quot; placeholder=&quot;아이디&quot; required /&amp;gt;
        {formState.errors.user_id &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{formState.errors.user_id.message}&amp;lt;/span&amp;gt;}
        &amp;lt;input {...register('user_pw')} type=&quot;password&quot; placeholder=&quot;비밀번호&quot; required /&amp;gt;
        {formState.errors.user_pw &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{formState.errors.user_pw.message}&amp;lt;/span&amp;gt;}
        &amp;lt;Button
          onClick={() =&amp;gt; {
            console.log('로그인 폼 제출됨');
          }}
          type=&quot;submit&quot;
        &amp;gt;
          로그인
        &amp;lt;/Button&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;p&amp;gt;아직 회원이 아니신가요?&amp;lt;/p&amp;gt; &amp;lt;Link href={'/signup'}&amp;gt;회원가입&amp;lt;/Link&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/section&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 작성하니 유효성 검사 결과가 에러없이 정상적으로 효시됨!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 로그인 페이지를 바탕으로 회원가입페이지까지 작성하면 되겠다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <category>가취뽀</category>
      <category>트러블슈팅</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/92</guid>
      <comments>https://playhong.tistory.com/92#entry92comment</comments>
      <pubDate>Sat, 12 Oct 2024 16:42:34 +0900</pubDate>
    </item>
    <item>
      <title>241011</title>
      <link>https://playhong.tistory.com/91</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가취뽀 - 회원가입&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;문제발생&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유효성 검사결과가 화면에 뜨지않고 통과하지 못해도 폼이 제출되는 등 아직 문제는 많긴하지만&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원가입 버튼을 눌렀을 때 supabase에 가입 정보가 등록되는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;supabase에서 제공해주는 Authentication(암호화가능한?유저테이블)에는 가입데이터가 다 쌓이는거 같은데 (제공되는 컬럼이랑 내가 저장해야하는 데이터랑 일치하지 않는 부분이 많아 전부 확인은 못했지만..) 내가 만든 auth테이블에는 안쌓임!! uuid랑 이메일이 들어오는데 이메일은 또 user_id에 쌓임 ㅠㅠㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인추론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;403은 권한 문제가 있을 때 발생한다고 함..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vs상에서 error를 넣어 콘솔로 확인할 수 있는 모든? 곳을 찍어봤는데도 내가 찍은 console은 찍히지 않고 그냥 403에러가 뜬다는 점에서..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xu52I/btsJ3I10bkN/KMNMXJPCYW9aovGNre1tkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xu52I/btsJ3I10bkN/KMNMXJPCYW9aovGNre1tkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xu52I/btsJ3I10bkN/KMNMXJPCYW9aovGNre1tkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxu52I%2FbtsJ3I10bkN%2FKMNMXJPCYW9aovGNre1tkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;410&quot; height=&quot;53&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UFDgd/btsJ3GXpDTP/lJMB5lXLwAvNi8qL0aoIJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UFDgd/btsJ3GXpDTP/lJMB5lXLwAvNi8qL0aoIJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UFDgd/btsJ3GXpDTP/lJMB5lXLwAvNi8qL0aoIJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUFDgd%2FbtsJ3GXpDTP%2FlJMB5lXLwAvNi8qL0aoIJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;896&quot; height=&quot;305&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAXxYx/btsJ3SXCeC4/9fF4KX3reAFgd1sp6cPKLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAXxYx/btsJ3SXCeC4/9fF4KX3reAFgd1sp6cPKLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAXxYx/btsJ3SXCeC4/9fF4KX3reAFgd1sp6cPKLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAXxYx%2FbtsJ3SXCeC4%2F9fF4KX3reAFgd1sp6cPKLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;444&quot; height=&quot;197&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무나 추가하지 못하도록 여기를 false로 해놨었는데 true로 수정하니까 정상적으로 들어온다!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;545&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMJnqj/btsJ3PzN0tZ/qYv8WDRe0xrEuymkt0tBPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMJnqj/btsJ3PzN0tZ/qYv8WDRe0xrEuymkt0tBPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMJnqj/btsJ3PzN0tZ/qYv8WDRe0xrEuymkt0tBPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMJnqj%2FbtsJ3PzN0tZ%2FqYv8WDRe0xrEuymkt0tBPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;545&quot; height=&quot;178&quot; data-origin-width=&quot;545&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결이 안된다 ㅋㅋ&lt;/p&gt;
&lt;pre id=&quot;code_1728667882257&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Supabase에 사용자 등록
    const { data, error: supabaseTableError } = await supabase.auth.signUp({
      email: formData.email,
      password: formData.user_pw
    });

// auth테이블에 등록
const { error } = await supabase.from('auth').insert({
  user_id: formData.user_id,
  user_pw: formData.user_pw,
  user_type: 'mentee',
  email: formData.email,
  user_name: formData.user_name,
  image_url: formData.image_url,
  id: data.user.id // 여기에서 'id'로 변경
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 Authentication(암호화가능한?유저테이블)에 데이터가 쌓이면 auth테이블에도 데이터를 넣어주는 로직인데 저기에 id 를 추가하고 data.user.id를 넣어주니 정상적으로 추가된다 ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL</category>
      <category>가취뽀</category>
      <category>트러블슈팅</category>
      <author>playhong</author>
      <guid isPermaLink="true">https://playhong.tistory.com/91</guid>
      <comments>https://playhong.tistory.com/91#entry91comment</comments>
      <pubDate>Sat, 12 Oct 2024 02:34:03 +0900</pubDate>
    </item>
  </channel>
</rss>