<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>progect_study.log</title>
        <link>https://velog.io/</link>
        <description>프로젝트전에 해당 부분을 깊게 공부한것을 올려두는 벨로그</description>
        <lastBuildDate>Sat, 08 Feb 2025 01:03:17 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. progect_study.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/progect_study" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[stmp 와 언어 변역, 로컬환경 테스트 결과]]></title>
            <link>https://velog.io/@progect_study/stmp-%EC%99%80-%EC%96%B8%EC%96%B4-%EB%B3%80%EC%97%AD-%EB%A1%9C%EC%BB%AC%ED%99%98%EA%B2%BD-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC</link>
            <guid>https://velog.io/@progect_study/stmp-%EC%99%80-%EC%96%B8%EC%96%B4-%EB%B3%80%EC%97%AD-%EB%A1%9C%EC%BB%AC%ED%99%98%EA%B2%BD-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC</guid>
            <pubDate>Sat, 08 Feb 2025 01:03:17 GMT</pubDate>
            <description><![CDATA[<p>영상을 업로드 하고 해당 업로드 파일에 자동으로 자막을 달는 기능을 만들어 봅시다.
이때 자막은 3가지 종류로 달아야 합니다.</p>
<h1 id="아래와-같은-아키텍처를-가집니다">아래와 같은 아키텍처를 가집니다</h1>
<p>로컬환경 으로 개발하기
<img src="https://velog.velcdn.com/images/progect_study/post/85c90dee-cc9c-41ba-97a4-fbd29e89a665/image.png" alt=""></p>
<p>어떠한 물리적인 api 를 사용하지 않고 만듭니다.
<a href="https://github.com/sengwoong/TranslationService_HTML">https://github.com/sengwoong/TranslationService_HTML</a>
해당 폴더에 어떠하게 만들어 졌는지 대략적이게 확인이 가능합니다.</p>
<p>원래는 Whisper-large-v2 을 사용하여야 인식이 됩니다.
하지만 너무나도 cpu 사용량이 높아서 가장작은 모델을 사용 하였습니다.
하지만 그럼에도 불구하고 너무 높은 cpu 사용량을 보입니다.</p>
<p><img src="https://velog.velcdn.com/images/progect_study/post/c7376872-243e-4082-957e-0bd55eca86e6/image.png" alt=""></p>
<p>로컬pc 기준에서 50퍼 정도의 사용량을 가집니다. </p>
<p>t3.2xlarge
USD 0.3328
cpu 8
memory 32GiB 
이며 이는 1일 기준하여 11,655원이 발생합니다. 
(2분 영상 기준하에 가장성능이 안좋은 모델 사용시 3분정도 소요됩니다.)
그리고 무려 두개의 요청상황을 제어 할 수 있습니다.
또한 모델을 다운받으면 언어하나당 4gb 이상의 비용이 청구 됩니다.</p>
<p>그래서 해당 전문적인 커스텀 api 를 만들기 힘들기 때문에 chathpt 와 Whisper를 api로 받아서 10분당 건당 200원의 비용을 발생 시키는 로직을 만들어 볼가 합니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[기본 Prisma 명령어]]></title>
            <link>https://velog.io/@progect_study/%EA%B8%B0%EB%B3%B8-Prisma-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@progect_study/%EA%B8%B0%EB%B3%B8-Prisma-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Sat, 25 Jan 2025 12:53:47 GMT</pubDate>
            <description><![CDATA[<p>Prisma 명령어는 데이터베이스 스키마 관리, 마이그레이션, 그리고 Prisma Client 생성 등을 위해 사용됩니다. 아래는 주요 Prisma 명령어를 정리한 내용입니다.</p>
<ol>
<li>기본 Prisma 명령어</li>
<li><ol>
<li>프로젝트 초기화
bash
복사
편집
npx prisma init
Prisma 프로젝트를 초기화하고 prisma/schema.prisma와 .env 파일을 생성합니다.</li>
</ol>
</li>
<li><ol start="2">
<li>데이터베이스와 Prisma 동기화
데이터베이스 스키마를 Prisma 스키마와 동기화:
bash
복사
편집
npx prisma db push
Prisma 스키마의 모델 정의를 데이터베이스에 적용합니다.
기존 데이터베이스에 영향을 주지 않고 스키마를 반영합니다.</li>
</ol>
</li>
<li><ol start="3">
<li>Prisma Client 생성
bash
복사
편집
npx prisma generate
Prisma Client를 생성하여 코드에서 데이터베이스를 사용할 수 있도록 합니다.</li>
</ol>
</li>
<li><ol start="4">
<li>데이터베이스 마이그레이션 관리
마이그레이션 생성:
bash
복사
편집
npx prisma migrate dev --name <migration_name>
데이터베이스에 새로운 마이그레이션을 적용합니다.
migration_name은 마이그레이션의 이름입니다.
마이그레이션 적용:
bash
복사
편집
npx prisma migrate deploy
생성된 마이그레이션 파일을 데이터베이스에 적용합니다.
마이그레이션 상태 확인:
bash
복사
편집
npx prisma migrate status
현재 마이그레이션 상태를 확인합니다.</li>
</ol>
</li>
<li><ol start="5">
<li>데이터베이스 정보 가져오기
데이터베이스 스키마 가져오기:
bash
복사
편집
npx prisma db pull
데이터베이스의 현재 상태를 기반으로 Prisma 스키마를 업데이트합니다.
데이터베이스 초기화(주의: 모든 데이터 삭제됨!):
bash
복사
편집
npx prisma migrate reset
데이터베이스를 초기화하고, 마이그레이션을 다시 적용합니다.</li>
</ol>
</li>
<li><ol start="6">
<li>Prisma Studio
bash
복사
편집
npx prisma studio
Prisma Studio를 실행하여 데이터베이스를 GUI에서 확인하고 관리합니다.</li>
</ol>
</li>
<li>추가 명령어</li>
<li><ol>
<li>Prisma CLI 버전 확인
bash
복사
편집
npx prisma -v
현재 설치된 Prisma CLI 버전을 확인합니다.</li>
</ol>
</li>
<li><ol start="2">
<li>도움말 확인
bash
복사
편집
npx prisma help
Prisma CLI에서 사용할 수 있는 모든 명령어 목록을 확인합니다.</li>
</ol>
</li>
<li>자주 사용하는 명령어 예시</li>
<li><ol>
<li>데이터베이스 설정 후 기본 워크플로우
프로젝트 초기화:
bash
복사
편집
npx prisma init
Prisma 스키마 작성:
prisma
복사
편집
model User {
id    Int     @id @default(autoincrement())
email String  @unique
name  String?
}
데이터베이스와 동기화:
bash
복사
편집
npx prisma db push
Prisma Client 생성:
bash
복사
편집
npx prisma generate
데이터베이스 GUI 관리:
bash
복사
편집
npx prisma studio</li>
</ol>
</li>
<li><ol start="2">
<li>마이그레이션 관리 워크플로우
새로운 모델 추가 후 마이그레이션 생성:
bash
복사
편집
npx prisma migrate dev --name add_user_model
생성된 마이그레이션 적용:
bash
복사
편집
npx prisma migrate deploy
마이그레이션 상태 확인:
bash
복사
편집
npx prisma migrate status</li>
</ol>
</li>
<li>참고
Prisma 공식 문서: Prisma Documentation
에러가 발생하거나 이해되지 않는 부분이 있으면 언제든지 질문하세요! 😊</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[next.js 15 와 도커 세팅방법]]></title>
            <link>https://velog.io/@progect_study/next.js-15-%EC%99%80-%EB%8F%84%EC%BB%A4-%EC%84%B8%ED%8C%85%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@progect_study/next.js-15-%EC%99%80-%EB%8F%84%EC%BB%A4-%EC%84%B8%ED%8C%85%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 25 Jan 2025 12:44:53 GMT</pubDate>
            <description><![CDATA[<p>현재 PostgreSQL는 정상적으로 실행되고 있으며, 데이터베이스도 준비된 상태입니다. 그러나 DATABASE_URL을 통해 Prisma가 데이터베이스와 통신하는 데 문제가 발생했을 가능성이 있습니다. 아래 단계를 따라 문제를 해결해보세요.</p>
<ol>
<li>DATABASE_URL 확인
DATABASE_URL의 값이 올바른지 확인하세요. 특히 다음 항목들을 확인해야 합니다:</li>
</ol>
<p>유저 이름: doumi가 PostgreSQL 데이터베이스의 사용자로 등록되어 있어야 합니다.
비밀번호: randompassword가 실제로 doumi 사용자에 설정된 비밀번호인지 확인하세요.
호스트: localhost에서 PostgreSQL에 접속 가능한지 확인하세요.
포트 번호: PostgreSQL의 기본 포트는 5432입니다. 변경되지 않았다면 그대로 사용합니다.
데이터베이스 이름: mydb가 실제 데이터베이스 이름과 일치해야 합니다.
2. PostgreSQL에 직접 접속 테스트
Docker 컨테이너 내부에서 PostgreSQL에 직접 접속해 DATABASE_URL이 올바른지 확인하세요:</p>
<p>PostgreSQL CLI 접속:</p>
<p>bash
복사
편집
docker exec -it helper-db psql -U doumi -d mydb
위 명령이 성공하면, PostgreSQL 사용자와 데이터베이스 설정이 올바르다는 뜻입니다.</p>
<p>비밀번호가 틀리거나 접속 오류가 발생하면, PostgreSQL에서 사용자를 다시 설정해야 합니다.</p>
<ol start="3">
<li>PostgreSQL 사용자 및 데이터베이스 설정
만약 위 단계에서 접속 오류가 발생한다면, 다음 명령을 실행하여 PostgreSQL에서 사용자와 데이터베이스를 설정하세요:</li>
</ol>
<p>컨테이너 내부로 접속:</p>
<p>bash
복사
편집
docker exec -it helper-db bash
PostgreSQL에 postgres 사용자로 접속:</p>
<p>bash
복사
편집
psql -U postgres
사용자 및 데이터베이스 생성:</p>
<p>sql
복사
편집
CREATE USER doumi WITH PASSWORD &#39;randompassword&#39;;
CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON DATABASE mydb TO doumi;
4. Prisma schema.prisma 파일 업데이트
schema.prisma 파일에 데이터베이스를 제대로 매핑했는지 확인하세요:</p>
<p>prisma
복사
편집
datasource db {
  provider = &quot;postgresql&quot;
  url      = env(&quot;DATABASE_URL&quot;)
}</p>
<p>generator client {
  provider = &quot;prisma-client-js&quot;
}</p>
<p>model User {
  id    Int    @id @default(autoincrement())
  email String @unique
  name  String?
}
5. Prisma 데이터베이스 연결 테스트
모든 설정이 완료되었으면 다음 명령어를 실행해 보세요:</p>
<p>bash
복사
편집
npx prisma db push
명령어가 성공적으로 실행되면 Prisma 스키마와 데이터베이스가 동기화됩니다.</p>
<ol start="6">
<li>추가 문제 발생 시 로그 확인
여전히 문제가 발생한다면 다음 명령어로 Docker 로그를 확인하세요:</li>
</ol>
<p>bash
복사
편집
docker logs helper-db
위 로그에서 에러 메시지가 나오는 경우, 해당 내용을 기반으로 추가적인 조치를 취해야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[디자인]]></title>
            <link>https://velog.io/@progect_study/%EB%94%94%EC%9E%90%EC%9D%B8</link>
            <guid>https://velog.io/@progect_study/%EB%94%94%EC%9E%90%EC%9D%B8</guid>
            <pubDate>Sat, 21 Sep 2024 23:44:03 GMT</pubDate>
            <description><![CDATA[<h1 id="디자인-방법">디자인 방법</h1>
<p>1)표현
같은 도형이라 하더라도 위치랑 크기에 따라서 느껴지는것이 다름
2)균형
색상과 크기 위치를 사용하여 맞춤
3)대비
구도는 위치나 모양 사이즈 특히색상등 을 사용하여 기존 스타일과 조금 다르게 만들어 표현하는 방법
4)형태
같은 삼각형이라 하더라도 너덜너덜한삼각형 정삼걱형 직각삼각형등 모두 느낌이다름
5)게층구조
배치를 할때 시각적인것의 진열 방법을 바꾸어 눈에뛰게 한다
가장 과시하고 싶은 문장이나 포스트를 크게키움으로 구조를 만들수도있다.
6)관계
같이 있는것 끼리 정렬하거나 다른것을 떨어뜨려둠
7)정렬
원은 정렬할때 조금더 크게 만들어야 합니다.
차지하는 영역으로 중요도 강조</p>
<h1 id="타이포그래프">타이포그래프</h1>
<p>글자의 사이즈나 크기 서채등으로 나눕니다.
1)글꼴
서체 - 예술작품
글꼴 - 컴퓨터에 설치할수 있는 서체
2)웹과 신문의 다른점
신문은 하나의 경우를 들고 디자인하는 반면 웹은 여러가지 형태에서도 이쁘게 보여야 한다.
3)서체정하기
브랜드와 관련 있는 키워드를 나열하고 비슷한 느낌의 서체를 구하기
본문 - 비교적 신뢰적이게 폰트사이즈로 강조
4)종황비
글자사이즈 x 값의 기준으로 측정
font size adjust 사용</p>
<p>16-&gt; 24 ,36,48
아이폰 태블릿 컴퓨터
30 45 60
각분 22</p>
<p>사이즈 4-&gt; 8 -&gt; 12
줄은 95자이상 적지말것</p>
<h1 id="그리드">그리드</h1>
<p>1) 그리드를 딱맞추어 만들지 않는이유
일본어는 특이하여 맞출수가 없다.
줄높이는 텍스트에 기반한다.
2) 이때 그리드는 마진을 제외한다.</p>
<h2 id="그리드종류">그리드종류</h2>
<p>기본적으로 원고 격자 그리드, 컬럼 그리드, 베이스라인 그리드, 모듈 그리드, 계층적 그리드,</p>
<p>이렇게 5가지 유형의 그리드가 있습니다
 예시를 통해 자세히 이해해 봅시다 기본적으로 원고 격자 그리드는 많은 텍스트를</p>
