<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>생각 정리</title>
    <link>https://zet109.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 6 Apr 2026 13:06:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>stableh</managingEditor>
    <image>
      <title>생각 정리</title>
      <url>https://tistory1.daumcdn.net/tistory/2760822/attach/143c000e4d3a46b3bed9705a383d5cae</url>
      <link>https://zet109.tistory.com</link>
    </image>
    <item>
      <title>[React] react-beautiful-dnd 빠르게 작동했을 시 에러 해결</title>
      <link>https://zet109.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;워크플로우 관련 기능을 만들기 위해 react-beutiful-dnd를 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onDragEnd 함수에서 목록에 대한 값들을 업데이트하는 setState들을 사용하였다. 일반적인 경우 매우 정상적으로 작동되지만, 빠르게 사용하였을 경우 key값이 중복되었다고 하며 에러가 발생하였다.&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;구글링을 통해 확인한 결과, useState가 비동기적으로 작동하기 때문에 발생하는 에러라는 것을 확인하였다.&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;해당 문제는 react18에 도입된 flushSync를 setState에 사용하니 해결되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 flushSync의 경우, 성능저하를 일으킬 수 있으므로 일반적인 상황에서는 추천하지 않고, 공식문서에서도 최후의 수단으로 사용하라고 나와있었다.&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;최선이 아닌 차선의 방법이였지만, 이미 왠만한 방법들은 다 시도해보았기에 결국 flushSync를 사용하기로했다.&lt;/p&gt;
&lt;pre id=&quot;code_1709388180872&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const onDragEnd = (result: any) =&amp;gt; {
      if (result?.destination === null) return

      flushSync(() =&amp;gt; {
         setWorkFlowData((prevData: WorkFlowType[]): WorkFlowType[] =&amp;gt; {
            const reorder = orderSort(result, prevData);

            calcWorkFlowHeight([...reorder]);

            requestApi
               .post('/update/workflow', {
                  name: '작품1',
                  workflow: reorder,
               })
               .then((res) =&amp;gt; {})
               .catch((err) =&amp;gt; {
                  console.log(err)
               })

            return [...reorder]
         })
      })
   }&lt;/code&gt;&lt;/pre&gt;</description>
      <category>coooding/React</category>
      <category>DnD</category>
      <category>err</category>
      <category>React</category>
      <category>react-beautiful-dnd</category>
      <category>빠르게</category>
      <category>에러</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/32</guid>
      <comments>https://zet109.tistory.com/32#entry32comment</comments>
      <pubDate>Sat, 2 Mar 2024 23:03:50 +0900</pubDate>
    </item>
    <item>
      <title>[NestJS] cors 해결</title>
      <link>https://zet109.tistory.com/31</link>
      <description>&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;react와 별도로&amp;nbsp;&amp;nbsp;nestjs를 사용하여 api 서버를&amp;nbsp;배포 하였더니 cors 문제가 생겨 데이터를 받아오지 못하는 오류가 생겼다.&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;react 서버 도메인은 example.com, api서버 도메인은 api.example.com으로 사용하기에 생긴 문제였다. 이러한 cors 문제는 배포 환경에서는 백엔드에서 해결해야하는 경우가 대부분이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;첫 시도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료를 찾아보니 nestjs에서 app.enableCors라는 것을 기본 제공해주어 이것을 사용하여 설정을 하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1708782326750&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NestFactory } from &quot;@nestjs/core&quot;
import { AppModule } from &quot;./app.module&quot;
import * as cookieParser from &quot;cookie-parser&quot;
import { ValidationPipe } from &quot;@nestjs/common&quot;
import { ConfigService } from &quot;@nestjs/config&quot;

async function bootstrap() {
  const app = await NestFactory.create(AppModule)

  app.enableCors({
    origin: [&quot;http://localhost:5173&quot; : &quot;https://example.com/&quot;],
    allowedHeaders: [&quot;Content-Type&quot;, &quot;Origin&quot;, &quot;X-Requested-With&quot;, &quot;Accept&quot;, &quot;Authorization&quot;],
    exposedHeaders: [&quot;Authorization&quot;],
    credentials: true
  })

  app.useGlobalPipes(
     new ValidationPipe({
       whitelist: true,
       forbidNonWhitelisted: true,
       transform: true
     })
  )
  app.use(cookieParser())

  await app.listen(5208)
}

bootstrap()&lt;/code&gt;&lt;/pre&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;찾아보니 env파일을 이용하여 개발 도메인과 배포 도메인을 분리하는 방법이 있다는 것을 알게되어 두번째 시도를 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;두번째 시도&lt;/h2&gt;
&lt;pre id=&quot;code_1708782519088&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NestFactory } from &quot;@nestjs/core&quot;
import { AppModule } from &quot;./app.module&quot;
import * as cookieParser from &quot;cookie-parser&quot;
import { ValidationPipe } from &quot;@nestjs/common&quot;
import { ConfigService } from &quot;@nestjs/config&quot;

async function bootstrap() {
  // 변경된 부분
  const envFile = process.env.NODE_ENV === 'dev' ? &quot;http://localhost:5173&quot; : &quot;https://example.com/&quot;

  const app = await NestFactory.create(AppModule)

  app.enableCors({
    origin: [envFile],
    allowedHeaders: [&quot;Content-Type&quot;, &quot;Origin&quot;, &quot;X-Requested-With&quot;, &quot;Accept&quot;, &quot;Authorization&quot;],
    exposedHeaders: [&quot;Authorization&quot;],
    credentials: true
  })

  app.useGlobalPipes(
     new ValidationPipe({
       whitelist: true,
       forbidNonWhitelisted: true,
       transform: true
     })
  )
  app.use(cookieParser())

  await app.listen(5208)
}