<p>적절하게 정렬해야 하는 경우에 사용됩니다 화면의 예시를 보면 원고 격자를 활용하여</p>
<h2 id="격자-모양-그리기">격자 모양 그리기</h2>
<p>(텍스트가 중앙에있고 텍스트마진을 그리기)
적절하게 정렬해야 하는 경우에 사용됩니다 화면의 예시를 보면 원고 격자입니다.</p>
<h2 id="컬럼그리드">컬럼그리드</h2>
<p>적절하게 세로로 정렬하여 화면을 세로선상 대칭으로 보이게하기위해 사용 합니다.</p>
<h2 id="베이스-그리드">베이스 그리드</h2>
<p>텍스트를 정리할때 사용합니다.</p>
<h2 id="모듈그리드">모듈그리드</h2>
<p>어디에 어떡해 배치할까x 축 y 축을 모두 생각하며 배치한다.</p>
<h2 id="계층적-그리드">계층적 그리드</h2>
<p>뉴스기사등 필요함에 따라서 큰것은크게 작은것은 작게디자인한다.</p>
<p>그리드는 12 24가 적당하다.</p>
<h1 id="색상">색상</h1>
<p>조합에따라서 두가지 색상이 같거나 다르게 보일수 있음
색상에 감정이 있음
색상에 명도에따라서 구분시킬수있음</p>
<p>첫 번째 색상 조화는 보색입니다</p>
<p>이 방법에서는 반대되는 두 가지 색상이 선택됩니다</p>
<p>이제 강의 시작 부분에서 본 예시를 다시 살펴보겠습니다</p>
<p>이 그림에서 볼 수 있듯이 사과에는 녹색이 사용되고 냄비는 빨간색이 보색으로 사용되었습니다</p>
<p>이런 식으로 UI를 만들거나 그림을 그릴 때 색상 조화가 매우 유용합니다</p>
<p>다음 색상 조화는 분할 보색입니다</p>
<p>분할 보색에는 하나의 주요 색상과 두 개의 인접 색상이 있으며, 화면 사진은 분할 보색의 예입니다</p>
<p>화가가 색들을 얼마나 아름답게 사용했는지 알 수 있습니다</p>
<p>다음 배색은 유사색입니다</p>
<p>기본적으로 유사색은 나란히 위치한 세 가지 색상으로 구성됩니다</p>
<p>유사색의 예를 살펴보겠습니다</p>
<p>이 예에서는 화가가 유사색을 사용한 것을 볼 수 있습니다</p>
<p>색상환에서 서로 옆에 위치한 색상을 사용했습니다</p>
<p>다음 색상 조화는 트리아딕(삼색)으로, 색상환에서 등변 삼각형을 배치하여</p>
<p>색상 조합을 만드는 것입니다</p>
<p>이 그림에서 트리아딕 조합을 볼 수 있습니다</p>
<p>다음 색상 조화는 테트라딕입니다 기본적으로 4가지 색상으로 구성되며</p>
<p>색상환 위에 직사각형을 놓을 때 얻어지는 색상입니다 테트라딕은 이중보완 색상으로도 알려져 있습니다</p>
<p>한 쌍의 보색을 사용합니다 영어로 &#39;테트라&#39;는 4고 &#39;트라이&#39;는 3을 뜻합니다</p>
<p>그래서 트리아딕은 3가지 색을 사용하고 테트라딕은 4가지 색을 사용합니다</p>
<p>이 그림에서 디자이너가 해당 색상을 사용한 것을 볼 수 있습니다</p>
<p>다음 유형의 배색은 정사각 배색입니다</p>
<p>상대적으로 덜 알려진 배색법입니다</p>
<p>색상환 안에 사각형을 배치하면 됩니다 기본적으로 테트라딕 배색 방식입니다</p>
<p>다음 유형은 단색입니다</p>
<p>아름다운 배색입니다</p>
<p>기본적으로 이 색상 조화는 한가지 휴(원색)을 기본으로 하며</p>
<p>전체 색상 구성표는 서로 다른 쉐이드, 톤, 틴트를 사용하여 만들어집니다</p>
<p>네 가지 단어를 말씀드렸습니다. 휴, 쉐이드, 톤, 틴트</p>
<p>이것을 이해하려면 이 색상 조합을 보면 될 것 같습니다</p>
<p>이 네 가지가 무엇인지 설명하겠습니다</p>
<p>휴는 기본적으로 어떤 혼합도 없는 순수한 색입니다</p>
<p>휴에 흰색을 섞으면 틴트가 됩니다</p>
<p>휴에 회색을 섞으면 톤이 됩니다</p>
<p>그리고 휴에 검은색을 섞으면 쉐이드가 됩니다</p>
<p>화장품과 관련해서 아마 이 단어들을 들어보셨을 것입니다</p>
<p>이제 단색의 색상 조화로 돌아가 보겠습니다</p>
<p>정의를 다시 살펴보겠습니다</p>
<p>정의에 따르면 단색 색상 조합은 단일 기본 색상을 사용하고</p>
<p>색채 배합을 쉐이드, 톤, 틴트 색상의 다른 세트 톤을 사용하여 색상 구성을 확장합니다</p>
<p>이 색상환에서는 빨간색, 녹색, 노란색, 주황색 등의 단색 색상 구성을 볼 수 있습니다</p>
<p>이 예에서는 이 그림이 파란색 단색을 사용하는 것을 볼 수 있습니다</p>
<p>이것이 바로 색상 조화를 사용하여 놀라운 디자인을 만드는 방법입니다</p>
<p>이번 강의에서는 색이론에 대해 자세히 배웠고,</p>
<p>색의 조화를 이루는 방법을 이해했습니다</p>
<hr>
<p>unspalsh</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[sqs 스프링]]></title>
            <link>https://velog.io/@progect_study/sqs-%EC%8A%A4%ED%94%84%EB%A7%81</link>
            <guid>https://velog.io/@progect_study/sqs-%EC%8A%A4%ED%94%84%EB%A7%81</guid>
            <pubDate>Sun, 15 Sep 2024 02:58:04 GMT</pubDate>
            <description><![CDATA[<h1 id="삽질g">삽질(#G)</h1>
<p>sqs 스프링 연결을 할 줄 몰라서 힘들었던 부분을 정리합니다.
아래의 블로그에 서 자세히 다룹니다.</p>
<p><a href="https://devbksheen.tistory.com/entry/Spring-boot-3x-Amazon-SQS-%EC%A0%81%EC%9A%A9%EA%B8%B0">https://devbksheen.tistory.com/entry/Spring-boot-3x-Amazon-SQS-%EC%A0%81%EC%9A%A9%EA%B8%B0</a></p>
<pre><code>#sqs 에서 발급
cloud.aws.region.static=us-ea
cloud.aws.sqs.queue.name=real_estat
cloud.aws.sqs.queue.url=

#iam 에서 발급
spring.cloud.aws.credentials.access-key=
spring.cloud.aws.credentials.secret-key=w</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[AL 공부]]></title>
            <link>https://velog.io/@progect_study/AL-%EA%B3%B5%EB%B6%80</link>
            <guid>https://velog.io/@progect_study/AL-%EA%B3%B5%EB%B6%80</guid>
            <pubDate>Wed, 11 Sep 2024 11:36:55 GMT</pubDate>
            <description><![CDATA[<h1 id="al-ml-dl">AL ML DL</h1>
<p>인공지능(AI), 머신러닝(ML), 그리고 딥러닝(DL)은 모두 데이터 분석과 학습에 관련된 기술이지만, 그 범위와 접근 방식에서 차이가 있습니다.</p>
<p>인공지능 (AI, Artificial Intelligence)
AI는 인간처럼 사고하고 결정을 내릴 수 있는 기계를 만드는 기술을 말합니다. AI는 아주 넓은 개념으로, 데이터를 기반으로 문제를 해결하고, 학습하고, 적응하는 시스템을 포함합니다. AI는 규칙 기반 시스템부터 고급 알고리즘까지 포함하며, 자연어 처리, 컴퓨터 비전 등 다양한 분야에서 활용됩니다.</p>
<p>머신러닝 (ML, Machine Learning)
머신러닝은 AI의 하위 분야로, 컴퓨터가 명시적인 프로그래밍 없이도 데이터에서 패턴을 학습해 예측 또는 결정을 내리는 기술입니다. ML은 데이터로부터 학습하고, 성능을 개선하며, 주로 통계적 방법을 사용합니다. 대표적인 알고리즘으로는 선형 회귀, 의사결정 나무, k-최근접 이웃(KNN) 등이 있습니다.</p>
<p>딥러닝 (DL, Deep Learning)
딥러닝은 머신러닝의 하위 분야로, 다층 신경망(Neural Networks)을 사용하여 더 복잡한 패턴을 학습합니다. 특히 이미지, 음성, 자연어 처리 등에서 매우 강력한 성능을 보여주며, 데이터의 양이 많을수록 성능이 향상됩니다. DL 모델은 여러 계층의 신경망을 사용하여 데이터를 추상화하고, 사람의 개입 없이도 자동으로 중요한 특징을 추출해냅니다. 대표적으로 CNN(Convolutional Neural Networks), RNN(Recurrent Neural Networks)이 있습니다.</p>
<p>요약:
AI: 인공지능, 컴퓨터가 인간처럼 사고하고 행동하는 기술
ML: 머신러닝, 데이터로부터 학습하는 기술 (AI의 하위 분야)
DL: 딥러닝, 다층 신경망을 이용한 머신러닝 (ML의 하위 분야)
ML은 비교적 간단한 모델을 사용하며, DL은 대규모 데이터와 복잡한 신경망을 다룹니다.</p>
<hr>
<h1 id="cnn-rnn-gan">CNN RNN GAN</h1>
<p>CNN(Convolutional Neural Networks), RNN(Recurrent Neural Networks), 그리고 GAN(Generative Adversarial Networks)는 모두 딥러닝의 하위 분야에 속하며, 각각 다른 방식으로 데이터를 처리하고 학습합니다. 그 차이점을 설명하자면:</p>
<ol>
<li>CNN (Convolutional Neural Networks)
주요 사용 분야: 이미지 처리 및 분석
구조 및 원리: CNN은 이미지나 영상 같은 2차원 데이터를 처리하는 데 최적화된 구조입니다. 컨볼루션 레이어를 통해 이미지에서 중요한 특징(엣지, 색상, 패턴 등)을 추출하고, 이를 기반으로 학습합니다.
특징:
컨볼루션 필터를 사용하여 데이터를 국소적으로 처리하고, 이미지 내 중요한 패턴을 학습합니다.
풀링(Pooling) 연산을 통해 데이터 크기를 줄이면서도 중요한 특징을 유지합니다.
이미지 분류, 객체 탐지, 얼굴 인식 같은 문제에서 주로 사용됩니다.</li>
<li>RNN (Recurrent Neural Networks)
주요 사용 분야: 순차적 데이터 처리 (텍스트, 시간 시계열 데이터)
구조 및 원리: RNN은 시간적 순서가 중요한 데이터를 처리하는 데 특화된 신경망입니다. RNN은 피드백 루프를 가지고 있어 이전의 출력이 다음 입력으로 연결되기 때문에, 시간 순서에 따른 패턴을 학습할 수 있습니다.
특징:
순차적 데이터 (예: 텍스트, 음성 데이터)를 처리하며, 과거 정보가 현재 데이터에 영향을 미칠 수 있도록 설계되었습니다.
하지만 장기 의존성(long-term dependency) 문제로 인해, 긴 시퀀스에서는 성능이 저하될 수 있습니다. 이를 해결하기 위해 LSTM(Long Short-Term Memory)이나 GRU(Gated Recurrent Unit) 같은 변형된 RNN이 사용됩니다.
자연어 처리(NLP), 음성 인식, 시계열 예측에서 주로 사용됩니다.</li>
<li>GAN (Generative Adversarial Networks)
주요 사용 분야: 데이터 생성 (이미지, 텍스트, 음성)
구조 및 원리: GAN은 <strong>생성자(Generator)</strong>와 <strong>판별자(Discriminator)</strong>라는 두 신경망이 서로 경쟁하면서 학습하는 구조입니다. 생성자는 데이터를 생성하고, 판별자는 그 데이터가 진짜인지 가짜인지를 구분하는 역할을 합니다. 두 신경망이 경쟁하면서 생성자는 점점 더 진짜 같은 데이터를 만들 수 있게 됩니다.
특징:
GAN은 새로운 데이터를 생성하는 데 뛰어납니다. 예를 들어, 실제처럼 보이는 가짜 이미지나 텍스트를 생성할 수 있습니다.
비지도 학습(unsupervised learning)의 대표적인 예로, 데이터의 레이블이 필요 없이 학습할 수 있습니다.
이미지를 변환하거나, 새로운 예술 작품을 생성하는 등 창의적인 작업에 자주 사용됩니다.
요약:
CNN: 이미지와 같은 2D 데이터를 처리하며, 패턴과 특징을 추출하는 데 강점이 있음.
RNN: 순차적 데이터 처리에 적합하며, 시간적 패턴을 학습할 수 있음. 주로 텍스트, 음성, 시계열 데이터를 처리.
GAN: 생성자와 판별자가 경쟁하며 학습하는 구조로, 새로운 데이터를 생성하는 데 특화됨.
이들 네트워크는 각각의 데이터 유형과 문제에 따라 최적화된 방식으로 사용됩니다.</li>
</ol>
<hr>
<p>머신러닝에는 다양한 학습 방식이 있으며, 그 중 대표적인 방법들이 지도학습, 비지도학습, 자기지도학습, 그리고 강화학습입니다. 각 방법은 데이터를 처리하고 학습하는 방식에 차이가 있습니다.</p>
<ol>
<li>지도학습 (Supervised Learning)
정의: 지도학습은 입력 데이터와 이에 대응하는 <strong>정답(레이블)</strong>을 사용하여 모델을 학습시키는 방법입니다.
예시: 이미지 분류, 스팸 메일 필터링, 가격 예측 등
원리: 모델은 입력과 레이블(출력) 쌍을 학습하여, 새로운 입력에 대해 적절한 출력을 예측합니다. 데이터에 명확한 정답이 있기 때문에, 모델의 성능을 측정하고 개선하는 것이 상대적으로 쉽습니다.
주요 알고리즘: 선형 회귀, 의사결정나무, 랜덤 포레스트, SVM, 신경망 등</li>
</ol>
<p><strong>지도학습(Supervised Learning)</strong>에서 <strong>회귀(Regression)</strong>와 <strong>분류(Classification)</strong>는 데이터의 목표 변수(출력값)가 연속적인 값인지 아니면 이산적인 값인지에 따라 차이가 있습니다.</p>
<ol>
<li>회귀 (Regression)
정의: 회귀는 <strong>연속적인 값(수치형)</strong>을 예측하는 문제를 해결하는 방식입니다. 목표는 입력 데이터에 대해 숫자 범위 내에서 특정 값을 예측하는 것입니다.
예시:
주택 가격 예측 (평수, 위치, 방 개수 등을 입력으로 받아 집값을 예측)
주식 가격 예측 (과거 데이터를 기반으로 미래의 주가를 예측)
날씨 예측 (온도, 습도 등을 기반으로 기온 예측)
주요 특징:
목표 변수는 연속적입니다. 예를 들어, 5.3이나 100.4와 같은 소수점 값을 가질 수 있습니다.
모델은 입력과 목표 변수 사이의 관계를 학습하여, 새로운 입력에 대해 적절한 연속 값을 예측합니다.
주요 알고리즘:
선형 회귀(Linear Regression)
다항 회귀(Polynomial Regression)
결정 트리 회귀(Decision Tree Regression)
랜덤 포레스트 회귀(Random Forest Regression)</li>
<li>분류 (Classification)
정의: 분류는 데이터를 이산적인 클래스 또는 범주형 값으로 나누는 문제를 해결합니다. 목표는 입력 데이터가 특정 클래스(카테고리)에 속하는지를 예측하는 것입니다.
예시:
스팸 이메일 분류 (이메일이 &quot;스팸&quot;인지 &quot;정상&quot;인지 분류)
암 진단 (세포 데이터를 분석하여 암인지 아닌지 예측)
손글씨 숫자 인식 (이미지 데이터를 숫자 0부터 9까지 분류)
주요 특징:
목표 변수는 이산적으로, 예를 들어 클래스 0, 1 또는 정상, 비정상 등으로 분류됩니다.
2개의 클래스만 구분하는 이진 분류(binary classification) 문제와, 3개 이상의 클래스를 다루는 다중 분류(multi-class classification) 문제로 나뉩니다.
주요 알고리즘:
로지스틱 회귀(Logistic Regression)
결정 트리(Classification Trees)
서포트 벡터 머신(SVM)
k-최근접 이웃(K-Nearest Neighbors, KNN)
나이브 베이즈(Naive Bayes)
회귀 vs. 분류 차이점
특징    회귀(Regression)    분류(Classification)
목표 변수(출력값)    연속적인 값 (예: 실수, 소수점)    이산적인 값 (예: 범주, 클래스)
예시    주택 가격, 주식 가격, 온도 예측    스팸 여부, 암 진단, 숫자 인식
주요 평가 지표    평균 제곱 오차(MSE), R² 점수    정확도(Accuracy), 정밀도(Precision), 재현율(Recall), F1 점수
목표    수치형 값을 예측    데이터가 어떤 카테고리에 속하는지 분류
알고리즘    선형 회귀, 다항 회귀, 랜덤 포레스트 회귀    로지스틱 회귀, 결정 트리, SVM, KNN
요약:
회귀는 연속적인 수치형 데이터를 예측할 때 사용되고, 분류는 데이터를 특정 범주나 클래스로 나누는 문제에 사용됩니다.</li>
</ol>
<ol start="2">
<li>비지도학습 (Unsupervised Learning)
정의: 비지도학습은 레이블 없이 주어진 데이터에서 패턴이나 구조를 찾는 방법입니다.
예시: 군집화(클러스터링), 차원 축소, 이상 탐지 등
원리: 데이터의 정답이 제공되지 않으므로, 모델은 데이터를 그룹화하거나 데이터를 요약하는 방식으로 학습합니다. 이는 데이터에 숨겨진 패턴을 찾아내거나 데이터를 시각화하는 데 유용합니다.
주요 알고리즘: K-평균(K-means), 주성분 분석(PCA), 군집화 알고리즘, 오토인코더 등</li>
<li>자기지도학습 (Self-Supervised Learning)
정의: 자기지도학습은 데이터의 일부를 레이블 없이 사용하여, 그 데이터를 자체적으로 레이블링하여 학습하는 방법입니다.
예시: GPT, BERT 같은 자연어 처리 모델에서의 사전 학습
원리: 자기지도학습은 비지도학습과 유사하지만, 데이터의 한 부분을 감추거나 변형하여 그 부분을 예측하게 함으로써 학습이 이루어집니다. 이 방식은 모델이 더 나은 표현을 학습하게 도와줍니다. 레이블이 필요 없는 상황에서 유용하며, 특히 딥러닝에서 많이 사용됩니다.
주요 알고리즘: BERT, GPT 등 사전 학습된 모델</li>
<li>강화학습 (Reinforcement Learning)
정의: 강화학습은 <strong>행동(Action)</strong>을 취하고, 그 결과에 대한 <strong>보상(Reward)</strong>을 받아 최적의 행동을 학습하는 방법입니다.
예시: 게임 AI, 자율 주행 자동차, 로봇 제어
원리: 에이전트는 환경과 상호작용하면서 행동을 선택하고, 그 행동의 결과로 보상을 받습니다. 에이전트는 보상을 극대화하는 방향으로 학습하며, 탐색과 활용의 균형을 맞춰가며 최적의 정책(policy)을 찾습니다.
주요 알고리즘: Q-learning, SARSA, Deep Q-Networks(DQN), 정책 경사법(Policy Gradient) 등
요약:
지도학습: 정답(레이블)이 있는 데이터를 학습하여, 새로운 데이터에 대한 정확한 예측을 목표로 함.
비지도학습: 정답이 없는 데이터를 학습하여, 패턴이나 구조를 발견함.
자기지도학습: 레이블이 없는 데이터를 스스로 레이블링하여 학습하며, 큰 규모의 데이터에서 더 나은 표현 학습을 가능하게 함.
강화학습: 환경과 상호작용하면서 보상을 최대화하는 방식으로 학습, 최적의 행동 전략을 찾음.</li>
</ol>
<hr>
<p><strong>자기지도학습(Self-Supervised Learning)</strong>은 비지도학습의 한 형태로, 데이터를 사용하여 레이블을 스스로 생성하고, 이를 기반으로 모델을 학습시키는 방법입니다. 기존의 비지도학습과 달리, 자기지도학습은 명시적인 레이블 없이 데이터의 일부를 이용해 나머지를 예측하는 방식으로 학습을 진행합니다.</p>
<p>특징 및 원리:
데이터의 일부를 예측하는 방식: 자기지도학습은 데이터에서 어떤 힌트(특정 정보를 감추거나 변형)를 주고, 모델이 그 힌트로부터 원래의 데이터를 복원하거나 예측하는 과정을 통해 학습합니다. 이 과정을 통해 모델은 데이터의 구조와 중요한 특징을 학습하게 됩니다.</p>
<p>레이블 생성: 자기지도학습에서 모델은 레이블을 스스로 생성합니다. 일반적으로 레이블이 필요하지 않지만, 데이터를 가공하여 일부를 감춘 뒤(또는 다른 방식으로 변경한 후) 이를 예측하는 작업을 통해 레이블 역할을 하게 됩니다.</p>
<p>주요 사례:
언어 모델링:</p>
<p>NLP에서 자기지도학습이 활발히 사용됩니다. 예를 들어, GPT나 BERT 같은 언어 모델들은 문장이나 텍스트의 일부 단어를 감추고, 나머지 단어를 통해 감춰진 단어를 예측하는 방식으로 학습합니다. 이를 통해 모델은 자연어의 패턴과 문맥을 이해할 수 있게 됩니다.
마스크드 언어 모델링(Masked Language Modeling): BERT는 문장에서 일부 단어를 마스킹(masking)한 후, 그 마스킹된 단어를 예측하는 방식으로 학습됩니다.
컴퓨터 비전:</p>
<p>이미지 처리에서 자기지도학습을 사용하면 이미지의 일부를 숨기거나 왜곡한 뒤, 원래 이미지로 복원하는 작업을 통해 이미지의 패턴을 학습할 수 있습니다.
예를 들어, 컬러 이미지 복원에서는 흑백 이미지를 입력으로 넣고, 원래 컬러 이미지를 예측하게 하는 방식으로 학습합니다.
컨트라스티브 학습(Contrastive Learning):</p>
<p>자기지도학습의 또 다른 방법으로, 데이터의 양극적인 쌍을 이용해 학습하는 방법입니다. 예를 들어, 같은 이미지를 약간 변형한 두 버전을 모델에게 보여주고, 이 둘이 같은 데이터라는 사실을 학습하게 합니다. SimCLR나 MoCo 같은 모델들이 이 방식으로 학습합니다.
자기지도학습의 장점:
대규모의 데이터 활용: 자기지도학습은 레이블이 없는 데이터를 효과적으로 활용할 수 있습니다. 대규모 데이터셋에서 레이블을 생성하기 위한 수작업은 매우 비용이 많이 들기 때문에, 자기지도학습은 이 문제를 해결하는 좋은 방법입니다.
사전 학습(Pre-training): 자기지도학습은 많은 데이터를 사용해 사전 학습을 수행한 후, 이를 다른 작업에 <strong>전이 학습(transfer learning)</strong>할 수 있습니다. 특히 BERT나 GPT 같은 모델들은 자기지도학습을 통해 방대한 양의 데이터에서 패턴을 학습한 뒤, 다양한 자연어 처리 작업에 적용됩니다.
요약:
자기지도학습은 데이터에서 일부 정보를 숨기거나 변형하여, 그 정보로 나머지 데이터를 예측하는 방식으로 학습을 진행합니다. 이를 통해 대규모 비지도 데이터로부터 유의미한 표현을 학습하고, 다양한 작업에 사용할 수 있습니다. 특히 자연어 처리와 컴퓨터 비전 분야에서 많이 사용되며, 비지도 학습과 지도 학습의 중간 단계로 간주될 수 있습니다.</p>
<hr>
<p>강화학습</p>
<p><strong>강화학습(Reinforcement Learning)</strong>은 <strong>행동(Action)</strong>을 취하고, 그 행동의 결과로부터 <strong>보상(Reward)</strong>을 받아, 환경(Environment)과 상호작용하면서 최적의 행동을 학습하는 방법입니다. 이는 게임이나 로봇 제어와 같은 문제에서 자주 사용되며, 에이전트(Agent)가 스스로 경험을 통해 학습하면서 목표를 달성하는 방식입니다.</p>
<p>강화학습의 핵심 요소:
에이전트(Agent):</p>
<p>강화학습을 수행하는 주체로, 환경과 상호작용하면서 행동을 선택합니다. 에이전트는 환경으로부터 피드백을 받아 학습합니다.
환경(Environment):</p>
<p>에이전트가 상호작용하는 대상입니다. 에이전트가 행동을 취하면, 환경은 그에 대한 보상과 상태(State) 변화를 에이전트에게 전달합니다.
상태(State):</p>
<p>환경의 현재 상태를 나타냅니다. 에이전트는 이 상태를 바탕으로 다음 행동을 결정합니다.
행동(Action):</p>
<p>에이전트가 환경에서 취할 수 있는 선택지입니다. 에이전트는 상태를 기반으로 여러 가지 행동 중 하나를 선택합니다.
보상(Reward):</p>
<p>에이전트가 취한 행동에 대해 환경이 제공하는 피드백입니다. 보상은 양수(positive)나 음수(negative)일 수 있으며, 에이전트는 최대한 많은 보상을 얻기 위해 학습합니다.
정책(Policy):</p>
<p>에이전트가 어떤 상태에서 어떤 행동을 취할지 결정하는 전략입니다. 정책은 에이전트가 환경과 상호작용하면서 업데이트되며, 최적의 행동을 찾는 것이 목표입니다.
가치 함수(Value Function):</p>
<p>주어진 상태에서 장기적으로 얻을 수 있는 기대 보상을 나타냅니다. 에이전트는 가치 함수가 최대화되도록 행동을 결정합니다.
강화학습의 작동 원리:
에이전트는 현재 <strong>상태(State)</strong>를 인식하고, 그 상태에서 취할 수 있는 여러 가지 행동(Action) 중 하나를 선택합니다. 선택한 행동은 <strong>환경(Environment)</strong>에 영향을 미치며, 환경은 그에 따른 <strong>보상(Reward)</strong>과 새로운 상태를 에이전트에게 제공합니다.
에이전트는 이러한 과정을 반복하면서, 장기적으로 최대한 많은 보상을 얻는 방향으로 학습하게 됩니다. 이를 통해 에이전트는 환경에서 <strong>최적의 정책(Optimal Policy)</strong>을 찾아낼 수 있습니다.
강화학습의 학습 과정:
<strong>탐색(Exploration)</strong>과 <strong>활용(Exploitation)</strong>의 균형:
강화학습에서 에이전트는 최적의 정책을 찾기 위해 새로운 행동을 탐색(Exploration)할지, 아니면 이미 알고 있는 행동을 활용(Exploitation)할지 결정해야 합니다. 탐색은 새로운 지식을 얻기 위한 행동이고, 활용은 기존의 지식을 바탕으로 보상을 극대화하는 행동입니다.
주요 알고리즘:
Q-Learning:</p>
<p>상태와 행동의 쌍을 기반으로, 각 행동에 대한 <strong>Q-값(보상 기대치)</strong>을 학습합니다. 에이전트는 Q-값이 높은 행동을 선택하는 방식으로 최적의 정책을 학습합니다. Q-Learning은 환경의 모델 없이도 학습이 가능하여, 모델-프리(model-free) 방법이라고도 불립니다.
SARSA:</p>
<p>Q-Learning과 유사하지만, SARSA는 실제로 취한 행동에 따라 Q-값을 업데이트합니다. 이를 통해 정책에 따른 행동을 더 정확하게 반영할 수 있습니다.
Deep Q-Networks (DQN):</p>
<p>Q-Learning을 심층 신경망(Deep Neural Networks)을 이용해 확장한 방법입니다. Q-값을 추정하는 데 딥러닝을 사용하여, 복잡한 환경에서도 강화학습을 적용할 수 있습니다. 알파고와 같은 고급 AI 시스템에 적용됩니다.
정책 경사법(Policy Gradient):</p>
<p>Q-값을 학습하는 대신, 정책 자체를 직접 학습하는 방법입니다. 이 방법은 연속적인 행동 공간에서 강화학습을 가능하게 하며, <strong>Proximal Policy Optimization (PPO)</strong>과 같은 방법들이 이에 해당합니다.
강화학습의 활용 사례:
게임: 에이전트가 게임을 플레이하며, 최적의 전략을 학습합니다. 예를 들어, 알파고(AlphaGo)는 바둑 게임에서 강화학습을 통해 세계 최고의 실력을 갖추었습니다.
로봇 공학: 로봇이 환경에서 스스로 학습하면서 걷기, 물건 집기 등의 작업을 수행할 수 있습니다.
자율주행차: 차량이 주변 환경과 상호작용하며 최적의 경로를 학습하여, 안전하고 효율적으로 주행합니다.
추천 시스템: 사용자의 피드백을 기반으로 최적의 상품이나 콘텐츠를 추천하는 시스템에 활용됩니다.
강화학습의 장점:
자율성: 에이전트가 스스로 학습하고 환경에 적응하면서 최적의 행동을 학습할 수 있습니다.
보상 기반 학습: 명확한 목표(보상 극대화)가 주어져 있어, 다양한 상황에서 적응력을 발휘할 수 있습니다.
강화학습의 단점:
탐색 문제: 새로운 행동을 탐색하는 과정에서, 초기에는 비효율적인 행동을 많이 할 수 있습니다.
학습 속도: 복잡한 환경에서는 학습에 많은 시간과 계산 자원이 소모될 수 있습니다.
불안정성: 학습이 제대로 되지 않거나, 환경이 너무 복잡할 경우 학습이 불안정할 수 있습니다.
요약:
강화학습은 에이전트가 환경과 상호작용하며 보상을 극대화하는 방향으로 최적의 행동을 학습하는 방법입니다. 에이전트는 경험을 통해 정책을 개선하며, 다양한 분야에서 효율적으로 활용됩니다.</p>
<hr>
<ol>
<li>인공 신경망(Artificial Neural Network, ANN)</li>
</ol>
<p>인공 신경망은 뇌의 신경망(neural network)을 모방한 모델로, 입력 데이터를 받아 다양한 <strong>가중치(weight)</strong>와 <strong>편향(bias)</strong>을 거쳐 출력을 생성하는 함수라고 할 수 있습니다. 이 과정에서 인공 신경망은 데이터의 패턴을 학습하여 예측이나 분류 작업을 수행하게 됩니다.</p>
<p>인공 신경망의 핵심 개념:
뉴런(Neuron): 인공 신경망의 기본 구성 요소로, 입력을 받아 특정 수학적 연산(주로 가중치 곱셈 및 편향 추가 후 활성화 함수 적용)을 수행하고 출력을 생성합니다.</p>
<p>레이어(Layer): 여러 뉴런이 모여 하나의 층(layer)을 이루며, 입력층(input layer), 은닉층(hidden layer), 출력층(output layer)으로 구성됩니다.</p>
<p>입력(input): 신경망이 학습하거나 예측을 수행하기 위해 받는 데이터입니다. 각 입력 값은 가중치와 함께 뉴런으로 전달됩니다.</p>
<ol start="2">
<li><strong>Weight(가중치)</strong>와 Bias(편향)
Weight와 Bias는 인공 신경망에서 가장 중요한 두 개념으로, 신경망이 학습하는 주요 요소입니다.</li>
</ol>
<p>2.1 Weight (가중치)
정의: 가중치는 입력 데이터가 뉴런에 전달될 때 얼마나 중요한지를 나타내는 값입니다. 각 입력 값과 연결된 가중치는 그 입력의 영향력을 조절합니다.
역할: 가중치는 입력에 대해 곱해진 후 뉴런에 전달되며, 그 값이 크면 입력 값이 더 중요한 것으로 간주되고, 작으면 중요도가 낮다고 해석됩니다.
직관적 이해: 가중치는 입력 데이터가 얼마나 중요한지 결정하는 필터와 같은 역할을 합니다. 예를 들어, 이미지 인식에서 특정 픽셀이 더 중요하게 여겨진다면 그 픽셀의 가중치는 더 크게 학습됩니다.
2.2 Bias (편향)
정의: 편향은 가중치가 곱해진 입력의 총합에 추가되는 상수 값입니다. 가중치가 입력의 중요도를 조절한다면, 편향은 신경망이 어느 정도의 기준치에서 출발할지 조정하는 역할을 합니다.
역할: 편향은 모델이 특정 출력 값을 더 쉽게 생성할 수 있도록 도와줍니다. 이는 신경망이 0에서만 시작하는 것이 아니라, 보다 유연하게 다양한 값을 예측할 수 있게 해줍니다.
직관적 이해: 편향은 모델이 학습할 때 출발점을 조정하는 값으로 생각할 수 있습니다. 즉, 특정 상황에서 출력이 조금 더 높거나 낮게 시작해야 할 경우, 편향 값이 그 조정을 담당합니다.
3. 인공 신경망은 함수다!
인공 신경망은 사실 하나의 복잡한 함수로 볼 수 있습니다. 이 함수는 입력 값을 받아 출력 값을 계산하는 일련의 연산을 수행하며, 가중치와 편향이 포함된 여러 수학적 연산을 통해 입력 데이터에서 학습된 패턴을 바탕으로 예측을 수행합니다.</p>
<p>수학적 표현: 인공 신경망에서 뉴런의 출력은 아래와 같은 수식으로 표현할 수 있습니다.</p>
<h1 id="𝑦">𝑦</h1>
<p>𝑓
(
𝑊
⋅
𝑥
+
𝑏
)
y=f(W⋅x+b)
𝑊
W: 가중치(weight) 매트릭스
𝑥
x: 입력 벡터
𝑏
b: 편향(bias)
𝑓
f: 활성화 함수 (Activation Function)
이 수식에서 입력 데이터 
𝑥
x는 가중치 
𝑊
W와 곱해지고, 편향 
𝑏
b가 더해집니다. 그 다음, 활성화 함수 
𝑓
f를 통해 최종 출력 값 
𝑦
y가 계산됩니다. 이 모든 과정은 입력 데이터를 변환하여 최종 출력(예측 값)을 생성하는 과정으로, 결국 하나의 함수라고 할 수 있습니다.</p>
<ol start="4">
<li>활성화 함수(Activation Function)
인공 신경망에서 중요한 또 하나의 요소는 활성화 함수입니다. 이는 입력의 총합에 비선형성을 추가하여 신경망이 복잡한 문제를 풀 수 있게 만들어줍니다. 선형 함수만 사용하면 단순한 선형 관계만 학습하게 되기 때문에, 비선형 함수가 필요합니다.</li>
</ol>
<p>대표적인 활성화 함수:
ReLU (Rectified Linear Unit): 주로 딥러닝에서 많이 사용되는 함수로, 양수인 경우는 그대로 출력하고, 음수인 경우는 0으로 출력합니다.
Sigmoid: 출력 값을 0과 1 사이로 제한하여, 확률 값을 나타내는 문제에서 많이 사용됩니다.
Tanh: 출력 값을 -1과 1 사이로 제한하며, Sigmoid와 유사하지만 출력 범위가 다릅니다.
요약:
인공 신경망은 하나의 함수로, 입력 데이터를 받아 가중치와 편향을 적용하여 예측 값을 출력합니다.
<strong>가중치(Weight)</strong>는 입력 데이터의 중요도를 결정하고, <strong>편향(Bias)</strong>은 신경망의 출발점을 조정하여 더 유연하게 학습할 수 있게 합니다.
이 모든 과정은 수학적으로 표현 가능한 함수 연산을 통해 이루어지며, 활성화 함수는 비선형성을 추가하여 신경망이 더 복잡한 패턴을 학습할 수 있게 돕습니다.</p>
<hr>
<p><strong>선형 회귀(Linear Regression)</strong>는 연속형 데이터를 기반으로 두 변수 사이의 관계를 직선으로 모델링하는 방법입니다. 즉, 주어진 입력 데이터를 이용해 최적의 직선을 찾아내는 것이 목표입니다. 이때 직선의 방정식은 y = mx + b (또는 y = Wx + b) 형태로 표현됩니다. 선형 회귀는 두 가지 주요 형태로 나뉩니다: 단순 선형 회귀와 다중 선형 회귀.</p>
<ol>
<li>선형 회귀의 개념
선형 회귀의 목표는 <strong>입력 변수(독립 변수)</strong>와 출력 변수(종속 변수) 사이의 선형 관계를 모델링하는 것입니다. 이를 통해 우리는 미래의 데이터를 예측할 수 있습니다.</li>
</ol>
<p>단순 선형 회귀(Simple Linear Regression):
입력 변수와 출력 변수가 각각 하나인 경우, 즉 
𝑦
=
𝑤
𝑥
+
𝑏
y=wx+b 같은 형태로 예측 모델을 만듭니다.
다중 선형 회귀(Multiple Linear Regression):
하나 이상의 입력 변수를 사용하여 출력 값을 예측합니다. 즉, 여러 독립 변수 
𝑥
1
,
𝑥
2
,
…
,
𝑥
𝑛
x 
1
​
 ,x 
2
​
 ,…,x 
n
​
 과 하나의 종속 변수 
𝑦
y 사이의 관계를 선형으로 나타냅니다.
다중 선형 회귀는 
𝑦
=
𝑤
1
𝑥
1
+
𝑤
2
𝑥
2
+
⋯
+
𝑤
𝑛
𝑥
𝑛
+
𝑏
y=w 
1
​
 x 
1
​
 +w 
2
​
 x 
2
​
 +⋯+w 
n
​
 x 
n
​
 +b 형태로 나타냅니다.
2. 선형 회귀의 수학적 모델
선형 회귀에서 <strong>입력 변수 
𝑥
x</strong>와 출력 변수 
𝑦
y 사이의 관계는 아래와 같은 수식으로 표현됩니다:</p>
<h1 id="𝑦-1">𝑦</h1>
<p>𝑊
𝑥
+
𝑏
y=Wx+b
여기서:</p>
<p>𝑦
y: 예측값 (종속 변수)
𝑊
W: 가중치(weight), 기울기(slope) 또는 계수(coefficients)로도 불립니다.
𝑥
x: 입력 데이터 (독립 변수)
𝑏
b: 편향(bias) 또는 절편(intercept)이라고도 합니다.
3. 손실 함수(Loss Function)와 비용 함수(Cost Function)
선형 회귀 모델을 학습하는 과정에서 중요한 목표는 예측 값과 실제 값의 차이를 최소화하는 것입니다. 이 차이를 측정하는 기준이 손실 함수입니다.</p>
<p>오차(Error): 각 데이터 포인트에서 모델이 예측한 값과 실제 값의 차이</p>
<p>𝐸
𝑟
𝑟
𝑜
𝑟
=
𝑦
actual
−
𝑦
predicted
Error=y 
actual
​
 −y 
predicted
​</p>
<p>손실 함수(Loss Function): 전체 데이터에서 모델의 성능을 평가하는 데 사용됩니다. 주로 <strong>평균 제곱 오차(Mean Squared Error, MSE)</strong>가 사용됩니다.</p>
<p>𝑀
𝑆
𝐸
=
1
𝑛
∑
𝑖
=
1
𝑛
(
𝑦
𝑖
−
𝑦
𝑖
^
)
2
MSE= 
n
1
​</p>
<p>i=1
∑
n
​
 (y 
i
​
 − 
y 
i
​</p>
<p>^
​
 ) 
2</p>
<p>𝑦
𝑖
y 
i
​
 : 실제 값
𝑦
𝑖
^
y 
i
​</p>
<p>^
​
 : 예측 값
𝑛
n: 데이터의 개수
MSE는 예측 값과 실제 값의 차이(오차)를 제곱하여 전체 데이터에 대해 평균을 구하는 방식입니다. 오차의 제곱을 사용하면, 음수 오차가 상쇄되지 않고 더 큰 오차에 더 큰 페널티를 부여할 수 있습니다.</p>
<ol start="4">
<li>최적화: 경사 하강법(Gradient Descent)
모델을 학습시키는 과정에서는 <strong>최적의 가중치(W)</strong>와 <strong>편향(b)</strong>을 찾아서 손실 함수를 최소화하는 것이 목표입니다. 이를 위해 많이 사용되는 알고리즘이 <strong>경사 하강법(Gradient Descent)</strong>입니다.</li>
</ol>
<p>경사 하강법은 손실 함수의 기울기(경사)를 계산하여, 그 경사의 반대 방향으로 가중치와 편향을 조정함으로써 손실을 줄이는 방법입니다.</p>
<p>경사 하강법의 주요 단계:
가중치(W)와 편향(b)의 초기화: 일반적으로 임의의 값으로 시작합니다.
손실 함수의 기울기 계산: MSE와 같은 손실 함수에 대한 가중치와 편향의 기울기를 계산합니다.
가중치 W에 대한 미분: 
∂
𝑀
𝑆
𝐸
∂
𝑊
∂W
∂MSE
​</p>
<p>편향 b에 대한 미분: 
∂
𝑀
𝑆
𝐸
∂
𝑏
∂b
∂MSE
​</p>
<p>가중치와 편향 업데이트: 기울기의 반대 방향으로 가중치와 편향을 업데이트합니다.
𝑊
:
=
𝑊
−
𝛼
⋅
∂
𝑀
𝑆
𝐸
∂
𝑊
W:=W−α⋅ 
∂W
∂MSE
​</p>
<p>𝑏
:
=
𝑏
−
𝛼
⋅
∂
𝑀
𝑆
𝐸
∂
𝑏
b:=b−α⋅ 
∂b
∂MSE
​</p>
<p>여기서 
𝛼
α는 학습률(learning rate)로, 한 번에 얼마나 많은 변화량을 적용할지 결정합니다.
반복: 손실 함수가 최소화될 때까지 반복적으로 기울기를 계산하고 업데이트합니다.
5. 선형 회귀의 학습 과정: Step by Step
Step 1: 데이터 준비
입력 데이터 
𝑥
x와 대응하는 출력 데이터 
𝑦
y가 주어져야 합니다. 이는 모델이 학습하는 데 필요한 훈련 데이터입니다.</p>
<p>Step 2: 모델 정의
모델은 아래와 같은 수식으로 정의됩니다:</p>
<h1 id="𝑦-2">𝑦</h1>
<p>𝑊
𝑥
+
𝑏
y=Wx+b
여기서 
𝑊
W와 
𝑏
b는 학습을 통해 찾아내야 하는 가중치와 편향입니다.</p>
<p>Step 3: 손실 함수 정의
손실 함수로 <strong>MSE(평균 제곱 오차)</strong>를 사용하여 모델의 예측과 실제 값의 차이를 평가합니다.</p>
<p>𝑀
𝑆
𝐸
=
1
𝑛
∑
𝑖
=
1
𝑛
(
𝑦
𝑖
−
𝑦
𝑖
^
)
2
MSE= 
n
1
​</p>
<p>i=1
∑
n
​
 (y 
i
​
 − 
y 
i
​</p>
<p>^
​
 ) 
2</p>
<p>Step 4: 경사 하강법을 사용한 학습
경사 하강법을 통해 <strong>가중치(W)</strong>와 <strong>편향(b)</strong>를 업데이트하면서 손실 함수를 최소화합니다. 학습률 
𝛼
α가 적절해야 경사 하강법이 효율적으로 작동합니다.</p>
<p>Step 5: 모델 평가
최종적으로 학습이 완료된 모델이 얼마나 잘 예측하는지 평가합니다. 일반적으로 <strong>평균 제곱 오차(MSE)</strong>나 R² (결정 계수) 같은 지표를 사용합니다.</p>
<ol start="6">
<li>선형 회귀의 가정
선형 회귀 모델을 사용할 때는 다음과 같은 가정이 성립해야 합니다:</li>
</ol>
<p>선형성(Linearity): 입력 변수와 출력 변수 사이의 관계는 선형적이어야 합니다.
독립성(Independence): 데이터 포인트 간의 독립성이 유지되어야 합니다.
등분산성(Homoscedasticity): 모든 데이터에서 오차의 분산이 동일해야 합니다.
정규성(Normality): 오차는 정규 분포를 따라야 합니다.
7. 선형 회귀의 장점과 단점
장점:
해석 용이성: 모델이 단순하고, 예측 결과를 해석하기 쉽습니다.
빠른 계산: 계산이 빠르며, 대규모 데이터에서도 효율적으로 작동합니다.
과적합 방지: 선형 회귀는 비교적 단순한 모델로, 과적합의 위험이 적습니다.
단점:
비선형 관계 모델링 불가능: 선형 회귀는 변수 간의 비선형 관계를 표현할 수 없습니다.
이상치에 민감함: 이상치(outlier)에 매우 민감하며, 이는 모델의 성능을 저하시킬 수 있습니다.
가정 위반에 취약함: 모델이 가정하는 조건(선형성, 등분산성 등)이 깨지면, 성능이 크게 떨어질 수 있습니다.
요약:
선형 회귀는 입력 변수와 출력 변수 사이의 선형 관계를 모델링하는 방법입니다.
모델의 목표는 <strong>가중치(W)</strong>와 <strong>편향(b)</strong>를 찾아내어 예측 오차를 최소화하는 것입니다.
경사 하강법을 통해 최적의 가중치와 편향을 찾아가는 과정에서 MSE와 같은 손실 함수를 최소화합니다.
선형 회귀는 간단하지만, 그만큼 비선형 관계나 복잡한 문제에서는 한계가 있습니다.</p>
<hr>
<p><strong>미니 배치 경사 하강법(Mini-Batch Gradient Descent)</strong>과 하이퍼파라미터 및 파라미터는 머신러닝 모델의 학습 및 최적화에서 중요한 개념입니다. 각 개념을 간단하게 설명하겠습니다.</p>
<ol>
<li>미니 배치 경사 하강법 (Mini-Batch Gradient Descent)
미니 배치 경사 하강법은 <strong>경사 하강법(Gradient Descent)</strong>의 변형으로, 전체 데이터셋을 작은 그룹(미니 배치)으로 나누어 각 그룹에 대해 기울기를 계산하고 가중치를 업데이트하는 방법입니다.</li>
</ol>
<p>작동 방식:</p>
<p>데이터셋을 여러 개의 미니 배치로 나누기: 데이터셋을 작은 배치로 나누어 각 배치에 대해 기울기를 계산합니다.
미니 배치 단위로 기울기 계산 및 업데이트: 각 미니 배치에 대해 손실 함수의 기울기를 계산하고 가중치를 업데이트합니다.
반복: 모든 미니 배치에 대해 이 과정을 반복하며, 전체 데이터셋에 대한 최적화를 진행합니다.
장점:</p>
<p>계산 효율성: 전체 데이터셋을 한 번에 처리하지 않으므로 메모리 소모가 줄어들고 계산이 더 빠릅니다.
기울기 추정의 노이즈 완화: 전체 데이터셋보다 미니 배치의 기울기가 더 자주 업데이트되므로, 기울기 추정의 노이즈를 완화할 수 있습니다.
속도와 안정성: 미니 배치는 경량화된 업데이트를 제공하여 더 빠르게 학습할 수 있으며, 전체 데이터셋을 사용할 때보다 안정적인 최적화가 가능합니다.
단점:</p>
<p>미니 배치 크기 조정: 미니 배치 크기에 따라 학습 성능이 달라질 수 있으며, 적절한 크기를 찾는 것이 중요합니다.
2. 하이퍼파라미터 (Hyperparameter)
하이퍼파라미터는 모델 학습 과정 전에 설정해야 하는 파라미터입니다. 이러한 값들은 모델의 학습 과정에 영향을 미치며, 일반적으로 모델의 구조나 학습 설정을 정의합니다.</p>
<p>예시:
학습률(Learning Rate): 경사 하강법에서 가중치를 업데이트할 때 기울기의 크기를 조정하는 값입니다.
배치 크기(Batch Size): 한 번의 업데이트에 사용되는 데이터의 양입니다.
에포크 수(Epochs): 전체 데이터셋을 몇 번 반복해서 학습할 것인지에 대한 설정입니다.
정규화 계수(Regularization Coefficient): 모델의 과적합을 방지하기 위해 사용하는 값입니다.
하이퍼파라미터는 학습 과정 전에 설정되며, 모델 성능에 큰 영향을 미치기 때문에 튜닝이 필요합니다.</p>
<ol start="3">
<li>파라미터 (Parameter)
파라미터는 모델이 학습 과정에서 조정하는 값으로, 모델의 가중치와 편향 등을 포함합니다.</li>
</ol>
<p>예시:
가중치(Weights): 입력 데이터에 곱해지는 값으로, 각 입력의 중요도를 나타냅니다.
편향(Bias): 활성화 함수에 추가되는 값으로, 모델의 예측에 일정한 오프셋을 추가합니다.
파라미터는 모델이 학습하는 과정에서 최적화됩니다. 모델의 학습 과정 중에 경사 하강법 등의 알고리즘을 사용하여 파라미터 값을 조정하여 손실 함수를 최소화합니다.</p>
<p>요약
미니 배치 경사 하강법은 전체 데이터셋을 작은 배치로 나누어 기울기를 계산하고 가중치를 업데이트하는 방법으로, 효율적인 학습과 안정적인 최적화를 제공합니다.
하이퍼파라미터는 모델 학습 전에 설정하는 값으로, 모델의 구조나 학습 설정에 영향을 미칩니다.
파라미터는 모델 학습 과정에서 조정되는 값으로, 모델의 가중치와 편향 등을 포함하며, 최적화 알고리즘을 통해 업데이트됩니다.</p>
<hr>
<ol start="7">
<li><p>Moment vs RMSProp차이
ChatGPT의 말:
ChatGPT
Momentum과 RMSProp은 모두 <strong>경사 하강법(Gradient Descent)</strong>을 향상시키기 위해 사용하는 최적화 기법입니다. 이들은 각각의 방식으로 기울기 기반의 최적화 과정에서 효율성을 개선합니다.</p>
</li>
<li><p>Momentum
Momentum은 경사 하강법의 기법으로, 이전 단계의 기울기를 고려하여 현재 단계의 업데이트를 조정합니다. 이를 통해 진동을 줄이고 더 빠른 수렴을 달성할 수 있습니다.</p>
</li>
</ol>
<p>작동 방식:
속도 개념 도입: 이전 기울기의 방향을 기억하여 현재의 업데이트에 반영합니다. 이로써 기울기의 방향이 일관되면 업데이트가 가속화됩니다.
수식:
𝑣
𝑡
=
𝛽
𝑣
𝑡
−
1
+
(
1
−
𝛽
)
∇
𝐿
(
𝜃
)
v 
t
​
 =βv 
t−1
​
 +(1−β)∇L(θ)
𝜃
=
𝜃
−
𝛼
𝑣
𝑡
θ=θ−αv 
t
​</p>
<p>여기서 
𝑣
𝑡
v 
t
​
 는 모멘텀 벡터, 
𝛽
β는 모멘텀의 감쇠 계수, 
∇
𝐿
(
𝜃
)
∇L(θ)는 손실 함수의 기울기, 
𝛼
α는 학습률입니다.
장점: 기울기의 방향이 일관되면, 빠르게 최적점에 접근할 수 있으며, 미세한 진동을 줄여서 더 안정적으로 수렴할 수 있습니다.
단점: 적절한 모멘텀 계수(
𝛽
β)를 선택해야 하며, 기울기가 급격히 변화할 때 문제가 발생할 수 있습니다.
2. RMSProp
RMSProp(Root Mean Square Propagation)은 Adagrad의 문제점을 개선하기 위해 개발된 기법입니다. 이 방법은 기울기의 크기에 따라 학습률을 조정하여, 학습률의 감소 문제를 완화합니다.</p>
<p>작동 방식:
기울기의 제곱의 지수 이동 평균을 계산하여 각 파라미터의 학습률을 조정합니다. 이로써 파라미터의 기울기가 클 때 학습률을 감소시키고, 기울기가 작을 때 학습률을 증가시킵니다.
수식:
𝐸
[
𝑔
2
]
𝑡
=
𝛽
𝐸
[
𝑔
2
]
𝑡
−
1
+
(
1
−
𝛽
)
𝑔
𝑡
2
E[g 
2
 ] 
t
​
 =βE[g 
2
 ] 
t−1
​
 +(1−β)g 
t
2
​</p>
<h1 id="𝜃">𝜃</h1>
<p>𝜃
−
𝛼
𝐸
[
𝑔
2
]
𝑡
+
𝜖
𝑔
𝑡
θ=θ− 
E[g 
2
 ] 
t
​
 +ϵ
​</p>
<p>α
​
 g 
t
​</p>
<p>여기서 
𝐸
[
𝑔
2
]
𝑡
E[g 
2
 ] 
t
​
 는 기울기의 제곱의 지수 이동 평균, 
𝛽
β는 감쇠 계수, 
𝑔
𝑡
g 
t
​
 는 현재 기울기, 
𝜖
ϵ는 안정성을 위한 작은 상수입니다.
장점: 각 파라미터의 기울기 크기에 따라 학습률을 조정하므로, 기울기가 크거나 작은 경우에도 안정적인 학습이 가능합니다. 특히 기울기 폭발 문제를 줄이는 데 효과적입니다.
단점: 하이퍼파라미터인 
𝛽
β와 
𝜖
ϵ을 적절히 설정해야 하며, 적절한 값이 아니라면 성능에 영향을 줄 수 있습니다.
요약
Momentum은 기울기의 이전 단계의 정보를 활용하여 현재 업데이트를 조정하고, 최적화 과정의 진동을 줄여줍니다. 기울기의 방향이 일관되면 학습 속도가 빨라지지만, 모멘텀 계수의 선택이 중요합니다.</p>
<p>RMSProp은 기울기의 제곱에 대한 지수 이동 평균을 사용하여 각 파라미터의 학습률을 조정합니다. 기울기가 큰 경우 학습률을 줄여주어 안정적인 학습을 돕습니다. 기울기의 크기에 따른 학습률 조정으로 기울기 폭발 문제를 완화할 수 있습니다.</p>
<p>각 기법은 모델 학습의 안정성과 속도를 개선하는 데 도움을 주며, 학습률 조정과 기울기 처리에 있어 서로 다른 접근 방식을 취합니다.</p>
<p><a href="https://chatgpt.com/c/66e16d6e-5524-800c-b016-d466eb25c3b9">https://chatgpt.com/c/66e16d6e-5524-800c-b016-d466eb25c3b9</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ KeyCloak 사용방법]]></title>
            <link>https://velog.io/@progect_study/KeyCloak-%EC%82%AC%EC%9A%A9%EB%B0%A9</link>
            <guid>https://velog.io/@progect_study/KeyCloak-%EC%82%AC%EC%9A%A9%EB%B0%A9</guid>
            <pubDate>Tue, 03 Sep 2024 05:57:50 GMT</pubDate>
            <description><![CDATA[<h1 id="키클록-세팅">키클록 세팅</h1>
<p><img src="https://velog.velcdn.com/images/progect_study/post/2a17e764-fdd1-4604-a315-0f0bec5d58db/image.png" alt="">
왼쪽위 상단에 create realm 클릭
<img src="https://velog.velcdn.com/images/progect_study/post/d357ec0b-15f5-473c-b7dd-168f64399fd5/image.png" alt="">
클라이언트를 생성 합니다.
마이크로 서비스 이기때문에 4번째는 꼭 체크해야 합니다</p>
<h1 id="요청보내기">요청보내기</h1>
<pre><code>http://localhost:8180/realms/real_estate/.well-known/openid-configuration</code></pre><p>으로 요청을 보냅니다.</p>
<pre><code>http://localhost:8180/realms/real_estate/protocol/openid-connect/token</code></pre><p>토큰을 요청합니다.</p>
<p><img src="https://velog.velcdn.com/images/progect_study/post/356e6008-47b6-443f-8e67-88164e6e81b5/image.png" alt=""></p>
<p>위와 같이 토큰을 발급 받습니다.
프론트엔드에서도 위같은방볍으로 토큰을 발급 받으면 따로auth api 설정은 하지않습니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Keycloak 실행방]]></title>
            <link>https://velog.io/@progect_study/Keycloak-%EC%8B%A4%ED%96%89%EB%B0%A9</link>
            <guid>https://velog.io/@progect_study/Keycloak-%EC%8B%A4%ED%96%89%EB%B0%A9</guid>
            <pubDate>Mon, 02 Sep 2024 19:32:47 GMT</pubDate>
            <description><![CDATA[<p>Keycloak을 Docker에서 실행하는 방법은 매우 간단합니다. 아래의 단계별 가이드를 따라 진행하시면 됩니다.</p>
<ol>
<li>Keycloak Docker 이미지 Pull
먼저 Keycloak 이미지를 Docker Hub 또는 Quay.io에서 가져와야 합니다. 명령어는 다음과 같습니다:</li>
</ol>
<p>bash
코드 복사
docker pull quay.io/keycloak/keycloak
이 명령어는 quay.io에서 Keycloak의 최신 이미지를 가져옵니다.</p>
<ol start="2">
<li>Keycloak 컨테이너 실행
Keycloak 컨테이너를 실행하려면 다음 명령어를 사용하세요:</li>
</ol>
<pre><code>bash
코드 복사
docker run -d --name keycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
</code></pre><p>여기서 사용된 옵션에 대해 설명드리겠습니다:</p>
<p>-d: 컨테이너를 백그라운드에서 실행합니다.
--name keycloak: 컨테이너 이름을 &quot;keycloak&quot;으로 지정합니다.
-p 8080:8080: 호스트의 포트 8080을 컨테이너의 포트 8080에 바인딩합니다.
-e KEYCLOAK_ADMIN=admin: 관리자 계정의 사용자 이름을 admin으로 설정합니다.
-e KEYCLOAK_ADMIN_PASSWORD=admin: 관리자 계정의 비밀번호를 admin으로 설정합니다.
이 명령어를 실행하면 Keycloak 서버가 시작되고, 웹 인터페이스에 접속할 수 있습니다.</p>
<ol start="3">
<li>Keycloak에 접속하기
컨테이너가 정상적으로 실행되면 웹 브라우저에서 다음 주소로 접속할 수 있습니다:</li>
</ol>
<p><a href="http://localhost:8080">http://localhost:8080</a></p>
<ol start="4">
<li>추가 설정
Keycloak을 실제 환경에서 사용하려면 데이터베이스 설정, HTTPS 적용, 볼륨 마운트 등을 추가로 설정해야 할 수 있습니다. 예를 들어, PostgreSQL 데이터베이스와 함께 사용하는 경우 다음과 같이 실행할 수 있습니다:<pre><code></code></pre></li>
</ol>
<p>bash
코드 복사
docker run -d --name keycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -e KC_DB=postgres -e KC_DB_URL=jdbc:postgresql://db:5432/keycloak -e KC_DB_USERNAME=keycloak -e KC_DB_PASSWORD=yourpassword quay.io/keycloak/keycloak</p>
<p>```
위의 예시는 PostgreSQL을 사용하여 Keycloak을 구성하는 방법입니다. db는 PostgreSQL 컨테이너의 이름이며, yourpassword를 실제 비밀번호로 바꿔 사용하시면 됩니다.</p>
<ol start="5">
<li>컨테이너 관리
컨테이너를 중지하거나 다시 시작하려면 다음 명령어를 사용하세요:</li>
</ol>
<p>bash
코드 복사</p>
<h1 id="컨테이너-중지">컨테이너 중지</h1>
<p>docker stop keycloak</p>
<h1 id="컨테이너-다시-시작">컨테이너 다시 시작</h1>
<p>docker start keycloak</p>
<h1 id="컨테이너-상태-확인">컨테이너 상태 확인</h1>
<p>docker ps -a
이 방법으로 Keycloak을 Docker 환경에서 쉽게 실행하고 관리할 수 있습니다. 추가적으로 궁금한 사항이 있으면 언제든지 문의해주세요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[햇깔리는부분 간단히 설명 ]]></title>
            <link>https://velog.io/@progect_study/%ED%96%87%EA%B9%94%EB%A6%AC%EB%8A%94%EB%B6%80%EB%B6%84-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%84%A4%EB%AA%85</link>
            <guid>https://velog.io/@progect_study/%ED%96%87%EA%B9%94%EB%A6%AC%EB%8A%94%EB%B6%80%EB%B6%84-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%84%A4%EB%AA%85</guid>
            <pubDate>Sun, 01 Sep 2024 21:24:04 GMT</pubDate>
            <description><![CDATA[<h1 id="내가-저기앱에서-가져올꺼야">내가 저기앱에서 가져올꺼야</h1>
<h2 id="같은앱단위에서-가져올거야">같은앱단위에서 가져올거야</h2>
<p><img src="https://velog.velcdn.com/images/progect_study/post/63b1fe4d-dc7d-4037-87e3-fa81eefb744e/image.png" alt=""></p>
<h2 id="컴포넌트에서-가져올거야">컴포넌트에서 가져올거야</h2>
<p><img src="https://velog.velcdn.com/images/progect_study/post/5c48ddfa-3332-4917-88ff-a42ebd060e17/image.png" alt="">
<img src="https://velog.velcdn.com/images/progect_study/post/ca6b2f36-f251-4f16-afaf-c0cb4fec3365/image.png" alt=""></p>
<hr>
<h1 id="이거써-내줄게">이거써 내줄게</h1>
<h2 id="컴포넌트에서-내줄때">컴포넌트에서 내줄때</h2>
<p><img src="https://velog.velcdn.com/images/progect_study/post/ff256235-b929-4d6d-9ca7-ad728e488b6a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MFA 를 공부하면서 사용했던 모든코드 정리]]></title>
            <link>https://velog.io/@progect_study/MFA-%EB%A5%BC-%EA%B3%B5%EB%B6%80%ED%95%98%EB%A9%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%96%88%EB%8D%98-%EB%AA%A8%EB%93%A0%EC%BD%94%EB%93%9C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@progect_study/MFA-%EB%A5%BC-%EA%B3%B5%EB%B6%80%ED%95%98%EB%A9%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%96%88%EB%8D%98-%EB%AA%A8%EB%93%A0%EC%BD%94%EB%93%9C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 01 Sep 2024 04:26:31 GMT</pubDate>
            <description><![CDATA[<h1 id="프로젝트-세팅">프로젝트 세팅</h1>
<h2 id="pnpm-세팅">pnpm 세팅</h2>
<pre><code> pnpm init
 corepack use pnpm@8.10.0</code></pre><h2 id="yaml-생성">yaml 생성</h2>
<p>pnpm-workspace.yaml 생성</p>
<pre><code>packages:
  - &quot;apps/*&quot;
  - &quot;packages/*&quot;</code></pre><h2 id="apps-폴더생성">apps 폴더생성</h2>
<p>mkdir apps</p>
<h2 id="mf-app-생성">mf-app 생성</h2>
<p> pnpm create mf-app</p>
<h2 id="생성후-인스톨">생성후 인스톨</h2>
<p>pnpm i</p>
<h2 id="터보생성">터보생성</h2>
<p>pnpm -w add turbo -D</p>
<p>turbo.json</p>
<pre><code>{
    &quot;$schema&quot;: &quot;https://turbo.build/schema.json&quot;,
    &quot;pipeline&quot;: {
      &quot;build&quot;: {
        &quot;dependsOn&quot;: [&quot;^build&quot;],
        &quot;outputs&quot;: [&quot;dist/**&quot;]
      },
      &quot;start:live&quot;: {
        &quot;cache&quot;: false,
        &quot;persistent&quot;: true
      },
      &quot;build:start&quot;: {
        &quot;cache&quot;: false,
        &quot;persistent&quot;: true
      }
    }
  }
</code></pre><hr>
<h2 id="packagejson-변경">package.json 변경</h2>
<pre><code>{
  &quot;name&quot;: &quot;@real-estate/monorepo&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
    &quot;scripts&quot;: {
      &quot;dev&quot;: &quot;turbo start:live&quot;,
      &quot;build&quot;: &quot;turbo build&quot;,
      &quot;serve&quot;: &quot;turbo build:start&quot;

  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;packageManager&quot;: &quot;pnpm@8.10.0+sha256.3c5d70d07b0c4849d7e07398b62bf48ca6619ca86f77981125eaab7f5ee82c4c&quot;,
  &quot;devDependencies&quot;: {
    &quot;turbo&quot;: &quot;^2.1.1&quot;
  }
}
</code></pre><hr>
<h1 id="ui-kit-만들기">ui-kit 만들기</h1>
<pre><code>mkdir packages
pnpm create vite ui-kit --template react-swc-ts
</code></pre><p>vite.config.ts</p>
<pre><code>import { defineConfig } from &quot;vite&quot;;
import react from &quot;@vitejs/plugin-react-swc&quot;;
import dts from &quot;vite-plugin-dts&quot;;

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), dts({ insertTypesEntry: true })],
  build: {
    outDir: &quot;./dist&quot;,
    lib: {
      entry: &quot;./src/index.ts&quot;,
      name: &quot;ui-kit&quot;,
      fileName: &quot;index&quot;,
    },
    rollupOptions: {
      external: [&quot;react&quot;, &quot;react-dom&quot;],
      output: {
        globals: {
          react: &quot;React&quot;,
          &quot;react-dom&quot;: &quot;ReactDOM&quot;,
        },
        assetFileNames: (assetInfo: any) =&gt; {  // 타입 강제 변환
          if (assetInfo.name === &quot;style.css&quot;) {
            return &quot;index.css&quot;;
          }
          return assetInfo.name;
        },
      } as any,  // 타입 강제 변환
    },
  },
});

</code></pre><h2 id="중요-바이트-연결방법">중요 바이트 연결방법</h2>
<p>루트에서
pnpm add vite-plugin-dts -D -w</p>
<p> pnpm --filter @real-estate/ui add vite-plugin-dts -D </p>
<hr>
<h2 id="의존성변경">의존성변경</h2>
<pre><code> &quot;dependencies&quot;: {
    &quot;react&quot;: &quot;^18.3.1&quot;,
    &quot;react-dom&quot;: &quot;^18.3.1&quot;
  },</code></pre><p>위파일을</p>
<pre><code>  &quot;peerDependencies&quot;: {
    &quot;react&quot;: &quot;^18.3.1&quot;,
    &quot;react-dom&quot;: &quot;^18.3.1&quot;
  },</code></pre><h2 id="빌드-하기">빌드 하기</h2>
<p>PS C:\Users\rje28\Downloads\career-up-step5\aa&gt; pnpm --filter @real-estate/ui-kit build</p>
<h2 id="패키지사용">패키지사용</h2>
<p>package.json 에서 아래를 추가</p>
<pre><code>&#39;&#39;&#39;
  &quot;exports&quot;: {
    &quot;.&quot;: {
      &quot;types&quot;: &quot;./dist/index.d.ts&quot;,
      &quot;require&quot;: &quot;./dist/index.umd.cjs&quot;,
      &quot;import&quot;: &quot;./dist/index.js&quot;
    },
    &quot;./index.css&quot;: &quot;./dist/index.css&quot;
  },  
  &quot;types&quot;: &quot;./dist/index.d.ts&quot;,
  &quot;main&quot;: &quot;./dist/index.umd.cjs&quot;,
&#39;&#39;&#39;</code></pre><hr>
<h1 id="만일에러가뜬다면">만일에러가뜬다면</h1>
<pre><code>{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;ES2020&quot;,
    &quot;useDefineForClassFields&quot;: true,
    &quot;lib&quot;: [&quot;ES2020&quot;, &quot;DOM&quot;, &quot;DOM.Iterable&quot;],
    &quot;module&quot;: &quot;ESNext&quot;,
    &quot;skipLibCheck&quot;: true,

    /* Bundler mode */
    &quot;moduleResolution&quot;: &quot;bundler&quot;,
    &quot;allowImportingTsExtensions&quot;: true,
    &quot;resolveJsonModule&quot;: true,
    &quot;isolatedModules&quot;: true,
    &quot;noEmit&quot;: true,
    &quot;jsx&quot;: &quot;react-jsx&quot;,

    /* Linting */
    &quot;strict&quot;: true,
    &quot;noUnusedLocals&quot;: true,
    &quot;noUnusedParameters&quot;: true,
    &quot;noFallthroughCasesInSwitch&quot;: true
  },
  &quot;include&quot;: [&quot;src&quot;],
  &quot;references&quot;: [{ &quot;path&quot;: &quot;./tsconfig.node.json&quot; }]
}
</code></pre><pre><code>{
  &quot;compilerOptions&quot;: {
    &quot;composite&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;module&quot;: &quot;ESNext&quot;,
    &quot;moduleResolution&quot;: &quot;bundler&quot;,
    &quot;allowSyntheticDefaultImports&quot;: true
  },
  &quot;include&quot;: [&quot;vite.config.ts&quot;]
}
</code></pre><p>다른쪽 app.shell 에서 사용하기</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Authentication Authorization]]></title>
            <link>https://velog.io/@progect_study/Authentication-Authorization</link>
            <guid>https://velog.io/@progect_study/Authentication-Authorization</guid>
            <pubDate>Mon, 26 Aug 2024 17:15:59 GMT</pubDate>
            <description><![CDATA[<p>인증(Authentication):</p>
<p>사용자의 신원을 확인하여 시스템 접근을 허용합니다.
권한 부여 전에 수행됩니다.
일반적으로 사용자의 로그인 정보가 필요합니다.
인증 실패 시 보통 401 오류 응답을 받습니다.
예를 들어, 은행 고객이나 직원이 앱에서 작업을 수행하려면 신원 확인이 필요합니다.
권한 부여(Authorization):</p>
<p>자원 접근을 위해 개인이나 사용자의 권한을 확인합니다.
항상 인증 후에 이루어집니다.
사용자의 권한이나 역할이 필요합니다.
권한 부여 실패 시 보통 403 오류 응답을 받습니다.
애플리케이션에 로그인한 후, 역할과 권한에 따라 수행할 수 있는 작업이 결정됩니다.</p>
<h1 id="권한-확인방법">권한 확인방법</h1>
<p>hasAuthority(): 단일 권한을 수락하며, 해당 엔드포인트는 구성된 단일 권한에 대해 검증됩니다. 동일한 권한을 가진 사용자만 엔드포인트를 호출할 수 있습니다.</p>
<p>hasAnyAuthority(): 여러 권한을 수락하며, 해당 엔드포인트는 구성된 여러 권한에 대해 검증됩니다. 구성된 권한 중 하나라도 가진 사용자만 엔드포인트를 호출할 수 있습니다.</p>
<p>access(): Spring Expression Language (SpEL)을 사용하여 위의 방법으로는 불가능한 권한 구성을 무제한으로 제공합니다. OR, AND와 같은 연산자를 access() 내부에서 사용할 수 있습니다.</p>
<pre><code>@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
    CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
    requestHandler.setCsrfRequestAttributeName(&quot;_csrf&quot;);

    http.securityContext().requireExplicitSave(false)
        .and().sessionManagement(session -&gt; session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
        .cors().configurationSource(new CorsConfigurationSource() { ... })
        .and().csrf(csrf -&gt; csrf.csrfTokenRequestHandler(requestHandler)
            .ignoringRequestMatchers(&quot;/contact&quot;, &quot;/register&quot;)
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
        .addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class)
        .authorizeHttpRequests()
            .requestMatchers(&quot;/myAccount&quot;).hasAuthority(&quot;VIEWACCOUNT&quot;)
            .requestMatchers(&quot;/myBalance&quot;).hasAnyAuthority(&quot;VIEWACCOUNT&quot;, &quot;VIEWBALANCE&quot;)
            .requestMatchers(&quot;/myLoans&quot;).hasAuthority(&quot;VIEWLOANS&quot;)
            .requestMatchers(&quot;/myCards&quot;).hasAuthority(&quot;VIEWCARDS&quot;)
            .requestMatchers(&quot;/user&quot;).authenticated()
            .requestMatchers(&quot;/notices&quot;, &quot;/contact&quot;, &quot;/register&quot;).permitAll()
        .and().formLogin()
        .and().httpBasic();

    return http.build();
}
</code></pre><hr>
<p>NSIDE SPRING SECURITY</p>
<p>Spring Security에서 역할 요구 사항은 다음과 같은 방법으로 구성할 수 있습니다.</p>
<p>hasRole(): 단일 역할 이름을 받아 해당 엔드포인트가 구성되며, 사용자는 지정된 단일 역할에 대해 검증됩니다. 동일한 역할이 구성된 사용자만 엔드포인트를 호출할 수 있습니다.</p>
<p>hasAnyRole(): 여러 역할을 받아 해당 엔드포인트가 구성되며, 사용자는 지정된 역할 중 하나에 대해 검증됩니다. 구성된 역할 중 하나를 가진 사용자만 엔드포인트를 호출할 수 있습니다.</p>
<p>access(): Spring Expression Language (SpEL)을 사용하여 위의 방법으로는 불가능한 역할 구성을 무제한으로 제공합니다. access() 메서드 내에서 OR, AND와 같은 연산자를 사용할 수 있습니다.</p>
<pre><code>@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
    CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
    requestHandler.setCsrfRequestAttributeName(&quot;_csrf&quot;);
    http.securityContext().requireExplicitSave(false)
        .and().sessionManagement(session -&gt; session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
        .cors().configurationSource(new CorsConfigurationSource() { ... })
        .and().csrf((csrf) -&gt; csrf.csrfTokenRequestHandler(requestHandler)
            .ignoringRequestMatchers(&quot;/contact&quot;, &quot;/register&quot;)
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
        .addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class)
        .authorizeHttpRequests()
            .requestMatchers(&quot;/myAccount&quot;).hasRole(&quot;USER&quot;)
            .requestMatchers(&quot;/myBalance&quot;).hasAnyRole(&quot;USER&quot;, &quot;ADMIN&quot;)
            .requestMatchers(&quot;/myLoans&quot;).hasRole(&quot;USER&quot;)
            .requestMatchers(&quot;/myCards&quot;).hasRole(&quot;USER&quot;)
            .requestMatchers(&quot;/user&quot;).authenticated()
            .requestMatchers(&quot;/notices&quot;, &quot;/contact&quot;, &quot;/register&quot;).permitAll()
        .and().formLogin()
        .and().httpBasic();
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[CORS와 CSRF에 대한 이해 및 차이점
]]></title>
            <link>https://velog.io/@progect_study/CORS%EC%99%80-CSRF%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4-%EB%B0%8F-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@progect_study/CORS%EC%99%80-CSRF%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4-%EB%B0%8F-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Mon, 26 Aug 2024 17:14:23 GMT</pubDate>
            <description><![CDATA[<p>CORS (Cross-Origin Resource Sharing)</p>
<ol>
<li><p>개요
CORS는 웹 애플리케이션이 다른 도메인에서 리소스를 요청할 때 발생하는 보안 메커니즘입니다. 기본적으로 웹 브라우저는 보안상의 이유로 다른 출처에서의 요청을 제한하지만, CORS를 사용하면 특정 조건을 만족하는 경우에 한해 이러한 제한을 해제할 수 있습니다.</p>
</li>
<li><p>작동 원리</p>
</li>
</ol>
<p>Origin: 웹 페이지의 출처는 스키마(HTTP/HTTPS), 도메인, 포트를 조합하여 정의됩니다. 동일한 출처에서만 리소스를 요청할 수 있는 규칙을 &#39;Same-Origin Policy&#39;라고 합니다.
Preflight Request: 복잡한 요청(예: PUT, DELETE, 또는 특정 헤더가 있는 요청)인 경우 브라우저는 먼저 OPTIONS 메서드를 사용하여 서버에 사전 요청을 보내 CORS 정책을 확인합니다.
Access-Control-Allow-Origin: 서버는 응답 헤더에 이 필드를 포함시켜 어느 출처에서 요청을 허용할지를 지정합니다.
3. 활용 CORS는 API 서버가 여러 도메인에서 접근할 수 있도록 할 때 유용하며, 올바르게 설정하지 않으면 보안 문제가 발생할 수 있습니다.</p>
<p>CSRF (Cross-Site Request Forgery)</p>
<ol>
<li><p>개요
CSRF는 악의적인 웹사이트가 사용자를 속여 그들이 의도하지 않은 요청을 다른 웹사이트로 전송하게 하는 공격입니다. 이 공격은 사용자가 이미 인증된 상태에서 발생하여, 공격자가 사용자의 권한을 악용해 요청을 수행하게 합니다.</p>
</li>
<li><p>작동 원리</p>
</li>
</ol>
<p>취약점 발생 조건: 사용자가 A 웹사이트에 로그인하여 세션 쿠키를 소지한 상태에서, B 악의적인 웹사이트에서 A 사이트로 요청을 보내는 링크를 클릭하면, 사용자는 모르게 A 사이트에 인증된 요청을 하게 됩니다.
공격 시나리오: 예를 들어, 사용자가 은행 사이트에 로그인한 상태에서 악성 사이트의 링크를 클릭하면 공격자가 사용자의 세션을 이용해 이체를 수행할 수 있습니다.
3. 방어 기법</p>
<p>CSRF 토큰 사용: 서버는 요청할 때마다 고유한 CSRF 토큰을 발급하고, 사용자가 요청을 보낼 때 이 토큰을 함께 제출하게 합니다. 서버는 이 토큰을 검증하여 요청의 정당성을 확인합니다.
SameSite 쿠키 설정: 쿠키에 SameSite 속성을 설정하여, 동일한 사이트에서 온 요청에서만 쿠키를 사용할 수 있도록 제한합니다.
CORS와 CSRF의 차이점
목적: CORS는 웹 애플리케이션이 다른 출처의 리소스에 접근할 때 발생하는 보안 문제를 해결하는 반면, CSRF는 악의적인 웹사이트가 사용자의 권한을 도용하는 공격을 방지하는 데 초점이 맞춰져 있습니다.
동작 방식: CORS는 서버의 설정을 통해 클라이언트의 요청을 허용할지 여부를 결정하는 메커니즘이고, CSRF는 사용자가 의도하지 않은 요청을 방지하기 위해 토큰이나 쿠키 속성을 사용하는 방법입니다.
위협 시나리오: CORS는 다른 출처의 API 호출과 관련된 위협을 다루고, CSRF는 사용자가 로그인된 상태에서 발생할 수 있는 의도치 않은 요청을 막습니다.
이 두 가지 개념을 잘 이해하고 적절하게 활용하면, 웹 애플리케이션의 보안을 크게 강화할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Authentication Provider: 왜 필요한가?
]]></title>
            <link>https://velog.io/@progect_study/Authentication-Provider-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%9C%EA%B0%80</link>
            <guid>https://velog.io/@progect_study/Authentication-Provider-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%9C%EA%B0%80</guid>
            <pubDate>Mon, 26 Aug 2024 17:14:09 GMT</pubDate>
            <description><![CDATA[<p>오늘날의 애플리케이션 보안에서 인증(Authentication)은 필수적인 요소입니다. 이를 효율적으로 처리하기 위해 Spring Security 프레임워크에서는 Authentication Provider라는 개념을 도입하고 있습니다. 이번 포스팅에서는 Authentication Provider가 무엇인지, 그리고 왜 필요한지에 대해 살펴보겠습니다.</p>
<p>Authentication Provider: 왜 필요한가?
Authentication Provider는 다양한 인증 방식을 지원하여 애플리케이션의 보안을 강화합니다. 이를 통해 개발자는 여러 종류의 인증 방법을 손쉽게 구현할 수 있습니다. 아래는 Spring Security에서 지원하는 주요 인증 요구 사항입니다:</p>
<p>사용자 이름과 비밀번호 인증 수락
사용자 이름과 비밀번호를 기반으로 사용자를 인증합니다. 이 방식은 가장 일반적인 인증 방법입니다.</p>
<p>OAuth2 인증 수락
외부 인증 서비스를 통해 인증을 처리합니다. 이 방법은 소셜 로그인이나 서드파티 인증을 통해 사용자 인증을 구현할 때 유용합니다.</p>
<p>OTP(일회용 비밀번호) 인증 수락
2단계 인증 또는 추가 보안 레이어로 사용되는 OTP 인증을 처리합니다.</p>
<p>이러한 요구 사항은 클라우드 아이콘으로 표현되며, 모두 Spring Security Framework로 연결됩니다.</p>
<p>Spring Security의 인증 구조
Spring Security에서는 인증 요청이 Spring Security Filters를 통해 들어와 ProviderManager로 전달됩니다. ProviderManager는 각 요청을 적절한 Authentication Providers에 전달하여 인증을 처리합니다. 이 구조는 다양한 인증 방식을 유연하게 지원할 수 있도록 설계되었습니다.</p>
<p>기본 구현과 커스텀 인증
Spring Security의 기본 구현은 UserDetailsService와 PasswordEncoder를 사용하여 사용자 세부 정보와 비밀번호를 검증합니다. 그러나 특정 애플리케이션 요구 사항에 맞는 커스텀 인증이 필요할 때는 AuthenticationProvider를 직접 구현하여 확장할 수 있습니다.</p>
<hr>
<p>블로그 제목: AuthenticationProvider 인터페이스에 대한 자세한 설명</p>
<p>본문:</p>
<p>Spring Security에서 중요한 구성 요소 중 하나인 AuthenticationProvider 인터페이스에 대해 살펴보겠습니다. 이 인터페이스는 커스텀 인증 로직을 구현할 수 있는 강력한 도구로, 다양한 인증 시나리오를 지원할 수 있습니다.</p>
<p>AuthenticationProvider 인터페이스의 메서드
AuthenticationProvider 인터페이스는 두 가지 주요 메서드를 포함하고 있으며, 각각의 역할은 다음과 같습니다:</p>
<ol>
<li>authenticate(Authentication authentication)
이 메서드는 인증 요청을 처리하는 핵심 메서드입니다. 인증 객체를 입력받아 처리한 후, 인증된 객체를 반환합니다. 이 안에 모든 사용자 정의 인증 로직을 구현할 수 있습니다. 예를 들어, 특정 조건을 검증하거나 외부 인증 서비스와 연동하는 로직을 이곳에 작성할 수 있습니다.</li>
</ol>
<p>java
코드 복사
public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
2. supports(Class&lt;?&gt; authentication)
이 메서드는 현재 AuthenticationProvider가 특정 유형의 인증 객체를 지원하는지 여부를 결정합니다. 이 메서드는 true 또는 false를 반환하며, 인증 로직이 처리할 수 있는 인증 객체의 유형을 명시합니다.</p>
<p>java
코드 복사
    boolean supports(Class&lt;?&gt; authentication);
}
추가 설명
이 두 메서드를 통해 개발자는 자신의 애플리케이션에 맞는 맞춤형 인증 로직을 손쉽게 구현할 수 있습니다. AuthenticationProvider 인터페이스는 Spring Security 내에서 다양한 인증 전략을 지원할 수 있는 유연한 구조를 제공합니다.</p>
<p>&quot;AuthenticationProviders 인터페이스 안에는&quot;
이 설명을 통해 Spring Security의 인증 메커니즘에 대한 이해를 높일 수 있습니다. 이를 통해 여러분의 애플리케이션에서 보다 강력하고 맞춤화된 인증 시스템을 구축할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security의 내부 로직]]></title>
            <link>https://velog.io/@progect_study/Spring-Security%EC%9D%98-%EB%82%B4%EB%B6%80-%EB%A1%9C%EC%A7%81</link>
            <guid>https://velog.io/@progect_study/Spring-Security%EC%9D%98-%EB%82%B4%EB%B6%80-%EB%A1%9C%EC%A7%81</guid>
            <pubDate>Mon, 26 Aug 2024 15:56:47 GMT</pubDate>
            <description><![CDATA[<p>Spring Security에서의 사용자 정의 및 관리: 심층 분석
Spring Security는 웹 애플리케이션의 보안을 강화하는 강력한 프레임워크입니다. 이 블로그 포스트에서는 Spring Security에서 사용자 정의와 관리를 중심으로, 데이터베이스와의 통합 및 사용자 인증 설정 방법을 심도 있게 설명합니다. 또한, Spring Security의 내부 로직을 참고하여 각 개념을 더욱 상세히 다루고자 합니다.</p>
<ol>
<li>UserDetailsService와 UserDetailsManager 인터페이스 심층 분석
UserDetailsService:</li>
</ol>
<p>역할 및 책임: UserDetailsService는 Spring Security에서 인증에 필요한 사용자 정보를 로드하는 핵심 인터페이스입니다. 기본적으로, 이 인터페이스는 loadUserByUsername(String username) 메서드를 통해 사용자의 이름을 기반으로 UserDetails 객체를 반환합니다.
내부 로직: loadUserByUsername() 메서드는 사용자 이름을 데이터베이스나 다른 데이터 저장소에서 조회하여, 해당 사용자의 비밀번호, 권한, 계정 상태(잠김, 비활성화 등)를 포함하는 UserDetails 객체를 생성합니다. 이 객체는 이후 인증 과정에서 사용됩니다.
java
코드 복사
public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
UserDetailsManager:</p>
<p>확장된 기능: UserDetailsManager는 UserDetailsService를 확장하여 사용자 생성, 업데이트, 삭제, 비밀번호 변경과 같은 추가적인 사용자 관리 기능을 제공합니다. Spring Security는 이 인터페이스를 사용해 다양한 저장소에서 사용자 데이터를 관리할 수 있도록 지원합니다.
구현 방법: 이 인터페이스는 사용자 계정을 프로그램적으로 관리할 수 있는 메서드를 제공하며, 내부적으로는 UserDetailsService와 유사한 구조를 가지지만, 추가적인 메서드가 포함되어 있습니다. 이를 통해 사용자 계정 관리의 유연성이 향상됩니다.
java
코드 복사
public interface UserDetailsManager extends UserDetailsService {
    void createUser(UserDetails user);
    void updateUser(UserDetails user);
    void deleteUser(String username);
    void changePassword(String oldPassword, String newPassword);
    boolean userExists(String username);
}
2. UserDetailsManager를 구현하는 클래스 심층 분석
InMemoryUserDetailsManager:</p>
<p>구현: InMemoryUserDetailsManager는 사용자 정보를 메모리에 저장하여 관리하는 구현체입니다. 이는 주로 테스트 환경이나 간단한 애플리케이션에서 사용됩니다. 모든 사용자 정보는 메모리에 저장되므로, 애플리케이션 종료 시 데이터가 사라집니다.
내부 로직: 메모리 내의 ConcurrentHashMap 또는 유사한 데이터 구조를 사용하여 사용자 데이터를 저장합니다. createUser() 메서드는 새로운 UserDetails 객체를 생성하고, 이를 맵에 추가합니다. loadUserByUsername() 메서드는 사용자 이름을 키로 하여 맵에서 데이터를 조회합니다.
java
코드 복사
public class InMemoryUserDetailsManager implements UserDetailsManager {
    private final Map&lt;String, UserDetails&gt; users = new ConcurrentHashMap&lt;&gt;();</p>
<pre><code>@Override
public void createUser(UserDetails user) {
    users.put(user.getUsername(), user);
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    UserDetails user = users.get(username);
    if (user == null) {
        throw new UsernameNotFoundException(&quot;User not found&quot;);
    }
    return user;
}

// 기타 메서드 생략</code></pre><p>}
JdbcUserDetailsManager:</p>
<p>구현: JdbcUserDetailsManager는 JDBC를 통해 데이터베이스에 사용자 정보를 저장하고 관리합니다. 데이터베이스에 저장된 사용자 정보를 기반으로 인증을 처리하며, 기본 제공되는 SQL 쿼리를 사용하거나 커스텀 쿼리를 정의할 수 있습니다.
내부 로직: 이 클래스는 JdbcTemplate을 사용하여 데이터베이스와 상호작용합니다. loadUserByUsername() 메서드는 기본적으로 SQL 쿼리를 사용하여 사용자 정보를 조회하고, 조회된 데이터를 기반으로 UserDetails 객체를 반환합니다. 이 과정에서 비밀번호는 PasswordEncoder를 통해 인코딩됩니다.
java
코드 복사
public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager {
    private String usersByUsernameQuery = &quot;select username,password,enabled from users where username = ?&quot;;
    private String authoritiesByUsernameQuery = &quot;select username,authority from authorities where username = ?&quot;;</p>
<pre><code>@Override
public UserDetails loadUserByUsername(String username) {
    List&lt;UserDetails&gt; users = getJdbcTemplate().query(usersByUsernameQuery, new String[]{username}, new UserRowMapper());
    // 기타 처리 로직 생략
    return users.get(0);
}

// 기타 메서드 생략</code></pre><p>}
LdapUserDetailsManager:</p>
<p>구현: LdapUserDetailsManager는 LDAP를 통해 사용자 정보를 관리합니다. 대규모 조직에서 디렉터리 서비스를 통해 사용자 정보를 중앙 집중식으로 관리하는 데 적합합니다.
내부 로직: LDAP 서버와 상호작용하기 위해 스프링의 LdapTemplate을 사용하며, 사용자 인증 및 권한 부여를 위해 LDAP 쿼리를 실행합니다.
java
코드 복사
public class LdapUserDetailsManager implements UserDetailsManager {
    private final LdapTemplate ldapTemplate;</p>
<pre><code>public LdapUserDetailsManager(LdapTemplate ldapTemplate) {
    this.ldapTemplate = ldapTemplate;
}

@Override
public UserDetails loadUserByUsername(String username) {
    // LDAP 쿼리 및 사용자 로드 로직 생략
}

// 기타 메서드 생략</code></pre><p>}
3. 클라우드 내 MySQL 데이터베이스 생성
클라우드 환경에서 MySQL 설정:</p>
<p>클라우드 제공자: AWS RDS, Google Cloud SQL, Azure Database for MySQL 등 클라우드 서비스에서 MySQL 데이터베이스 인스턴스를 생성하는 방법을 다룹니다.
데이터베이스 설정: 데이터베이스 생성 후, 사용자 계정과 권한을 설정합니다. 이때 Spring Security와 통합하기 위해 사용자 테이블과 권한 테이블을 사전에 정의해야 합니다.
연결 설정: Spring Boot 애플리케이션에서 application.properties 또는 application.yml 파일을 통해 데이터베이스 연결 정보를 설정합니다.
yaml
코드 복사
spring:
  datasource:
    url: jdbc:mysql://<your-database-url>:3306/<your-database-name>
    username: <your-username>
    password: <your-password>
    driver-class-name: com.mysql.cj.jdbc.Driver
4. JdbcUserDetailsManager에 따른 데이터베이스 연결과 데이터베이스 내 유저 생성
Spring Security와 MySQL 통합:</p>
<p>설정 과정: JdbcUserDetailsManager를 사용하여 Spring Security와 MySQL 데이터베이스를 통합합니다. 데이터베이스 테이블을 정의하고, Spring Security가 이 테이블을 기반으로 인증을 처리하도록 설정합니다.
유저 생성 및 관리: 사용자를 데이터베이스에 직접 생성하거나, 애플리케이션 코드에서 JdbcUserDetailsManager를 통해 관리할 수 있습니다. 사용자 생성 시 PasswordEncoder를 사용하여 비밀번호를 안전하게 저장합니다.
java
코드 복사
@Autowired
JdbcUserDetailsManager jdbcUserDetailsManager;</p>
<p>public void createUser() {
    UserDetails user = User.withUsername(&quot;username&quot;)
                           .password(passwordEncoder.encode(&quot;password&quot;))
                           .roles(&quot;USER&quot;)
                           .build();
    jdbcUserDetailsManager.createUser(user);
}
5. JdbcUserDetailsManager를 사용한 인증
데이터베이스 기반 인증:</p>
<p>인증 과정: JdbcUserDetailsManager는 UserDetailsService와 UserDetailsManager를 구현하여, 데이터베이스에서 사용자를 조회하고 인증합니다. 사용자가 로그인할 때, UsernamePasswordAuthenticationToken이 생성되며, 이를 통해 사용자 정보가 loadUserByUsername() 메서드를 통해 조회됩니다.
비밀번호 검증: 조회된 사용자 정보는 DaoAuthenticationProvider에 의해 처리되며, 이 과정에서 PasswordEncoder를 사용해 사용자가 입력한 비밀번호와 데이터베이스에 저장된 비밀번호를 비교합니다.
java
코드 복사
@Bean
public AuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setUserDetailsService(jdbcUserDetailsManager);
    provider.setPasswordEncoder(passwordEncoder());
    return provider;
}
6. 인증을 위한 사용자 정의 테이블 생성
커스텀 테이블 설계:</p>
<p>기본 테이블: Spring Security는 기본적으로 users와 authorities 테이블을 사용합니다. 하지만 사용자 정의 테이블을 사용하여, 보다 복잡한 요구 사항을 충족할 수 있습니다.
테이블 생성 SQL 예제: 커스텀 테이블 스키마를 설계하고 SQL 쿼리를 사용해 데이터베이스에 테이블을 생성합니다. 이때, 필수적인 컬럼 외에 사용자 프로파일 정보나 감사 로그와 같은 추가 컬럼을 포함할 수 있습니다.
sql
코드 복사
CREATE TABLE custom_users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(100) NOT NULL,
    enabled BOOLEAN NOT NULL,
    account_non_expired BOOLEAN NOT NULL DEFAULT TRUE,
    account_non_locked BOOLEAN NOT NULL DEFAULT TRUE,
    credentials_non_expired BOOLEAN NOT NULL DEFAULT TRUE
);</p>
<p>CREATE TABLE custom_authorities (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    authority VARCHAR(50) NOT NULL,
    FOREIGN KEY (user_id) REFERENCES custom_users(id)
);
7. 새로운 테이블을 위한 JPA Entity와 리포지토리 클래스 생성
JPA Entity 생성:</p>
<p>엔티티 클래스 정의: JPA 엔티티 클래스는 데이터베이스 테이블과 매핑되며, Spring Data JPA를 사용해 데이터베이스와 상호작용합니다. 사용자 정의 테이블에 맞게 엔티티를 정의하고, 이를 통해 Spring Security가 사용자 정보를 로드할 수 있습니다.
java
코드 복사
@Entity
@Table(name = &quot;custom_users&quot;)
public class CustomUser {</p>
<pre><code>@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String username;
private String password;
private boolean enabled;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;

// Getters and Setters</code></pre><p>}
Repository 클래스 정의:</p>
<p>사용자 정의 리포지토리: CrudRepository 또는 JpaRepository를 확장하여 사용자 정보를 데이터베이스에서 조회하는 메서드를 정의합니다. 예를 들어, 사용자 이름으로 사용자를 찾는 메서드를 정의할 수 있습니다.
java
코드 복사
public interface CustomUserRepository extends JpaRepository&lt;CustomUser, Long&gt; {
    Optional<CustomUser> findByUsername(String username);
}
8. 맞춤형 UserDetailsService 구현
커스텀 UserDetailsService:</p>
<p>구현: UserDetailsService 인터페이스를 구현하여, 데이터베이스나 다른 저장소에서 사용자 정보를 로드하는 커스텀 로직을 정의합니다. 이 과정에서 JPA 리포지토리를 활용하여 사용자 데이터를 조회하고, 이를 UserDetails 객체로 변환합니다.
java
코드 복사
@Service
public class CustomUserDetailsService implements UserDetailsService {</p>
<pre><code>@Autowired
private CustomUserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    CustomUser user = userRepository.findByUsername(username)
            .orElseThrow(() -&gt; new UsernameNotFoundException(&quot;User not found&quot;));

    return User.withUsername(user.getUsername())
               .password(user.getPassword())
               .accountExpired(!user.isAccountNonExpired())
               .accountLocked(!user.isAccountNonLocked())
               .credentialsExpired(!user.isCredentialsNonExpired())
               .disabled(!user.isEnabled())
               .authorities(new ArrayList&lt;&gt;()) // 실제 권한 로직 추가 필요
               .build();
}</code></pre><p>}
유연한 사용자 로드:</p>
<p>이점: 사용자 정의 UserDetailsService를 구현함으로써, 비즈니스 요구 사항에 맞게 사용자 데이터를 로드하고 처리할 수 있습니다. 예를 들어, LDAP, 외부 API, 파일 시스템 등 다양한 소스에서 데이터를 가져올 수 있습니다.
9. 새로운 유저 등록을 허용하는 새 REST API 구축
REST API 구축:</p>
<p>API 엔드포인트 정의: Spring MVC를 사용하여 새로운 사용자를 등록할 수 있는 RESTful API를 만듭니다. 사용자 등록 시, 입력된 데이터의 유효성을 검증하고, 등록된 사용자가 데이터베이스에 안전하게 저장될 수 있도록 합니다.
Spring Security 연동: API 요청을 처리할 때, Spring Security를 통해 인증 및 권한 부여를 적용하여, 적절한 사용자만이 새로운 유저를 등록할 수 있도록 합니다.
java
코드 복사
@RestController
@RequestMapping(&quot;/api/users&quot;)
public class UserController {</p>
<pre><code>@Autowired
private CustomUserDetailsService userDetailsService;

@Autowired
private PasswordEncoder passwordEncoder;

@PostMapping(&quot;/register&quot;)
public ResponseEntity&lt;?&gt; registerUser(@RequestBody UserDto userDto) {
    CustomUser user = new CustomUser();
    user.setUsername(userDto.getUsername());
    user.setPassword(passwordEncoder.encode(userDto.getPassword()));
    user.setEnabled(true);
    user.setAccountNonExpired(true);
    user.setAccountNonLocked(true);
    user.setCredentialsNonExpired(true);

    userRepository.save(user);

    return ResponseEntity.ok(&quot;User registered successfully&quot;);
}</code></pre><p>}
비밀번호 암호화:</p>
<p>비밀번호 보호: 사용자가 등록할 때, 비밀번호는 반드시 PasswordEncoder를 통해 암호화한 후 저장해야 합니다. 이는 데이터베이스에 평문 비밀번호를 저장하는 것을 방지하며, 애플리케이션 보안을 강화합니다.
마무리
이 포스트에서는 Spring Security를 활용한 사용자 관리와 인증을 심층적으로 분석했습니다. Spring Security의 다양한 구성 요소와 내부 로직을 이해함으로써, 애플리케이션의 보안을 보다 강화할 수 있습니다. 이 지식을 바탕으로 커스터마이징하여, 더 안전하고 유연한 보안 솔루션을 구현해 보세요.</p>
<p>이 블로그 포스트가 Spring Security에 대한 이해를 돕고, 실무에서 활용할 수 있는 유용한 지침이 되기를 바랍니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 시큐리티의 필터 및 내부 인증 저장 흐름]]></title>
            <link>https://velog.io/@progect_study/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0%EC%9D%98-%ED%95%84%ED%84%B0-%EB%B0%8F-%EB%82%B4%EB%B6%80-%EC%9D%B8%EC%A6%9D-%EC%A0%80%EC%9E%A5-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@progect_study/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0%EC%9D%98-%ED%95%84%ED%84%B0-%EB%B0%8F-%EB%82%B4%EB%B6%80-%EC%9D%B8%EC%A6%9D-%EC%A0%80%EC%9E%A5-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Mon, 26 Aug 2024 15:56:23 GMT</pubDate>
            <description><![CDATA[<p>스프링 시큐리티(Spring Security)는 웹 애플리케이션의 보안을 책임지는 강력한 프레임워크로, 다양한 보안 필터를 통해 인증(Authentication)과 인가(Authorization)을 처리합니다. 아래에서는 스프링 시큐리티의 기본적인 인증 흐름과 필터들, 그리고 내부에서 인증 정보를 저장하는 과정을 디테일하게 설명하겠습니다.</p>
<ol>
<li>스프링 시큐리티의 필터 체인
스프링 시큐리티는 FilterChainProxy를 통해 다수의 보안 필터를 관리합니다. 이 필터들은 사용자 요청을 가로채어 인증 및 인가 과정을 거친 후, 요청을 처리하거나 거부합니다. 주요 필터들은 다음과 같습니다:</li>
</ol>
<p>AuthorizationFilter (인가 필터): URL에 대한 접근 제한을 관리하는 필터입니다. 이 필터는 사용자가 요청한 URL에 대해 해당 사용자가 적절한 권한을 가지고 있는지 확인합니다. 사용자가 권한이 없으면, 접근을 거부합니다.</p>
<p>DefaultLoginPageGeneratingFilter: 디폴트 로그인 페이지를 생성하는 필터입니다. 만약 애플리케이션에서 사용자 정의 로그인 페이지를 제공하지 않는다면, 스프링 시큐리티는 이 필터를 통해 기본 로그인 페이지를 자동으로 생성합니다.</p>
<p>UsernamePasswordAuthenticationFilter: 사용자가 로그인 폼을 통해 제출한 사용자명과 비밀번호를 처리하는 필터입니다. 이 필터는 사용자 자격 증명(Username and Password)을 받아 UsernamePasswordAuthenticationToken을 생성합니다.</p>
<ol start="2">
<li>토큰 생성 및 인증 관리
스프링 시큐리티에서 인증은 주로 토큰 기반으로 이루어집니다. 주요 과정은 다음과 같습니다:</li>
</ol>
<p>UsernamePasswordAuthenticationToken: 사용자가 로그인 시 입력한 사용자명과 비밀번호를 포함하는 토큰입니다. 이 토큰은 Authentication 인터페이스를 구현하며, 스프링 시큐리티 내부에서 인증의 기본 단위로 사용됩니다.</p>
<p>AbstractAuthenticationToken: UsernamePasswordAuthenticationToken의 상위 클래스입니다. 이 클래스는 인증 관련 정보를 캡슐화하고 있으며, 인증이 완료되면 사용자의 권한 정보가 포함됩니다.</p>
<p>Authentication: 스프링 시큐리티에서 인증을 나타내는 인터페이스입니다. 인증이 완료된 후, 이 인터페이스를 구현한 객체가 SecurityContext에 저장됩니다.</p>
<ol start="3">
<li>AuthenticationManager와 ProviderManager
스프링 시큐리티의 인증 흐름에서 핵심 역할을 하는 것이 AuthenticationManager입니다. 이 매니저는 인증 요청을 처리하며, 주로 ProviderManager를 통해 실제 인증이 이루어집니다.</li>
</ol>
<p>ProviderManager: 여러 AuthenticationProvider를 관리하며, 인증 요청이 들어오면 이들 중 하나에 인증을 위임합니다. ProviderManager는 for문을 사용하여 각각의 AuthenticationProvider에 인증을 시도하며, 인증이 성공하면 Authentication 객체를 반환합니다.
4. UserDetailsService와 PasswordEncoder
스프링 시큐리티에서 사용자 정보를 관리하고 비밀번호를 처리하는 핵심 컴포넌트는 UserDetailsService와 PasswordEncoder입니다.</p>
<p>InMemoryUserDetailsManager: 메모리 내에서 사용자 정보를 관리하는 구현체로, 테스트나 작은 규모의 애플리케이션에 적합합니다. UserDetailsService를 구현하며, 사용자 이름으로 사용자를 로드하고, 해당 사용자의 세부 정보를 반환합니다.</p>
<p>PasswordEncoder: 비밀번호를 암호화하고 비교하는 데 사용되는 인터페이스입니다. NoOpPasswordEncoder는 비밀번호를 평문으로 저장하는 간단한 구현체입니다. 실제 운영 환경에서는 BCryptPasswordEncoder와 같은 강력한 인코더를 사용하는 것이 일반적입니다.</p>
<p>DaoAuthenticationProvider: AuthenticationProvider의 한 구현체로, UserDetailsService를 사용하여 사용자 정보를 로드하고, PasswordEncoder를 통해 비밀번호를 검증합니다. 인증이 성공하면 Authentication 객체를 반환합니다.</p>
<ol start="5">
<li>전체 흐름 요약 및 다이어그램
스프링 시큐리티의 기본 인증 흐름을 요약하면 다음과 같습니다:</li>
</ol>
<p>사용자 요청: 사용자가 보호된 리소스에 접근하려고 시도합니다.
필터 체인: AuthorizationFilter와 DefaultLoginPageGeneratingFilter가 요청을 가로채고, 인증 여부를 확인합니다.
자격 증명 추출: UsernamePasswordAuthenticationFilter가 로그인 폼에서 사용자명과 비밀번호를 추출하여 UsernamePasswordAuthenticationToken을 생성합니다.
AuthenticationManager: ProviderManager가 인증 요청을 받아, DaoAuthenticationProvider를 통해 실제 인증을 시도합니다.
UserDetailsService와 PasswordEncoder: DaoAuthenticationProvider가 InMemoryUserDetailsManager를 통해 사용자 정보를 로드하고, PasswordEncoder를 통해 비밀번호를 검증합니다.
인증 성공: 인증이 성공하면 Authentication 객체가 생성되어 SecurityContext에 저장됩니다.
응답: 인증이 완료되면, 요청된 리소스에 접근할 수 있도록 응답이 반환됩니다.
이 흐름을 다이어그램으로 나타내면 다음과 같습니다:</p>
<p>Request →
Filters (AuthorizationFilter, DefaultLoginPageGeneratingFilter) →
Token (UsernamePasswordAuthenticationToken) →
Authentication Manager (ProviderManager) →
Provider (DaoAuthenticationProvider) →
User Details Service (InMemoryUserDetailsManager) →
Validation (PasswordEncoder) →
Authentication Result →
Response
스프링 시큐리티 구성 방법 (Lambda DSL)
Spring Security 6.1 이후, Spring Boot 3.1.0에서는 보안 구성을 더 간결하게 하기 위해 람다 DSL(Lambda DSL) 스타일을 권장합니다. 이 스타일은 기존 방식에 비해 코드 가독성을 높이고, 불필요한 중복을 줄이는 장점이 있습니다.</p>
<p>예제: 람다 DSL을 사용한 보안 설정
기존 방식:</p>
<p>java
코드 복사
http
    .authorizeRequests()
        .anyRequest().authenticated()
        .and()
    .formLogin()
        .loginPage(&quot;/login&quot;)
        .permitAll();
람다 DSL 적용:</p>
<p>java
코드 복사
http {
    authorizeHttpRequests {
        authorize(anyRequest, authenticated)
    }
    formLogin {
        loginPage = &quot;/login&quot;
        permitAll()
    }
}
람다 DSL을 적용하면, 코드는 더 읽기 쉽게 정돈되며, .and()와 같은 연결 메소드를 생략할 수 있습니다. 이로 인해 보안 설정을 더 간결하게 작성할 수 있습니다.</p>
<p>이 설명을 통해 스프링 시큐리티의 필터 체인, 인증 흐름, 주요 컴포넌트 및 새로운 람다 DSL 스타일에 대한 이해를 높일 수 있습니다. 스프링 시큐리티를 사용하여 웹 애플리케이션의 보안을 효과적으로 관리하고 설정할 수 있을 것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 시큐리티 내부 흐름에 대한 상세 설명]]></title>
            <link>https://velog.io/@progect_study/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EB%82%B4%EB%B6%80-%ED%9D%90%EB%A6%84%EC%97%90-%EB%8C%80%ED%95%9C-%EC%83%81%EC%84%B8-%EC%84%A4%EB%AA%85</link>
            <guid>https://velog.io/@progect_study/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EB%82%B4%EB%B6%80-%ED%9D%90%EB%A6%84%EC%97%90-%EB%8C%80%ED%95%9C-%EC%83%81%EC%84%B8-%EC%84%A4%EB%AA%85</guid>
            <pubDate>Mon, 26 Aug 2024 15:40:56 GMT</pubDate>
            <description><![CDATA[<p>스프링 시큐리티(Spring Security)는 웹 애플리케이션에서 인증(Authentication)과 인가(Authorization)를 처리하는 강력한 보안 프레임워크입니다. 사용자의 요청이 들어왔을 때 이 요청을 어떻게 처리하는지, 그리고 주요 컴포넌트들이 어떤 역할을 하는지 자세히 알아보겠습니다.</p>
<ol>
<li><p>사용자 요청 (Request)
사용자가 웹 애플리케이션에 접근할 때, 그 요청은 HTTP 프로토콜을 통해 서버로 전달됩니다. 이때 사용자는 보호된 리소스에 접근할 수 있으며, 이 경우 요청은 인증 및 인가 과정을 거쳐야 합니다.</p>
</li>
<li><p>필터 체인 (FilterChainProxy)
스프링 시큐리티의 핵심은 FilterChainProxy입니다. 이 객체는 여러 보안 필터(Security Filters)로 구성된 체인으로, 각각의 필터는 특정 보안 작업을 담당합니다.</p>
</li>
</ol>
<p>주요 필터:
SecurityContextPersistenceFilter: 요청이 시작될 때 SecurityContext를 가져오고, 요청이 끝날 때 변경된 내용을 저장합니다. SecurityContext는 현재 인증된 사용자에 대한 정보를 포함하고 있습니다.</p>
<p>UsernamePasswordAuthenticationFilter: 사용자가 로그인 폼을 통해 제출한 사용자명과 비밀번호를 처리합니다. 기본적으로 스프링 시큐리티의 폼 로그인을 담당합니다.</p>
<p>BasicAuthenticationFilter: HTTP 기본 인증(Basic Authentication)을 처리하는 필터입니다. 이 필터는 HTTP 요청 헤더에 포함된 사용자 이름과 비밀번호를 해석하여 인증을 시도합니다.</p>
<p>AuthorizationFilter: 인증된 사용자가 요청한 리소스에 접근할 수 있는 권한이 있는지를 확인하는 필터입니다.</p>
<ol start="3">
<li><p>SecurityContext
SecurityContext는 현재 인증된 사용자의 보안 정보를 저장하는 컨텍스트입니다. SecurityContextHolder에 저장되며, 애플리케이션 전반에서 참조될 수 있습니다. 인증된 사용자의 정보는 여기에서 관리되며, 필터 체인이 진행되면서 참조됩니다.</p>
</li>
<li><p>AuthenticationManager
AuthenticationManager는 인증을 실제로 수행하는 주체입니다. UsernamePasswordAuthenticationFilter가 사용자 인증을 시도하면, 이 매니저가 AuthenticationProvider에게 인증을 위임합니다.</p>
</li>
<li><p>AuthenticationProvider
AuthenticationProvider는 실제 인증 작업을 수행하는 컴포넌트입니다. 여러 종류의 AuthenticationProvider가 있을 수 있으며, 그 중 대표적인 것이 DaoAuthenticationProvider입니다. DaoAuthenticationProvider는 데이터베이스에서 사용자 정보를 조회하여 인증을 수행합니다.</p>
</li>
<li><p>UserDetailsService
UserDetailsService는 AuthenticationProvider가 사용자 정보를 로드하는 데 사용하는 서비스입니다. 이 서비스는 주로 데이터베이스에서 사용자의 정보와 권한을 조회하여 UserDetails 객체로 반환합니다.</p>
</li>
<li><p>UserDetails
UserDetails는 UserDetailsService가 반환하는 객체로, 사용자 이름, 비밀번호, 권한 등을 포함합니다. AuthenticationProvider는 이 객체를 사용하여 인증을 수행합니다.</p>
</li>
<li><p>인증(Authentication)
AuthenticationProvider는 사용자의 자격 증명(예: 사용자 이름과 비밀번호)을 검증한 후, 인증이 성공하면 Authentication 객체를 반환합니다. 이 객체는 사용자의 인증 정보를 포함하며, SecurityContext에 저장됩니다.</p>
</li>
<li><p>인가(Authorization)
인증이 성공한 후, 사용자가 요청한 자원에 접근할 수 있는 권한이 있는지 확인하는 과정이 인가입니다. 이 과정은 AccessDecisionManager에 의해 수행되며, 사용자가 가지고 있는 권한(GrantedAuthority)에 따라 접근 권한이 결정됩니다.</p>
</li>
<li><p>응답(Response)
모든 인증 및 인가 과정이 성공적으로 완료되면, 사용자가 요청한 리소스에 대한 접근이 허용되고, 서버는 해당 리소스와 함께 응답을 반환합니다. 만약 인증이나 인가 과정에서 실패하면, 서버는 401(Unauthorized) 또는 403(Forbidden) 상태 코드와 함께 적절한 오류 페이지로 리다이렉트합니다.</p>
</li>
</ol>
<h1 id="스프링-시큐리티-주요-메소드-및-사용법">스프링 시큐리티 주요 메소드 및 사용법</h1>
<p>스프링 시큐리티에서는 몇 가지 중요한 메소드를 제공하여 보안을 쉽게 설정할 수 있습니다. 이 메소드들을 사용하여 접근 제어를 간단하게 구성할 수 있습니다.</p>
<ol>
<li><p>denyAll()
설명: 모든 요청에 대해 접근을 거부합니다.
사용 예제:
java
코드 복사
http
 .authorizeHttpRequests(authorize -&gt; authorize</p>
<pre><code> .anyRequest().denyAll()</code></pre><p> );</p>
</li>
<li><p>permitAll()
설명: 모든 요청에 대해 접근을 허용합니다.
사용 예제:
java
코드 복사
http
 .authorizeHttpRequests(authorize -&gt; authorize</p>
<pre><code> .anyRequest().permitAll()</code></pre><p> );
InMemoryUserDetailsManager와 PasswordEncoder</p>
</li>
<li><p>InMemoryUserDetailsManager
설명: 메모리에 사용자 정보를 저장하고 관리하는 간단한 사용자 관리 서비스입니다. 테스트나 간단한 애플리케이션에서 자주 사용됩니다.
사용 예제:
java
코드 복사
@Bean
public UserDetailsService userDetailsService() {
 UserDetails user = User.builder()</p>
<pre><code> .username(&quot;user&quot;)
 .password(passwordEncoder().encode(&quot;password&quot;))
 .roles(&quot;USER&quot;)
 .build();</code></pre><p> return new InMemoryUserDetailsManager(user);
}</p>
</li>
<li><p>PasswordEncoder
설명: 비밀번호를 암호화하는 데 사용되는 인터페이스입니다. 일반적으로 BCryptPasswordEncoder를 사용하여 비밀번호를 안전하게 저장합니다.
사용 예제:
java
코드 복사
@Bean
public PasswordEncoder passwordEncoder() {
 return new BCryptPasswordEncoder();
}</p>
</li>
<li><p>DaoAuthenticationProvider
설명: AuthenticationProvider의 대표적인 구현체로, 데이터베이스에서 사용자 정보를 조회하여 인증을 수행합니다. UserDetailsService를 통해 사용자 정보를 로드하고, PasswordEncoder를 사용하여 비밀번호를 검증합니다.
사용 예제:
java
코드 복사
@Bean
public DaoAuthenticationProvider authenticationProvider() {
 DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
 authProvider.setUserDetailsService(userDetailsService());
 authProvider.setPasswordEncoder(passwordEncoder());
 return authProvider;
}
위와 같은 구조와 메소드를 활용하면, 스프링 시큐리티에서 인증과 인가를 유연하게 설정할 수 있으며, 보안이 필요한 웹 애플리케이션에서 강력한 보호 기능을 구현할 수 있습니다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 시큐리티]]></title>
            <link>https://velog.io/@progect_study/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0</link>
            <guid>https://velog.io/@progect_study/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0</guid>
            <pubDate>Mon, 26 Aug 2024 11:23:13 GMT</pubDate>
            <description><![CDATA[<p>Spring Security 기본 설정 및 내부 흐름 정리
Spring Security를 사용하여 애플리케이션의 보안을 설정하는 방법과 내부적인 인증 및 인가 과정을 간략히 정리해 보았습니다. 이 글은 Spring Boot 3.x와 Spring Security 6.x 버전을 기준으로 작성되었습니다.</p>
<ol>
<li>스프링 시큐리티 의존성 추가
먼저, build.gradle 파일에 스프링 시큐리티 관련 의존성을 추가합니다.</li>
</ol>
<p>groovy
코드 복사
implementation &#39;org.springframework.boot:spring-boot-starter-security&#39;
2. 기본 보안 설정
Spring Security 3.0 이상에서는 SecurityFilterChain 빈을 사용하여 보안 구성을 수행합니다. 예시 코드는 다음과 같습니다.</p>
<p>java
코드 복사
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;</p>
<p>@Configuration
public class SecurityConfig {</p>
<pre><code>@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(authorize -&gt; authorize
            .requestMatchers(&quot;/&quot;, &quot;/home&quot;).permitAll()
            .anyRequest().authenticated()
        )
        .formLogin(form -&gt; form
            .loginPage(&quot;/login&quot;)
            .permitAll()
        )
        .logout(logout -&gt; logout
            .permitAll()
        );
    return http.build();
}

@Bean
public UserDetailsService userDetailsService() {
    UserDetails user = User.builder()
        .username(&quot;user&quot;)
        .password(passwordEncoder().encode(&quot;password&quot;))
        .roles(&quot;USER&quot;)
        .build();

    return new InMemoryUserDetailsManager(user);
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}</code></pre><p>}
3. 사용자 정의 로그인 페이지
사용자 정의 로그인 페이지를 설정하기 위해서는 다음과 같은 컨트롤러와 HTML 파일을 준비해야 합니다.</p>
<p>LoginController.java
java
코드 복사
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;</p>
<p>@Controller
public class LoginController {</p>
<pre><code>@GetMapping(&quot;/login&quot;)
public String login() {
    return &quot;login&quot;;
}</code></pre><p>}
login.html
html
코드 복사
<!DOCTYPE html></p>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <form th:action="@{/login}" method="post">
        <div>
            <label for="username">Username:</label>
            <input type="text" id="username" name="username" />
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" id="password" name="password" />
        </div>
        <div>
            <button type="submit">Sign in</button>
        </div>
    </form>
</body>
</html>
4. 스프링 시큐리티 내부 흐름
Spring Security의 내부 흐름을 이해하면 보안 구성을 더 효과적으로 다룰 수 있습니다. 요청이 들어온 후 인증과 인가 과정은 다음과 같은 순서로 이루어집니다.

<p>1) 요청(Request)
사용자가 웹 애플리케이션에 요청을 보냅니다.
2) 필터 체인(FilterChainProxy)
요청은 FilterChainProxy를 통해 여러 보안 필터를 거칩니다. 중요한 필터는 SecurityContextPersistenceFilter, UsernamePasswordAuthenticationFilter, BasicAuthenticationFilter, AuthorizationFilter 등이 있습니다.
3) SecurityContext
SecurityContext는 현재 사용자에 대한 보안 정보를 저장합니다.
4) AuthenticationManager 및 AuthenticationProvider
AuthenticationManager는 인증을 주관하며, AuthenticationProvider를 통해 실제 인증을 수행합니다.
5) UserDetailsService
UserDetailsService는 사용자 정보를 로드하는 역할을 합니다. 주로 데이터베이스나 메모리에서 사용자 정보를 조회합니다.
6) 인증(Authentication)
인증이 성공하면 Authentication 객체가 SecurityContext에 저장됩니다.
7) 인가(Authorization)
인증 후, 사용자가 요청한 자원에 접근할 권한이 있는지 확인합니다.
8) 응답(Response)
인증과 인가가 완료되면 요청한 자원에 대한 접근이 허용되고, 서버는 응답을 반환합니다.
5. Spring Security 필터
Spring Security에서 사용하는 주요 필터는 다음과 같습니다.</p>
<p>UsernamePasswordAuthenticationFilter: 사용자의 로그인 요청을 처리.
BasicAuthenticationFilter: HTTP 기본 인증 처리.
SecurityContextPersistenceFilter: SecurityContext 관리.
AuthorizationFilter: 권한 부여 처리.
6. 마무리
Spring Security는 강력한 보안 프레임워크로, 애플리케이션의 인증 및 권한 관리를 간편하게 할 수 있도록 도와줍니다. 이번 포스트에서는 기본적인 설정과 내부 흐름을 알아보았으며, 이를 바탕으로 다양한 보안 시나리오에 맞게 Spring Security를 활용해 보시길 바랍니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[상태저장 패턴]]></title>
            <link>https://velog.io/@progect_study/%EC%83%81%ED%83%9C%EC%A0%80%EC%9E%A5-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@progect_study/%EC%83%81%ED%83%9C%EC%A0%80%EC%9E%A5-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sun, 25 Aug 2024 18:06:23 GMT</pubDate>
            <description><![CDATA[<p>배달 주문 시스템에서 고객의 진행 상태를 백엔드에서 관리하는 방법을 구현하려면, 상태 관리를 통해 고객의 진행 상태를 추적하는 것이 필요합니다. 이를 위해 흔히 사용되는 패턴 중 하나는 <strong>상태 머신 패턴(State Machine Pattern)</strong>입니다. 이 패턴을 사용하면 고객이 주문 프로세스에서 어디에 있는지 쉽게 추적하고, 중간에 다른 작업을 하더라도 원활하게 이전 상태로 돌아올 수 있게 할 수 있습니다.</p>
<ol>
<li><p>상태 머신 패턴 개요
상태 머신은 시스템이 특정 상태에서 시작하여, 이벤트에 따라 다른 상태로 전이되는 구조입니다. 예를 들어, &quot;메뉴 선택&quot;, &quot;카드 선택&quot;, &quot;결제&quot; 등의 상태를 정의하고, 각 상태에서 특정 조건을 충족하면 다음 상태로 전이되도록 설계합니다.</p>
</li>
<li><p>상태 관리 로직
상태 정의
python
코드 복사
from enum import Enum</p>
</li>
</ol>
<p>class OrderState(Enum):
    MENU_SELECTION = &quot;MENU_SELECTION&quot;
    CARD_SELECTION = &quot;CARD_SELECTION&quot;
    PAYMENT = &quot;PAYMENT&quot;
    COMPLETED = &quot;COMPLETED&quot;
상태 저장
고객의 상태는 세션 또는 데이터베이스에 저장됩니다.
고객이 어디까지 진행했는지를 저장하기 위해 각 고객에 대해 OrderState를 저장하는 필드를 사용합니다.
상태 전이 로직
python
코드 복사
def get_next_state(current_state):
    if current_state == OrderState.MENU_SELECTION:
        return OrderState.CARD_SELECTION
    elif current_state == OrderState.CARD_SELECTION:
        return OrderState.PAYMENT
    elif current_state == OrderState.PAYMENT:
        return OrderState.COMPLETED
    else:
        return OrderState.MENU_SELECTION  # 기본값은 메뉴 선택
3. 상태 확인 및 재진입 처리
고객이 주문을 시작할 때, 현재 고객의 상태를 확인합니다. 만약 고객이 &quot;메뉴 선택&quot; 상태를 완료한 후 다른 작업을 하다가 다시 돌아온 경우, 고객의 현재 상태를 확인하여 &quot;카드 선택&quot; 단계로 바로 넘어갈 수 있도록 합니다.</p>
<p>python
코드 복사
def handle_order_request(user_id):
    current_state = get_user_state(user_id)  # DB나 세션에서 현재 상태를 가져옴</p>
<pre><code>if current_state == OrderState.MENU_SELECTION:
    return render_menu_selection()
elif current_state == OrderState.CARD_SELECTION:
    return render_card_selection()
elif current_state == OrderState.PAYMENT:
    return render_payment_page()
else:
    return render_menu_selection()  # 기본값으로 메뉴 선택 페이지 렌더링</code></pre><ol start="4">
<li>상태 업데이트
각 단계가 완료되면 고객의 상태를 업데이트해야 합니다.</li>
</ol>
<p>python
코드 복사
def update_user_state(user_id, next_state):
    # DB나 세션에 다음 상태를 저장
    save_user_state(user_id, next_state)</p>
<p>def menu_selection_completed(user_id):
    update_user_state(user_id, OrderState.CARD_SELECTION)</p>
<p>def card_selection_completed(user_id):
    update_user_state(user_id, OrderState.PAYMENT)</p>
<p>def payment_completed(user_id):
    update_user_state(user_id, OrderState.COMPLETED)
5. 재진입 시 처리
고객이 중간에 다른 작업을 하다가 돌아왔을 때 handle_order_request 함수가 자동으로 현재 상태에 맞는 페이지를 렌더링하도록 보장합니다.</p>
<ol start="6">
<li>데이터베이스 스키마 예시
sql
코드 복사
CREATE TABLE user_order_state (
 user_id INT PRIMARY KEY,
 order_state VARCHAR(20)
);
고객이 주문을 완료하거나 취소하면 해당 레코드를 업데이트하거나 삭제하여 상태 관리를 합니다.</li>
</ol>
<p>결론
이와 같은 구조로 백엔드에서 상태 관리를 하면 고객이 주문 과정에서 어디까지 진행했는지 쉽게 추적할 수 있고, 중간에 다른 일을 하더라도 자연스럽게 주문을 이어나갈 수 있습니다. 상태 머신 패턴을 사용함으로써 코드의 가독성과 유지보수성도 높일 수 있습니다.</p>
<hr>
<p>세션에서 주문 상태를 관리하고 각 상태를 2분간 유지하려면 스프링에서 세션 타임아웃을 설정하고, 세션을 사용하여 상태를 저장 및 관리하는 방법을 구현할 수 있습니다. 아래는 스프링을 사용하여 메뉴 선택, 카드 선택, 결제 상태를 세션에서 관리하는 예시입니다.</p>
<ol>
<li>스프링 세션 설정
스프링 부트에서는 기본적으로 HTTP 세션을 사용하여 상태를 저장합니다. 세션 타임아웃은 기본적으로 30분으로 설정되어 있지만, 이를 2분으로 줄이기 위해 application.properties 파일에서 설정할 수 있습니다.</li>
</ol>
<p>properties
코드 복사
server.servlet.session.timeout=2m
2. 상태 Enum 정의
주문 상태를 정의하는 OrderState Enum을 작성합니다.</p>
<p>java
코드 복사
public enum OrderState {
    MENU_SELECTION,
    CARD_SELECTION,
    PAYMENT,
    COMPLETED
}
3. 서비스 클래스
서비스 클래스에서는 세션에서 상태를 관리하는 메소드를 제공합니다.</p>
<p>java
코드 복사
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;</p>
<p>@Service
public class OrderService {</p>
<pre><code>public void setOrderState(HttpSession session, OrderState state) {
    session.setAttribute(&quot;orderState&quot;, state);
}

public OrderState getOrderState(HttpSession session) {
    OrderState state = (OrderState) session.getAttribute(&quot;orderState&quot;);
    return (state != null) ? state : OrderState.MENU_SELECTION;
}

public void advanceState(HttpSession session) {
    OrderState currentState = getOrderState(session);
    OrderState nextState;

    switch (currentState) {
        case MENU_SELECTION:
            nextState = OrderState.CARD_SELECTION;
            break;
        case CARD_SELECTION:
            nextState = OrderState.PAYMENT;
            break;
        case PAYMENT:
            nextState = OrderState.COMPLETED;
            break;
        default:
            nextState = OrderState.MENU_SELECTION;
    }

    setOrderState(session, nextState);
}

public void resetOrder(HttpSession session) {
    setOrderState(session, OrderState.MENU_SELECTION);
}</code></pre><p>}
4. 컨트롤러 클래스
컨트롤러에서는 HTTP 요청을 처리하고 상태를 업데이트합니다.</p>
<p>java
코드 복사
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;</p>
<p>import javax.servlet.http.HttpSession;</p>
<p>@Controller
public class OrderController {</p>
<pre><code>@Autowired
private OrderService orderService;

@GetMapping(&quot;/order&quot;)
public String orderProcess(HttpSession session, Model model) {
    OrderState currentState = orderService.getOrderState(session);

    switch (currentState) {
        case MENU_SELECTION:
            return &quot;menuSelection&quot;;  // 메뉴 선택 페이지
        case CARD_SELECTION:
            return &quot;cardSelection&quot;;  // 카드 선택 페이지
        case PAYMENT:
            return &quot;payment&quot;;        // 결제 페이지
        case COMPLETED:
            return &quot;orderCompleted&quot;; // 주문 완료 페이지
        default:
            return &quot;menuSelection&quot;;  // 기본적으로 메뉴 선택 페이지로 돌아감
    }
}

@PostMapping(&quot;/order/menu&quot;)
public String menuSelectionCompleted(HttpSession session) {
    orderService.advanceState(session);
    return &quot;redirect:/order&quot;;
}

@PostMapping(&quot;/order/card&quot;)
public String cardSelectionCompleted(HttpSession session) {
    orderService.advanceState(session);
    return &quot;redirect:/order&quot;;
}

@PostMapping(&quot;/order/payment&quot;)
public String paymentCompleted(HttpSession session) {
    orderService.advanceState(session);
    return &quot;redirect:/order&quot;;
}

@PostMapping(&quot;/order/reset&quot;)
public String resetOrder(HttpSession session) {
    orderService.resetOrder(session);
    return &quot;redirect:/order&quot;;
}</code></pre><p>}
5. 뷰 템플릿
각 상태에 맞는 뷰 템플릿을 작성합니다. 예를 들어 menuSelection.html, cardSelection.html, payment.html, orderCompleted.html 등을 작성하여 상태에 맞는 UI를 제공합니다.</p>
<ol start="6">
<li>결론
위의 예제에서는 스프링의 HTTP 세션을 사용하여 주문 상태를 관리하고, 상태를 변경할 때마다 세션에 저장하도록 구현했습니다. 세션 타임아웃을 2분으로 설정하여, 사용자가 2분 동안 아무런 작업을 하지 않으면 세션이 만료되도록 하였습니다.</li>
</ol>
<p>이 방법은 상태 정보를 서버에서 유지하므로 보안상 안전하며, 세션 타임아웃을 통해 상태를 자동으로 만료시킬 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[카산드]]></title>
            <link>https://velog.io/@progect_study/%EC%B9%B4%EC%82%B0%EB%93%9C</link>
            <guid>https://velog.io/@progect_study/%EC%B9%B4%EC%82%B0%EB%93%9C</guid>
            <pubDate>Sun, 25 Aug 2024 18:03:54 GMT</pubDate>
            <description><![CDATA[<p>카산드라의 기능들</p>
<ol>
<li>Masterless 형태의 분산 아키텍처
기능: 카산드라는 모든 노드가 동등한 역할을 수행하는 masterless 아키텍처를 채택하여 고가용성과 확장성을 제공합니다.
요약: 특정 마스터 노드 없이 모든 노드가 균등한 역할을 하며, 클러스터 내의 어떤 노드가 실패해도 다른 노드가 작업을 이어받아 시스템의 안정성을 유지합니다.</li>
<li>Gossip 프로토콜 사용
기능: 노드 간의 상태 정보를 주기적으로 교환하기 위해 Gossip 프로토콜을 사용합니다.
요약: Gossip 프로토콜을 통해 클러스터 내의 모든 노드가 서로의 상태를 주기적으로 공유하여, 새로운 노드의 추가나 장애 발생 시 빠르게 반응합니다.</li>
<li>Key-Value 형태의 데이터 모델
기능: 카산드라는 데이터 저장에 key-value 모델을 사용하며, 각 row는 고유한 key에 의해 식별됩니다.
요약: 데이터는 row 단위로 저장되며, 각 row의 구성 요소인 column들은 유연하게 정의될 수 있습니다.</li>
<li>파티셔닝과 복제를 통한 성능 및 내결함성 제공
기능: 데이터는 파티셔닝을 통해 클러스터 내의 여러 노드에 분산되며, 복제 메커니즘을 통해 높은 내결함성을 제공합니다.
요약: 기본 키를 기준으로 데이터를 파티셔닝하고, 복제를 통해 데이터의 안정성과 가용성을 높입니다.</li>
<li>CQL(Cassandra Query Language) 제공
기능: 카산드라에서 데이터베이스와 상호작용하기 위한 쿼리 언어인 CQL을 제공합니다.
요약: SQL과 유사한 CQL을 통해 카산드라 데이터베이스에서 데이터를 관리하고 쿼리할 수 있습니다.</li>
<li>일관성 모델 튜닝 가능
기능: 카산드라는 사용자가 원하는 수준의 일관성을 설정할 수 있는 옵션을 제공합니다.
요약: 필요에 따라 읽기 및 쓰기 작업에 대해 일관성 수준을 조정할 수 있어, 성능과 데이터 무결성 사이에서 균형을 맞출 수 있습니다.</li>
</ol>
<hr>
<p>Keyspace: 가장 상위 레벨 데이터 집합 단위로, 테이블을 그룹화 Table(Column Family): RDB의 테이블에 해당
Row: 테이블 내에서 데이터는 row 단위로 저장되고, key로 구분됨 Column: row에 들어있는 데이터로 row마다 다른 column 구성이 가능함 Partition: 각 row의 기본 키를 기준으로 나뉘는 그룹</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[eda]]></title>
            <link>https://velog.io/@progect_study/eda</link>
            <guid>https://velog.io/@progect_study/eda</guid>
            <pubDate>Sun, 25 Aug 2024 16:29:53 GMT</pubDate>
            <description><![CDATA[<h1 id="복제">복제</h1>
<p>마스터-슬레이브 패턴(Master-Slave Pattern) 정리</p>
<p>개요
마스터-슬레이브 패턴은 데이터베이스 시스템에서 자주 사용되는 구조로, 복제와 분산의 한 형태입니다. 이 패턴은 데이터 일관성과 가용성을 보장하면서도 시스템의 확장성과 성능을 향상시키기 위해 사용됩니다.</p>
<p>주요 개념
마스터(Master)</p>
<p>역할: 데이터베이스의 주요 쓰기 작업(데이터 입력, 수정, 삭제)을 담당합니다.
특징: 모든 데이터 변경 사항이 마스터에서 이루어지며, 마스터는 변경된 데이터를 슬레이브로 전파합니다.
단일 포인트: 마스터가 고장 나면 전체 시스템의 쓰기 작업이 중단될 수 있는 단일 장애점이 됩니다.
슬레이브(Slave)</p>
<p>역할: 마스터의 데이터를 복제하여 읽기 작업(데이터 조회)을 처리합니다.
특징: 슬레이브는 마스터로부터 변경된 데이터를 주기적으로 받아서 업데이트합니다. 여러 개의 슬레이브가 있을 수 있으며, 이를 통해 읽기 작업을 분산하여 처리할 수 있습니다.
확장성: 슬레이브를 추가하여 시스템의 읽기 처리 성능을 높일 수 있습니다.
장점
성능 향상: 읽기 작업을 여러 슬레이브에 분산시켜 시스템의 읽기 성능을 크게 향상시킬 수 있습니다.
확장성: 슬레이브를 추가하는 것만으로도 시스템의 처리 능력을 확장할 수 있습니다.
데이터 백업: 슬레이브에 저장된 데이터는 마스터의 백업 역할도 할 수 있습니다.
단점
데이터 일관성 문제: 마스터에서 슬레이브로 데이터가 복제되는 과정에서 약간의 지연이 발생할 수 있어, 슬레이브에서 읽은 데이터가 최신이 아닐 수 있습니다.
마스터 장애: 마스터가 장애를 일으킬 경우, 쓰기 작업이 중단되며 시스템 복구가 필요합니다.
복잡성 증가: 마스터와 슬레이브 간의 데이터 동기화와 복제 설정이 복잡할 수 있습니다.</p>
<p>• 복제(Replication): 데이터나 서비스의 복사본을 만들어서 처리 
• 분산(Distribution): 데이터나 서비스를 여러 곳에 나누어서 처리</p>
<hr>
<h1 id="분산">분산</h1>
<p>분산(Distribution)
• 여러 노드가 범위를 나누어 데이터 처리
• RDB의 파티셔닝(샤딩), Redis 클러스터
• 읽기&amp;쓰기 부하를 분산할 수 있어서 성능 향상에 용이
• 밸런싱과 routing이 중요하고, consistent hashing과 같은 기법
사용됨.
• RDB에서는 JOIN 연산이 불가능</p>
<hr>
<h1 id="분산-문제-eda-사용이유">분산 문제 eda 사용이유</h1>
<p>분산으로 해결되지 않는 문제
• 분산 처리에 따라오는 복잡도와 동시성 문제
ᄋ 데이터 일관성의 문제
ᄋ Routing의 처리
노드 개수 변화에 따른 재조정(rebalancing)
○ 부분 장애
•요청량이 급변할 때(spike traffic)의 확장 문제
• 처리량을 넘었을 때 발생할 수 있는 일시적인 오류</p>
<hr>
<h1 id="이벤트-기반-처리로-얻을-수-있는-것들">이벤트 기반 처리로 얻을 수 있는 것들</h1>
<p>• 요청량 변화에 탄력적으로 대응(비동기적 특성으로 인한 쉬운 확장)
• 관련 서비스의 일시적 오류에도 데이터 유실 없이 정상 작동
● 다른 서비스들과의 느슨한 결합(변경 영향도 최소화)
• 대용량 데이터의 실시간 처리(Batch 처리와 비교)</p>
<hr>
<h1 id="eda와-다른것들">eda와 다른것들</h1>
<ol>
<li>이벤트 알림(Event Notification)
개요:
이벤트 알림은 이벤트 기반 시스템에서 가장 단순한 형태의 패턴입니다. 이 패턴은 이벤트가 발생했음을 다른 시스템 또는 컴포넌트에게 알리기만 합니다.</li>
</ol>
<p>설명:
이벤트 알림은 이벤트가 발생한 사실을 알리기 위해 사용됩니다. 예를 들어, 사용자가 주문을 완료하면 &quot;주문 완료&quot; 이벤트를 발생시킵니다. 이 이벤트는 관련된 다른 시스템(예: 배송 시스템)에게 주문이 완료되었다는 사실을 알리는 역할만 합니다. 이벤트에는 추가적인 데이터나 상태 정보가 포함되지 않으며, 수신자는 추가 데이터를 얻기 위해 별도의 요청을 보내야 할 수 있습니다.</p>
<p>차이점:
이벤트 알림은 이벤트 자체의 정보를 전달하지 않으며, 단순히 이벤트가 발생했다는 사실만을 전달합니다. 이 점에서 이벤트 기반 상태 전송과 다릅니다. 후자는 상태 정보까지 포함하여 전송하므로, 수신자가 추가 데이터를 요청할 필요가 없습니다.</p>
<ol start="2">
<li>이벤트 기반 상태 전송(Event-carried State Transfer)
개요:
이벤트 기반 상태 전송은 이벤트 발생 시 해당 이벤트와 관련된 상태 정보를 포함하여 전송하는 패턴입니다.</li>
</ol>
<p>설명:
이 패턴에서는 이벤트가 발생하면, 이벤트에 관련된 상태 정보가 포함되어 다른 시스템으로 전송됩니다. 예를 들어, 사용자가 주문을 완료했을 때, &quot;주문 완료&quot; 이벤트에 주문의 상세 정보(주문 ID, 품목, 가격 등)를 포함하여 전송합니다. 수신자는 이 정보를 사용해 즉시 필요한 작업을 수행할 수 있으며, 추가적인 데이터 요청이 필요 없습니다.</p>
<p>차이점:
이벤트 알림과 달리, 이벤트 기반 상태 전송은 이벤트 발생 시점의 상태 정보까지 전달합니다. 따라서 수신자가 데이터를 실시간으로 활용할 수 있으며, 추가 요청이 필요하지 않지만, 이벤트의 크기가 커질 수 있다는 단점이 있습니다.</p>
<ol start="3">
<li>이벤트 소싱(Event Sourcing)
개요:
이벤트 소싱은 시스템의 상태를 직접 저장하지 않고, 상태 변화를 유발한 이벤트를 순차적으로 저장하는 패턴입니다.</li>
</ol>
<p>설명:
이 패턴에서는 모든 상태 변경이 이벤트로 저장되며, 이러한 이벤트의 기록이 시스템의 상태를 재구성하는 데 사용됩니다. 예를 들어, 은행 계좌의 잔액을 저장하는 대신, 입금과 출금 이벤트를 모두 기록합니다. 시스템의 현재 상태(예: 계좌 잔액)를 알고 싶다면, 모든 이벤트를 순차적으로 재생하여 상태를 계산합니다.</p>
<p>차이점:
이벤트 소싱은 상태를 직접 저장하는 대신, 이벤트를 통해 상태를 재구성합니다. 이는 이벤트 알림이나 상태 전송과 달리, 시스템 상태의 변경 이력을 완벽하게 추적할 수 있다는 장점이 있지만, 상태를 재구성하는 과정이 복잡하고 시간이 오래 걸릴 수 있습니다.</p>
<ol start="4">
<li>CQRS(Command and Query Responsibility Segregation)
개요:
CQRS는 명령(Command)과 조회(Query) 작업을 분리하여 각각의 모델로 관리하는 패턴입니다.</li>
</ol>
<p>설명:
이 패턴은 시스템에서 쓰기 작업(명령)과 읽기 작업(조회)을 별도의 데이터 모델로 분리합니다. 예를 들어, 주문 시스템에서 주문 생성(쓰기)과 주문 조회(읽기)를 각각 다른 데이터베이스 또는 모델을 사용하여 처리합니다. 이로 인해 각 작업에 최적화된 데이터 구조를 사용할 수 있어 성능을 개선할 수 있습니다. CQRS는 종종 이벤트 소싱과 결합하여 사용되며, 읽기와 쓰기 모델 간의 일관성을 유지하는 것이 중요합니다.</p>
<p>차이점:
CQRS는 이벤트의 전달 방식보다는 시스템의 구조와 관련이 있습니다. CQRS는 쓰기와 읽기 작업을 분리하여 최적화하지만, 구조가 복잡해질 수 있습니다. 이벤트 알림, 상태 전송, 이벤트 소싱은 주로 이벤트를 어떻게 전달하고 저장할 것인지에 관한 패턴입니다.</p>
<hr>
<p>EDA의 장단점
장점
• 느슨한 결합(유연성) 확장성
• 실시간 처리
•분산 아키텍처(MSA)
복잡성
단점
• 디버깅 어려움
• 일관성 관리
• 이벤트 소실 및 중복</p>
]]></description>
        </item>
    </channel>
</rss>