bootstrap()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 시도를 하여도 작동이 잘 되지 않았다. 그래서 삽질을 하던 중, origin: [envFile] 이 부분에서 대괄호를 해제하니 개발 환경에서는 cors가 문제없이 잘 작동하였다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;origin: envFile&lt;/code&gt;&lt;/pre&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;하지만 여전히 배포 환경에서는 잘 작동하지 않았다. 혹시나 해서 process.env.NODE_ENV를 출력해 보니 undefined가 뜨고 있었다. app.module.ts에서는 잘 출력이 되었지만, main.ts에서는 출력이 되지 않았다. 확인해 보니 env파일이 설정되는 순서 때문에 main.ts에서는 undefined가 출력되었다.&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;이것을 해결하기 위해 env와 관련된 추가적인 라이브러리를 설치하는 것을 많은 사람들이 추천하고 있었는데 추가로 설치하지 않아도 해결할 수 있는 방법이 있을 것 같았다. 일단 main.ts에서 process.env를 출력해보니 NODE_ENV를 제외하고도 많은 값들이 출력되었다. 나는 개발은 윈도우 환경에서, 배포는 ubuntu에서 하기 때문에 이 둘을 명확히 구분할 수 있는 값을 설정하면 될 것이라 생각하였다. 찾아보니 윈도우와 ubuntu를 구분할 수 있는 많은 값들을 확인할 수 있었고, 나는 그 중 process.env.EDITOR 라는 값과 process.env.npm_lifecycle_event라는 값들 중 하나를 사용하기로 했다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;process.env.EDITOR: 'C:\\Windows\\notepad.exe'
process.env.npm_lifecycle_event: 'start:dev'&lt;/code&gt;&lt;/pre&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;process.env.npm_lifecycle_event라는 값은 ubuntu 환경에서도 사용할 수 있는 명령어라고 생각을 하여 process.env.EDITOR 값을 이용하여 설정을 진행하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1708783287381&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NestFactory } from &quot;@nestjs/core&quot;
import { AppModule } from &quot;./app.module&quot;
import * as cookieParser from &quot;cookie-parser&quot;
import { ValidationPipe } from &quot;@nestjs/common&quot;
import { ConfigService } from &quot;@nestjs/config&quot;

async function bootstrap() {
  const envFile = process.env.EDITOR === &quot;C:\\Windows\\notepad.exe&quot; ? &quot;http://localhost:5173&quot; : &quot;https://example.com/&quot;

  const app = await NestFactory.create(AppModule)

  app.enableCors({
    origin: envFile,
    allowedHeaders: [&quot;Content-Type&quot;, &quot;Origin&quot;, &quot;X-Requested-With&quot;, &quot;Accept&quot;, &quot;Authorization&quot;],
    exposedHeaders: [&quot;Authorization&quot;],
    credentials: true
  })

  app.useGlobalPipes(
     new ValidationPipe({
       whitelist: true,
       forbidNonWhitelisted: true,
       transform: true
     })
  )
  app.use(cookieParser())

  await app.listen(5208)
}

bootstrap()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드로 작성을 하여도 정상적으로 작동이 되지 않았다. 하지만 envFile값을 출력해보면 값은 정상적으로 들어간 것을 확인할 수 있었다. 그래서 도대체 뭐가 문제일까 하고 확인해보니 배포 도메인 뒤에 붙어있는 / 가 눈에 보였다. 그래서 그 값을 지우고 실행을 해보니&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;아래는 정상작동하는 main.ts 코드다.&lt;/p&gt;
&lt;pre id=&quot;code_1708783769434&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { NestFactory } from &quot;@nestjs/core&quot;
import { AppModule } from &quot;./app.module&quot;
import * as cookieParser from &quot;cookie-parser&quot;
import { ValidationPipe } from &quot;@nestjs/common&quot;
import { ConfigService } from &quot;@nestjs/config&quot;

async function bootstrap() {
  const envFile = process.env.EDITOR === &quot;C:\\Windows\\notepad.exe&quot; ? &quot;http://localhost:5173&quot; : &quot;https://example.com&quot;

  const app = await NestFactory.create(AppModule)

  app.enableCors({
    origin: envFile,
    allowedHeaders: [&quot;Content-Type&quot;, &quot;Origin&quot;, &quot;X-Requested-With&quot;, &quot;Accept&quot;, &quot;Authorization&quot;],
    exposedHeaders: [&quot;Authorization&quot;],
    credentials: true
  })

  app.useGlobalPipes(
     new ValidationPipe({
       whitelist: true,
       forbidNonWhitelisted: true,
       transform: true
     })
  )
  app.use(cookieParser())

  await app.listen(5208)
}

bootstrap()&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;깃허브 주소&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Anhye0n/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1626805494398&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;Anhye0n - Overview&quot; data-og-description=&quot;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Anhye0n/&quot; data-og-url=&quot;https://github.com/Anhye0n&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Anhye0n/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Anhye0n - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>coooding/NestJS</category>
      <category>CORS</category>
      <category>env</category>
      <category>NestJS</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/31</guid>
      <comments>https://zet109.tistory.com/31#entry31comment</comments>
      <pubDate>Sat, 24 Feb 2024 23:11:03 +0900</pubDate>
    </item>
    <item>
      <title>[Nginx] site-available 설정</title>
      <link>https://zet109.tistory.com/30</link>
      <description>&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;기존에는&amp;nbsp;ejs를 사용하였기에&amp;nbsp;express서버 하나만을 배포하여 전부 해결할 수 있었지만, react를 공부하면서 디자인 패턴도 같이 조금씩 공부하다보니 react와 api 서버를 분리하여 배포를 해보고 싶었다.&lt;/span&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;react와 api 서버(nestjs)를 배포하기 위해 nginx를 사용하였다.&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;/etc/nginx/site-available의 default 파일에 해당 코드들을 추가해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;react, vue와 같은 fe파일들 설정&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;listen 포트 설정&lt;/li&gt;
&lt;li&gt;도메인 설정&lt;/li&gt;
&lt;li&gt;location의 root 설정(index.html 파일이 들어있는 위치)&lt;/li&gt;
&lt;/ul&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; react나 vue의 경우, router를 설정할 시 배포 환경마다 추가로 설정해야되는 것들이 있기에, 배포가 제대로 안된다면 찾아보면 좋다.&lt;/p&gt;
&lt;pre id=&quot;code_1708781267213&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;server {
	listen 80;
	listen [::]:80;

	server_name example.com;

	location / {
		root /var/www/example/frontend;
		index index.html;
		try_files $uri $uri/ /index.html;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;api서버 설정&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;listen 포트 설정&lt;/li&gt;
&lt;li&gt;api 도메인 설정&lt;/li&gt;
&lt;li&gt;설정해놓은 포트로 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 서버 파일들을 실행하면 정상적으로 작동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nestjs를 사용하기에 pm2를 활용하여 파일을 배포하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1708780962244&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server {
	listen 80;
	listen [::]:80;

	server_name api.example.com;

	location / {
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection 'upgrade';
		proxy_set_header Host $host;
		proxy_cache_bypass $http_upgrade;
		proxy_pass http://[ip주소]:[포트];
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>coooding/서버</category>
      <category>API</category>
      <category>nginx</category>
      <category>React</category>
      <category>vue</category>
      <category>배포</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/30</guid>
      <comments>https://zet109.tistory.com/30#entry30comment</comments>
      <pubDate>Sat, 24 Feb 2024 22:34:10 +0900</pubDate>
    </item>
    <item>
      <title>[Ubuntu 22.04] MariaDB 다른 서버에 이동하기</title>
      <link>https://zet109.tistory.com/29</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;로컬에서 작업하고 서버로 배포 혹은, 서버 자체를 바꿀 때, db구조와 데이터 모두 옮길 수 있는 방법이 있다.&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;1. 기존 db를 dump를 이용하여 sql파일로 만들어준다.&lt;/p&gt;
&lt;pre id=&quot;code_1704869464671&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mysqldump -u root -p 기존DB명 &amp;gt; 저장할 위치/파일이름.sql&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;2. sql파일을 복사할 서버의 아무 위치에 옮겨준 다음, 해당 서버에 db를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sql파일을 이용하여 새로 생성하는것이 아니라, 새로운 서버에 db를 생성후, 해당 db에 덮어씌운다는 느낌이기 때문이다.&lt;/p&gt;
&lt;pre id=&quot;code_1704869793507&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql -u root -p
...생략...

create database 원하는db명;&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;3. 다시 mysql을 나온 후, 리눅스에 아래 명령어를 입력한다.&lt;/p&gt;
&lt;pre id=&quot;code_1704869597721&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql -u root -p 생성한DB이름 &amp;lt; 복사한 위치/파일이름.sql&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;깃허브 주소&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Anhye0n/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1626805494398&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;Anhye0n - Overview&quot; data-og-description=&quot;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Anhye0n/&quot; data-og-url=&quot;https://github.com/Anhye0n&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Anhye0n/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Anhye0n - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>coooding/서버</category>
      <category>db 복사</category>
      <category>db 이동</category>
      <category>MariaDB</category>
      <category>mysqldump</category>
      <category>SQL</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/29</guid>
      <comments>https://zet109.tistory.com/29#entry29comment</comments>
      <pubDate>Wed, 10 Jan 2024 15:59:38 +0900</pubDate>
    </item>
    <item>
      <title>[Ubuntu 22.04] MariaDB 설치</title>
      <link>https://zet109.tistory.com/28</link>
      <description>&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1. MariaDB&amp;nbsp; 설치&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1704866830064&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install mariadb-server&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MariaDB 보안 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1704866850180&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mariadb-secure-installation&lt;/code&gt;&lt;/pre&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;비밀번호 입력: 처음 설치 시에는 비밀번호가 세팅이 안되어있어 엔터를 누른다.&lt;/li&gt;
&lt;li&gt;Switch to unix_sokect authentication: default 값으로 유지 / y 입력&lt;/li&gt;
&lt;li&gt;Change the root password: y 입력 후 비밀번호를 설정한다.&lt;/li&gt;
&lt;li&gt;Remove anonymous users?: 익명 유저들 제거 / y 입력&lt;/li&gt;
&lt;li&gt;Disallow root login remotely?: 원격 접속 혀용 유무, 아직까지는 원격 접속할 일이 없음 / n 입력&lt;/li&gt;
&lt;li&gt;Remove test database and access to it?: test db와 권한 정보 제거 / y 입력&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;깃허브 주소&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Anhye0n/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1626805494398&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;Anhye0n - Overview&quot; data-og-description=&quot;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Anhye0n/&quot; data-og-url=&quot;https://github.com/Anhye0n&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Anhye0n/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Anhye0n - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>coooding/서버</category>
      <category>MariaDB</category>
      <category>ubuntu</category>
      <category>ubuntu 22.04</category>
      <category>우분투</category>
      <category>우분투 22.04</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/28</guid>
      <comments>https://zet109.tistory.com/28#entry28comment</comments>
      <pubDate>Wed, 10 Jan 2024 15:44:10 +0900</pubDate>
    </item>
    <item>
      <title>[JWT] Vue, NestJS, jwt를 이용하여 로그인하기 (로그인 구현)</title>
      <link>https://zet109.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;그동안은 passport와 세션을 이용하여 로그인을 구현해왔었는데, jwt도 이번 기회에 익혀둘려고한다. Nest로 구현하면서 생각보다 조금 해맸기에, 블로그에 정리하려고 한다.&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;우선 어떤 순서로 로직이 작동되는지 이해해야한다. access token, refresh token 개념은 다른 곳에도 정리가 잘 되어있어 자세한 설명은 생략한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;작동 순서&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;로그인시 access token, refresh token 발급, refresh&amp;nbsp;token은&amp;nbsp;DB에&amp;nbsp;저장&lt;/li&gt;
&lt;li&gt;access token, refresh token 모두 httpOnly 쿠키로 클라이언트에 전송&lt;/li&gt;
&lt;li&gt;클라이언트에서 페이지 이동할 때마다 access token을 서버에 보내 토큰 유효성 확인&lt;/li&gt;
&lt;li&gt;acces token 불일치 시, refresh token 유효 여부 확인&lt;/li&gt;
&lt;li&gt;refresh token 유효할 시, access token&amp;nbsp; 발급 / 유효하지 않을 시 재로그인 요청&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 순서로 작동된다고 보면 된다. 우선 로그인부터 구현해보자. user모듈과 auth모듈을 분리해서 작성하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user.service에서는 간단하게 유저 정보 db 존재 여부를 return해주고, 이 return된 데이터를 바탕으로 auth 부분이 작동한다. 순서대로 코드를 설명하자면&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Module 설정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 jwt를 사용하기 위해 auth.module에 설정을 해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1705174921893&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// auth.module.ts
import { Module } from &quot;@nestjs/common&quot;
import { AuthService } from &quot;./auth.service&quot;
import { UserModule } from &quot;../user/user.module&quot;
import { PassportModule } from &quot;@nestjs/passport&quot;
import { LocalStrategy } from &quot;./local.strategy&quot;
import { AuthController } from &quot;./auth.controller&quot;
import { jwtConstants } from &quot;./constants&quot;

import { JwtModule } from &quot;@nestjs/jwt&quot;
import { JwtStrategy } from &quot;./jwt.strategy&quot;
import { TypeOrmModule } from &quot;@nestjs/typeorm&quot;
import { UserInfoEntity } from &quot;../user/entities/user.entity&quot;
import { RefreshJwtStrategy } from &quot;./refresh-jwt.strategy&quot;

@Module({
  imports: [UserModule,
    TypeOrmModule.forFeature([UserInfoEntity]),
    PassportModule.register({
      defaultStrategy: &quot;jwt&quot;
    }),
    JwtModule.register({
      secret: jwtConstants.ACCESS_TOKEN_SECRET,
      signOptions: { expiresIn: &quot;5m&quot; }
    })],
  providers: [AuthService, LocalStrategy, JwtStrategy],
  controllers: [AuthController]
})
export class AuthModule {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 jwt를 사용할 것이므로, passportModule의 기본 Strategy를 jwt로 설정한다. 그리고 jwt의 secret키와 만료 시간을 설정한다. 여기서는 access token에 관한 옵션을 설정하고, refresh token 옵션은 따로 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Controller 설정&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1705174931634&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// auth.controller.ts
import { Controller, Request, Res, Post, UseGuards, Get } from &quot;@nestjs/common&quot;
import { AuthGuard } from &quot;@nestjs/passport&quot;
import { LocalAuthGuard } from &quot;./local-auth.guard&quot;
import { AuthService } from &quot;./auth.service&quot;
import { InjectRepository } from &quot;@nestjs/typeorm&quot;

@Controller(&quot;auth&quot;)
export class AuthController {
  constructor(private authService: AuthService) {
  }

  @UseGuards(LocalAuthGuard)
  @Post(&quot;/login&quot;)
  async login(@Request() req: any, @Res({ passthrough: true }) res: any) {
    const { access_token, refresh_token }: { access_token: string, refresh_token: string } 
    = await this.authService.login(req.user)

    res.cookie(&quot;access_token&quot;, access_token, {
      httpOnly: true,
      secure: true,
      // maxAge: 5 * 60 * 1000
      // maxAge: 10 * 1000
    })

    res.cookie(&quot;refresh_token&quot;, refresh_token, {
      httpOnly: true,
      secure: true,
      // maxAge: 24 * 60 * 60 * 1000
    })

    return req.user.user_name
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@UseGuards(LocalAuthGuard): LocalAuthGuard라는 가드에서 전달받은 값의 유효성을 검사한다. (아래 코드)&lt;/li&gt;
&lt;li&gt;@Request() req: Guard에서 return된 값이 넘어오게 된다.&lt;/li&gt;
&lt;li&gt;@Res({ passthrough: true }) res: 클라이언트에 쿠키를 전달하기 위해 설정한다. passthrough: true를 설정해야 쿠키를 넘길 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트에서 값을 받아오고, Guard를 통해 유효성을 검증한 뒤, 통과되면 access_token, refresh_token을 쿠키로 전달해주는 코드다. 유저 정보는 body에 담아서 보내줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Guard 설정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음으로 LocalAuthGuard를 참고해보면, passport모듈을 사용하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1705174945390&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// local-auth.guard.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1705174955824&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// local.strategy.ts
import { Strategy } from &quot;passport-local&quot;
import { PassportStrategy } from &quot;@nestjs/passport&quot;
import { Injectable, UnauthorizedException } from &quot;@nestjs/common&quot;
import { AuthService } from &quot;./auth.service&quot;

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({
      // 받아오는 key 이름 설정
      usernameField: &quot;user_name&quot;,
      passwordField: &quot;user_pwd&quot;
    })
  }

  // validate라는 함수이름은 변경하면 에러 발생.
  async validate(user_name: string, user_pwd: string): Promise&amp;lt;any&amp;gt; {
    const user = await this.authService.validateUser(user_name, user_pwd)
    if (!user) {
      throw new UnauthorizedException()
    }

    return {
      &quot;user_UUID&quot;: user.user_UUID,
      &quot;user_name&quot;: user.user_name
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;local-auth.guard.ts를 보면 AuthGuard('local')이라는 코드가 존재하는데, 이 코드는 passport-local모듈의 Strategy를 사용하는 파일을 찾아서 연결해준다. 아래와 같이&amp;nbsp; 이름도 설정할 수 있다. 이름을 설정하면 AuthGuard에 설정한 이름을 넣으면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1705174968624&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PassportStrategy(Strategy, 'setName')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/auth/login으로 전송된 user_name, user_pwd를 Guard를 사용해 local.strategy.ts로 가져왔다. 가져온 값들은 validate 함수의 매개변수로 가져올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가져온 값들을 authService에 정의해논 validateUser 메서드를 통해 이름과 비밀번호가 유효한지 확인한 후, 없을 시, 401에러, 있을 시 유저 정보를 가져온다. 그리고 여기서 user정보를 return해준다. 여기서 return된 값은 auth.controller.ts의login 메서드로 가게되고, 이 메서드에서 req 매개변수로 받게되고, 이 값들을 통해, access token, refresh token을 발급받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Service 설정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;login 메서드에서 사용했던, access token, refresh token을 발급해주는 authService의 login 메서드 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1705174980994&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// auth.service.ts
import { Injectable, UnauthorizedException } from &quot;@nestjs/common&quot;
import { UserService } from &quot;../user/user.service&quot;
import { JwtService } from &quot;@nestjs/jwt&quot;

import * as bcrypt from &quot;bcrypt&quot;
import { jwtConstants } from &quot;./constants&quot;
import { In, Repository } from &quot;typeorm&quot;
import { InjectRepository } from &quot;@nestjs/typeorm&quot;
import { UserInfoEntity } from &quot;../user/entities/user.entity&quot;
import { UserInfoDto } from &quot;./dto/user-info-dto&quot;

@Injectable()
export class AuthService {
  constructor(private userService: UserService,
              private jwtService: JwtService,
              @InjectRepository(UserInfoEntity) private userInfoRepository: Repository&amp;lt;UserInfoEntity&amp;gt;
  ) {
  }

  async validateUser(user_name: string, user_pwd: string): Promise&amp;lt;any&amp;gt; {
    const user = await this.userService.userLogin(user_name)

    if (user &amp;amp;&amp;amp; await bcrypt.compare(user_pwd, user.user_pwd) === true) {
      return user
    }
    return null
  }

  async generateAccessToken(user: UserInfoDto) {
    const payload = { user_name: user.user_name }
    return this.jwtService.sign(payload)
  }

  async generateRefreshToken(user: UserInfoDto) {
    const payload = { user_name: user.user_name }

    return this.jwtService.sign(payload, {
      secret: jwtConstants.REFRESH_TOKEN_SECRET,
      expiresIn: &quot;1d&quot;
    })
  }

  async login(user: any) {
    const payload = { user_name: user.user_name }

    const access_token: string = await this.generateAccessToken(user)
    const refresh_token: string = await this.generateRefreshToken(user)

    await this.userInfoRepository.update({ user_UUID: user.user_UUID }, {
      refresh_token: refresh_token
    })

    return {
      user_name: user.user_name,
      access_token,
      refresh_token
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;controller에서 받아온 user정보로 payload를 설정한다. 그리고 이를 바탕으로 access token과 refresh token을 발급한다. 이 두 토큰을 생성하는 함수를 분리한 이유는 이후 재발급할 때도 사용하기 위함이다. 그리고&amp;nbsp; refresh 토큰의 secret키와 만료 시간을 설정하고, 나중에 유효성 검사를 하기 위해, db에 저장해둔다. 여기서 return된 토큰과 유저 정보가 controller에 return 되고, 클라이언트로 전송된다.&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;이제 남은건 기능은 api요청이 들어올 때마다 access token, refresh token을 검증하는 기능이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;깃허브 주소&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Anhye0n/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1626805494398&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;Anhye0n - Overview&quot; data-og-description=&quot;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Anhye0n/&quot; data-og-url=&quot;https://github.com/Anhye0n&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Anhye0n/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Anhye0n - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>coooding/NestJS</category>
      <category>JWT</category>
      <category>Nest</category>
      <category>Passport</category>
      <category>vue</category>
      <category>로그인</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/27</guid>
      <comments>https://zet109.tistory.com/27#entry27comment</comments>
      <pubDate>Fri, 29 Dec 2023 22:21:39 +0900</pubDate>
    </item>
    <item>
      <title>[Vue] Pinia 새로고침 시 자료 없어짐 해결</title>
      <link>https://zet109.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Pinia를 사용하여 유저정보를 페이지에 사용하고 있는데, 새로고침 시 데이터가 초기화 되는 것을 확인했다. 찾아보니 pinia나 redux같은 상태 관리 라이브러리들은 데이터를 따로 저장해두는 곳이 없어서, 새로고침 시 데이터가 사라진다고 한다.&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;이를 해결하려면 pinia에서는 pinia-plugin-persistedstate를 사용해야한다.&lt;/p&gt;
&lt;figure id=&quot;og_1703809753946&quot; style=&quot;color: #333333; text-align: start;&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/7rNlz/hyUTwJVfWh/8EH9FSO3sHBhgIpkqqXWCk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot; data-og-url=&quot;https://www.npmjs.com/package/pinia-plugin-persistedstate&quot; data-og-source-url=&quot;https://www.npmjs.com/package/pinia-plugin-persistedstate&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-description=&quot;Configurable persistence and rehydration of Pinia stores.. Latest version: 3.2.1, last published: 12 days ago. Start using pinia-plugin-persistedstate in your project by running &amp;#96;npm i pinia-plugin-persistedstate&amp;#96;. There are 103 other projects in the npm r&quot; data-og-title=&quot;pinia-plugin-persistedstate&quot; data-og-type=&quot;website&quot; data-ke-align=&quot;alignCenter&quot; data-ke-type=&quot;opengraph&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.npmjs.com/package/pinia-plugin-persistedstate&quot; data-source-url=&quot;https://www.npmjs.com/package/pinia-plugin-persistedstate&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/7rNlz/hyUTwJVfWh/8EH9FSO3sHBhgIpkqqXWCk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;pinia-plugin-persistedstate&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; style=&quot;color: #909090;&quot; data-ke-size=&quot;size16&quot;&gt;Configurable persistence and rehydration of Pinia stores.. Latest version: 3.2.1, last published: 12 days ago. Start using pinia-plugin-persistedstate in your project by running `npm i pinia-plugin-persistedstate`. There are 103 other projects in the npm r&lt;/p&gt;
&lt;p class=&quot;og-host&quot; style=&quot;color: #909090;&quot; data-ke-size=&quot;size16&quot;&gt;www.npmjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1703809236779&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i pinia-plugin-persistedstate&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;이후 main.js에서 pinia.use(piniaPluginPersistedstate)로 라이브러리 사용을 등록해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1703809842813&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.js
import { createApp } from 'vue';

import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

import App from './App.vue';
import router from './router';

const app = createApp(App);

// pinia 설정
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia);

app.use(router);

app.mount('#app');&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;그리고 사용할 store에 가서 persist을 true로 바꿔준다.&lt;/p&gt;
&lt;pre id=&quot;code_1703809982878&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// userManage.js
import { defineStore } from &quot;pinia&quot;

export const useUserStore = defineStore(&quot;user&quot;, {
  state: () =&amp;gt; ({
    userName: null,
  }),
  getters: {

  },
  actions: {},
  // 새로고침해도 안바뀜.
  persist: 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;이렇게하면 새로고침을해도 데이터가 잘 유지된다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;깃허브 주소&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Anhye0n/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1626805494398&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;Anhye0n - Overview&quot; data-og-description=&quot;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Anhye0n/&quot; data-og-url=&quot;https://github.com/Anhye0n&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/Anhye0n/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Anhye0n/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oo071/hyKX1dSZqv/UxCkzeXoxnQ5xoYYFnPJXk/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460,https://scrap.kakaocdn.net/dn/FZ3t3/hyKWRjEGwB/Pmx22Tdb3uDDoStEef4hD1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Anhye0n - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;anhye0n.me. Anhye0n has 10 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>coooding/Javascript</category>
      <category>pinia</category>
      <category>vue</category>
      <category>상태 관리</category>
      <category>새로고침</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/26</guid>
      <comments>https://zet109.tistory.com/26#entry26comment</comments>
      <pubDate>Fri, 29 Dec 2023 09:22:15 +0900</pubDate>
    </item>
    <item>
      <title>Node js mysql 값 가져올 때 async await 사용하기</title>
      <link>https://zet109.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우선 async, await을 사용하기 위해선 기존에 사용하던 mysql이 아닌 mysql2 모듈을 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 mysql2에 맞게 코드를 변경하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1676525294940&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const mysql = require('mysql2/promise');
const db_info = {
    host: '127.0.0.1',
    user: '-',
    password: '-',
    database: '-',
    multipleStatements: true,
    dateStrings: 'date',
    //clearExpired: true,
    //checkExpirationInterval: 3600000,
    //expiration: 3600000,
    enableKeepAlive: true // 갑자기 종료되는 econnreset 해결 위해
}

module.exports = {
    init: function () {
        return mysql.createPool(db_info);
    },
    // var conn = db_config.init();
    connect: function (conn) {
        conn.connect(function (err) {
            if (err) console.error('mysql connection error : ' + err);
            else console.log('mysql is connected successfully!');
        });
    },
    db_info
}&lt;/code&gt;&lt;/pre&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값이 배열로 나오니 주의하자.&lt;/li&gt;
&lt;li&gt;에러를 잡을 때 .catch를 사용하면 코드를 훨씬 간편하게 바꿀 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1676525375167&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let saveData = []


const outDate = async () =&amp;gt; {
    let test = null
    test = await conn.getConnection().catch(err =&amp;gt; console.log(err));

    saveData = await test.query('사용한 쿼리').catch(err =&amp;gt; console.log(err))

    console.log(saveData[0])
    console.log('saveDate : ' + JSON.stringify(saveData[0]))
}

outDate();&lt;/code&gt;&lt;/pre&gt;</description>
      <category>coooding/Node.js</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/25</guid>
      <comments>https://zet109.tistory.com/25#entry25comment</comments>
      <pubDate>Thu, 16 Feb 2023 14:32:54 +0900</pubDate>
    </item>
    <item>
      <title>2022년을 13일 남겨둔 시점</title>
      <link>https://zet109.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2022년을 13일 남겨두고, 부대 복귀 날의 의정부 풍경 기록&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20221218_150427.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BhKmY/btrTQ0fGy1k/5iAmv1ySX6Psbgnohtxdy1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BhKmY/btrTQ0fGy1k/5iAmv1ySX6Psbgnohtxdy1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BhKmY/btrTQ0fGy1k/5iAmv1ySX6Psbgnohtxdy1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBhKmY%2FbtrTQ0fGy1k%2F5iAmv1ySX6Psbgnohtxdy1%2Fimg.jpg&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;4000&quot; height=&quot;1800&quot; data-filename=&quot;20221218_150427.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20221218_154606.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuRYqb/btrTYC4YPJZ/HkDGGkhmKtKYy6n1RNKM9K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuRYqb/btrTYC4YPJZ/HkDGGkhmKtKYy6n1RNKM9K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuRYqb/btrTYC4YPJZ/HkDGGkhmKtKYy6n1RNKM9K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuRYqb%2FbtrTYC4YPJZ%2FHkDGGkhmKtKYy6n1RNKM9K%2Fimg.jpg&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;4000&quot; height=&quot;1800&quot; data-filename=&quot;20221218_154606.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20221218_154611.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mqULT/btrTR0MYnJy/2NhuN6yBFs8QektWouyFo1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mqULT/btrTR0MYnJy/2NhuN6yBFs8QektWouyFo1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mqULT/btrTR0MYnJy/2NhuN6yBFs8QektWouyFo1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmqULT%2FbtrTR0MYnJy%2F2NhuN6yBFs8QektWouyFo1%2Fimg.jpg&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;4000&quot; height=&quot;1800&quot; data-filename=&quot;20221218_154611.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>기록/군대</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/24</guid>
      <comments>https://zet109.tistory.com/24#entry24comment</comments>
      <pubDate>Sun, 18 Dec 2022 16:53:17 +0900</pubDate>
    </item>
    <item>
      <title>2022년을 한달 남겨둔 시점에서..</title>
      <link>https://zet109.tistory.com/23</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2022년 11월, 나는 지금 군대에 있다.&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작년은 코로나로 인해 집에서 코딩만 하는 대학생이였다. 그리고 재수하느라 못했던 게임도 실컷했다. 그렇게 대학생활을 하다 21년이 지나갔다.&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;그리고 대부분의 사람들과 비슷하게 1학년을 마치고 올해 초에 입대했다. 재수를 하였기에 내 주변 친구들보다 1년 늦게 군대에 들어오게 되었다.&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;참 큰일났다 싶었는데 막상 돌이켜보면 올해도 벌써 1달 정도 밖에 안남았다.&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;휴가를 나온 지금, 내가 지금까지 코딩과 관련되어 어떻게 살았는지 되돌아보며, 앞으로에 대한 간단한 계획을 블로그에 남겨볼까 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;한국디지털미디어고등학교를 다니며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중학교 2학년 때 C언어로 코딩을 입문했던 나는 고등학교에 올라오면서부터 본격적으로 코딩을 하기 시작했다. 내가 재미를 느끼는 분야를 찾기 위해 많은 언어와 분야를 접해봤다. 해킹(리버싱, 웹해킹, 포너블), 자바, c언어, c++, R, 안드로이드, php, 웹 등등.. 유명한건 한번 씩 다 간단하게 해본 것 같다. 그러다 고등학교 2학년 말 쯤에 나의 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;관심분야가 확고해졌다. &lt;b&gt;웹이였다.&lt;/b&gt; 또 친구들과 창업대회를 나가서 웹앱을 만들어 시제품을 만드는 경험은 지금 생각해도 되게 좋은 경험이였다.&lt;/span&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;letter-spacing: 0px;&quot;&gt;하지만 고등학생 때, 학업과 코딩 사이를 오가며 방황을 하다 공부와 코딩을 둘다 놓친 느낌이였다. 공부도 많이 잘하지 못했고, 코딩도 기초적인 프론트(html, css, js) 지식을 가지고, 잘만들어져있는 템플릿과 코드들을 수정하며, php를 이용해 CRUD를 구현하는 정도였다.&amp;nbsp;&lt;/span&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;CRUD정도면 왠만한건 다 만들 수 있지만, 내 스스로가 느끼기에, 디미고에서 워낙 잘하는 친구들이 많다보니 턱없이 실력이 부족하다고 느꼈다. 코드도 깔끔하지 못한, 유지보수가 거의 불가능할 정도의 스파게티 코드였다. 이런 내 실력을 깨닫고, 코딩을 깊게 공부를 할려고하니, 학업에 투자할 시간이 부족했고, 학업에 집중을 하자니, 나에겐 코딩은 게임을 하는 것과 비슷할 정도로 (포기하기 힘든)재미있는 놀이였다.&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이렇게 방황을 하다, 결국 재수를 하게되며 1년정도 코딩과 담을 쌓으며 지냈다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;대학을 다니며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹이 재밌는건 지금도 마찬가지였기에, 지금 가장 핫한거 같은 js를 이용하여 프론트엔드와 백엔드를 차근차근 시작해보자라는 생각으로 리액트와 노드를 공부했다. 근데 2개를 동시에 접하며 느낀 것이 노드가 훨씬 재미있었다. 이때는 프론트엔드에 대한 이해가 별로 없던 때기도 하고, 간단한 페이지만 구현하던 때라 만들고 있었던 사이드 프로젝트들에 SPA 적용 필요성과, 바닐라js 대신 굳이 리액트로 개발해야될 필요성을 느끼지 못한게 컸다.&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;그래서 노드만 집중적으로 공부하며 사이드 프로젝트로 블로그와 api를 이용한 가상화폐 가격비교 사이트 등을 만들었으며, 백엔드 포지션으로 대회에 참가하여 yolo와 tensorflowjs를 이용하여, 시각장애인 분들이 음료 캔을 구분하실 수 있는 YCSI(공개SW개발자대회), 구글 맵 api를 이용한 위치기반 sns(구글 2022 Solution Challenge) 등에 참여했었다. 특히 구글 대회는 입대 당일 날 새벽까지 준비할 정도로 열심히했는데, 결과가 조금 아쉬웠다.&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년의 경험과 대학을 1년정도 다니며 얻은 경험은 나의 꿈이 백엔드 개발자라는 확신을 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;지금은&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 나의 기술 스택은 html, css, js, Nodejs, python, mysql, nginx 정도이다. 노드를 어느정도 경험하고, 리액트 공부를 다시하고 싶었지만, 대회를 준비하다보니 입대하기 전까지 공부할 시간이 부족했다. 아무튼 지금 나의 백엔드 개발 실력은 간단한 외주는 가능할 것 같지만, 스타트업에 취업이 가능할 정도로 좋다고는 말할 수 없을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nginx, 노드js, mysql을 이용하여 무언가 만들고 싶은 것들은 대부분 만들 수 있었지만, 입대하기 전, 여러 대회를 준비하고, 코드와 파일이 많아지게 되면서, js와 노드js 제대로 이해하지 못하고, 사용하고 있다는 느낌이 많이 들었다. 콜백들이 많아지며 가로로 길어지는 코드, if else를 너무 많이 남발하고, 기능 분리를 제대로 하지 못하여 코드의 가독성과 유지보수가 좋지 못했다. 기능 구현에만 급급하여 함수, Promise, async와 await, 에러 처리를 제대로 활용하지 못한 탓이 크다.&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;나의 이러한 문제들을 알고 있기에, 지금은 새로운 기술을 배우기보다, 코드를 어떻게 짜면 좋을지, 설계와 구상을 어떤식으로 하면 좋을지 등을 배우기 위해, 일단 js를 깊게 공부하는게 먼저라는 생각이 들어, 책(모던 자바스크립트 Deep Dive)을 구매하여 공부하고 있고, 구글과 유튜브를 통해 안좋은 코드들의 사례와 그 코드들을 어떻게 바꿀 수 있는지를 공부하고 공부한 내용들을 기존에 작성했던 코드에 적용하며 실력을 쌓고 있다.&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;사실 원래는 군대에서 무엇을 공부할까 하다가 취업을 위해 노드를 접고, 스프링을 위해 자바를 천천히 공부할려 했었지만, 현재 한국에서 노드js도 충분히 시장에서 수요가 있고, 점점 수요가 많아지고 있는게 취업 공고 사이트에서 보였다. 사실 자바와 스프링은 아예 처음 배우는거라 시간도 오래걸리고 군대에서 배우기에 부담이 있었는데, 취업 공고 사이트에서 노드js의 수요가 늘어나는게 보여, 공부하는데 상대적으로 부담이 적은 js를 집중적으로 공부중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;앞으로&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;군생활을 이제 절반정도 했으니, 이제 9개월만 지나면 전역이다. 솔직히 많이 남은걸로 느껴지지만, 막상 지나고 나면 순식간이라는걸 알기 때문에, 전역 후 백엔드 포지션으로 회사에 들어가기 위해, 지금부터 공부 중이다. 나는 군대를 전역하고, 복학하기 전부터, 복학 후에도 웬만하면 회사 일과 학업을 병행하며 살고 싶다.&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;현업에서는 어떤 코드를 짤까?&lt;br /&gt;내가 짠 코드가 실무에서도 사용할 수 있는 코드일까?&lt;/span&gt;&lt;/blockquote&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022년이 한달 남았다. 전역하면 23년 9월이다. 복학하면 24년이다. 적어도 24년에 나는 지금의 나와는 다르게, 가독성이 좋고, 유지보수에 유리하며, 실무에서 사용 가능한 코드를 짜는, 남들이 짠 코드를 리뷰할 수 있는 사람이 되고 싶다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20221120_131501.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/36SBB/btrRRXYwULD/JU8WA5UfzNklY9nm30k8v0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/36SBB/btrRRXYwULD/JU8WA5UfzNklY9nm30k8v0/img.jpg&quot; data-alt=&quot;2022년 11월 20일에 찍은 휴가 나온 날 의정부 풍경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/36SBB/btrRRXYwULD/JU8WA5UfzNklY9nm30k8v0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F36SBB%2FbtrRRXYwULD%2FJU8WA5UfzNklY9nm30k8v0%2Fimg.jpg&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;4000&quot; height=&quot;1800&quot; data-filename=&quot;20221120_131501.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2022년 11월 20일에 찍은 휴가 나온 날 의정부 풍경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>기록/군대</category>
      <author>stableh</author>
      <guid isPermaLink="true">https://zet109.tistory.com/23</guid>
      <comments>https://zet109.tistory.com/23#entry23comment</comments>
      <pubDate>Tue, 22 Nov 2022 21:17:06 +0900</pubDate>
    </item>
  </channel>
</rss>