<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jangkku.log</title>
        <link>https://velog.io/</link>
        <description>영원히 남는 기록, 재밌게 쓰자 :)</description>
        <lastBuildDate>Mon, 19 Jun 2023 08:59:54 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jangkku.log</title>
            <url>https://velog.velcdn.com/images/kim-youngjae/profile/20205034-3a33-4ee3-b32b-b8fa780d4c35/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jangkku.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kim-youngjae" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[스프링 부트 AWS S3 연동 시 이미지 업로드 관련 오류 (해결)]]></title>
            <link>https://velog.io/@kim-youngjae/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-AWS-S3-%EC%97%B0%EB%8F%99-%EC%8B%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C-%EA%B4%80%EB%A0%A8-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@kim-youngjae/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-AWS-S3-%EC%97%B0%EB%8F%99-%EC%8B%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C-%EA%B4%80%EB%A0%A8-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Mon, 19 Jun 2023 08:59:54 GMT</pubDate>
            <description><![CDATA[<p>기존의 로컬에서 이미지 파일을 업로드하고 불러오는 로직으로 구현되어 있었다.</p>
<p>이를 배포 시 서버 스토리지(S3) 에서 가져와 사용할 수 있도록 S3 API 를 스프링 부트에 연동하여 이미지 업로드가 잘 되는지 테스트를 진행하였다.</p>
<p>처음 API 연동을 하는데 있어 어려움이 많았는데 @duswnsxnxn 께 많은 도움을 받았다.</p>
<p>구현한 내용에서 문제점은 다음과 같았다.</p>
<p><strong>에러 로그</strong></p>
<p><img src="https://user-images.githubusercontent.com/62341313/246741237-eaada1d2-3562-42c9-a6f9-d513d76f4d3c.png" alt="image"></p>
<p>try-catch 의 예외를 IOException 으로 지정하여 예외를 던져주지 못해 에러 로그를 확인하지 못하고 있었음..
최상위 예외인 Exception 으로 catch 하여 에러 로그를 확인했다.
com.amazonaws.services.s3.model.AmazonS3Exception: The bucket does not allow ACLs (Service: Amazon S3; Status Code: 400; Error Code: AccessControlListNotSupported; Request ID: ECWDZKD95SFQNE7B; S3 Extended Request ID: Lyy8ya1kOYoj5oNlu6FQPFynTPTjpUahryB0uLqP5mxIbkVlAQ7HD4aLk1JzMJjDhLBz18e9xadnhGP/fEyQ9g==; Proxy: null)
이런 예외가 발생하였다.</p>
<p>발생하는 이유를 찾기 위해서는 자바 라이브러리를 계속 파고 들어가는 수 밖에 없는 한계가 있어서 정책 설정을 다시 보니</p>
<p>이미 퍼블릭 액세스를 허용한다고 설정 되어 있었지만
.withCannedAcl(CannedAccessControlList.PublicRead) 메서드로 인해 예외가 발생하는 것이었다.</p>
<p>그래서 권한 정책에 putObjectAcl 정책을 추가해주고 ACL 설정까지 활성화 해주어서야 이 메서드가 제대로 동작을 하였고</p>
<p><strong>권한 정책 추가</strong></p>
<p><img src="https://user-images.githubusercontent.com/62341313/246761312-62ca9afe-21d4-4144-acd9-fdeb012ed690.png" alt="image"></p>
<p><strong>ACL 활성화</strong></p>
<p><img src="https://user-images.githubusercontent.com/62341313/246761464-7ff6e80a-7e0e-40ac-9f64-286e3d989488.png" alt="image"></p>
<p>ACL 설정을 비활성화 할 것을 AWS 에서 권장하니 메서드를 굳이 추가해줄 필요는 없다고 생각했다..</p>
<p>그래도 S3 연동을 하고 이미지 업로드를 해보면서 발생할 수 있는 문제에 대해 고민해볼 수 있는 시간이 되어서 좋았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[spring security 에 대해서]]></title>
            <link>https://velog.io/@kim-youngjae/spring-security-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</link>
            <guid>https://velog.io/@kim-youngjae/spring-security-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</guid>
            <pubDate>Sun, 11 Jun 2023 14:36:40 GMT</pubDate>
            <description><![CDATA[<h2 id="스프링-시큐리티">스프링 시큐리티</h2>
<p>스프링 기반 애플리케이션의 인증과 권한을 담당하는 하위 프레임 워크</p>
<h3 id="인증과-인가">인증과 인가</h3>
<hr>
<p>인증 : 사용자가 어떤 행위를 할 때 본인이 맞는지를 확인하는 절차</p>
<p>인가 : 인증이 완료된 사용자가 요청된 자원에 접근을 할 수 있는지 결정하는 절차</p>
<h3 id="인증-방식에-대해">인증 방식에 대해</h3>
<hr>
<ol>
<li>credential 기반 인증 : 사용자명과 비밀번호를 이용한 방식</li>
<li>이중 인증(twofactor 인증) : 사용자가 입력한 개인 정보를 인증 후, 다른 인증 체계(예: 물리적인 카드)를 이용하여 두가지의 조합으로 인증하는 방식</li>
<li>하드웨어 인증 : 자동차 키와 같은 방식</li>
</ol>
<p>spring security 는 credential 방식의 인증을 취한다.</p>
<ul>
<li>principal : 아이디, (spring security 로 부터 보호받는 자원(resurce) 으로 접근하는 대상)</li>
<li>credential : 비밀번호, (resource 에 접근하는 대상의 비밀번호)</li>
</ul>
<p><img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https://blog.kakaocdn.net/dn/AbFLx/btqEJC1tYaJ/BDq9cRTqiDarlBa3Z05FoK/img.png" alt="Untitled"></p>
<p>주요 모듈로는 이렇게 몇가지가 있는데 주요한 모듈을 중심으로 살펴보자</p>
<h3 id="securitycontextholder"><strong>SecurityContextHolder</strong></h3>
<hr>
<p>보안 컨텍스트 보관함? 뜻을 보면 보안 컨텍스트를 가지고 있는 객체인 것으로 유추가 된다.</p>
<p>조금 자세한 설명은 이렇다.</p>
<p>보안 주체의 세부 정보를 포함하여 응용 프로그램의 현재 보안 컨텍스트에 대한 세부 정보가 저장된다. SecurityContextHolder는 기본적으로 SecurityContextHolder.MODE_INHERITABLETHREADLOCAL 방법과SecurityContextHolder.MODE_THREADLOCAL 방법을 제공한다.</p>
<h3 id="securitycontext"><strong>SecurityContext</strong></h3>
<hr>
<p>Authentication을 보관하는 역할을 하며, SecurityContext를 통해 Authentication 객체를 꺼내올 수 있다.</p>
<p>Authentication을 보관한다.. SecurityContext를 통해 Authentication 객체를 얻는다..!</p>
<h3 id="authentication"><strong>Authentication</strong></h3>
<hr>
<p>Authentication는 현재 접근하는 주체의 정보와 권한을 담는 인터페이스이다.</p>
<p>Authentication 객체는 Security Context에 저장되며, SecurityContextHolder를 통해 SecurityContext에 접근하고, SecurityContext를 통해 Authentication에 접근할 수 있다.</p>
<p><img src="https://file.notion.so/f/s/e9066b00-1340-4bec-a8ee-5d4991a30e5d/Untitled.jpeg?id=2b0ceb1c-ad7c-4a70-9807-d3b6af54a16c&table=block&spaceId=31cca12f-8434-4350-8e15-b65cdbdefa03&expirationTimestamp=1686580362357&signature=Y6Uf6-3xjEOQf3KwiCcPB442e8UqbSW317J_o-871pg&downloadName=Untitled.jpeg" alt="Untitled"></p>
<h3 id="usernamepasswordauthenticationtoken"><strong><strong>UsernamePasswordAuthenticationToken</strong></strong></h3>
<hr>
<p>UsernamePasswordAuthenticationToken은 Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로, User의 ID가 Principal 역할을 하고, Password가 Credential의 역할을 한다.</p>
<p>UsernamePasswordAuthenticationToken의 첫 번째 생성자는 인증 전의 객체를 생성하고, 두번째 생성자는 인증이 완려된 객체를 생성한다.</p>
<p>이건 코드가 같이 있으면 이해가 빠를 것 같아서 첨부해보았다.</p>
<pre><code class="language-java">public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
    // 주로 사용자의 ID에 해당함
    private final Object principal;
    // 주로 사용자의 PW에 해당함
    private Object credentials;

    // 인증 완료 전의 객체 생성
    public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
        super(null);
        this.principal = principal;
        this.credentials = credentials;
        setAuthenticated(false);
    }

    // 인증 완료 후의 객체 생성
    public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
            Collection&lt;? extends GrantedAuthority&gt; authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true); // must use super, as we override
    }
}

public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {
}</code></pre>
<h3 id="간단하게-스프링-시큐리티-이용하기"><strong>간단하게 스프링 시큐리티 이용하기</strong></h3>
<hr>
<pre><code>implementation &#39;org.springframework.boot:spring-boot-starter-security&#39;
implementation &#39;org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.1.RELEASE&#39;</code></pre><p>이렇게 라이브러리를 설치만 하게 되면 </p>
<p><img src="https://file.notion.so/f/s/22e7f0ac-fe45-4aea-abc5-388724a8fb73/Untitled.png?id=03750c30-c439-49fd-8ad9-d9edb23dd5d3&table=block&spaceId=31cca12f-8434-4350-8e15-b65cdbdefa03&expirationTimestamp=1686580331317&signature=svN2jZ5uHRQSZgAmxxjVAKbNZF5V7xr_EcmTwqJek9w&downloadName=Untitled.png" alt="Untitled"></p>
<p>다음과 같은 화면이 나타난다.</p>
<p>기본적으로 인증되지 않은 사용자는 서비스를 사용할 수 없게끔 되어 있다. </p>
<p>따라서 인증을 위한 로그인 화면이 나타나는 것</p>
<p>라이브러리를 추가한 뒤 rebuild를 진행하고</p>
<p>요청들이 스프링 시큐리티의 제어를 받을 수 있도록 시큐리티 설정을 다음과 같이 해준다</p>
<pre><code class="language-java">@Configuration // 스프링의 환경설정 파일임을 의미하는 애너테이션 -&gt; 스프링 시큐리티 설정을 위해 사용되었음
@EnableWebSecurity //모든 요청 URL이 스프링 시큐리티의 제어를 받도록 만드는 애너테이션
public class SecurityConfig {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        http.authorizeHttpRequests().requestMatchers(
                new AntPathRequestMatcher(&quot;/**&quot;)).permitAll();
        return http.build();
    }
}</code></pre>
<p>추가 설명</p>
<blockquote>
<p><code>@EnableWebSecurity</code> 애너테이션을 사용하면 내부적으로 SpringSecurityFilterChain이 동작하여 URL 필터가 적용된다.</p>
</blockquote>
<p>스프링 시큐리티 설정은 SecurityFilterChain을 통해서 할 수 있는데 밑의 코드의 의미는 모든 인증되지 않은 요청을 허락한다는 의미이다. → 로그인을 하지 않아도 모든 페이지에 접근 가능</p>
<pre><code class="language-java">http.authorizeHttpRequests().requestMatchers(
    new AntPathRequestMatcher(&quot;/**&quot;)).permitAll();</code></pre>
<p>더 정리하지는 못했지만 지금 당장 너무 많은 것을 집어 넣기 보다는 내게 필요한 지식을 정리하려고 하자 😚</p>
<p>Reference</p>
<hr>
<p><a href="https://mangkyu.tistory.com/76">[SpringBoot] Spring Security란?</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ResponseEntity란]]></title>
            <link>https://velog.io/@kim-youngjae/ResponseEntity%EB%9E%80</link>
            <guid>https://velog.io/@kim-youngjae/ResponseEntity%EB%9E%80</guid>
            <pubDate>Thu, 01 Jun 2023 02:37:56 GMT</pubDate>
            <description><![CDATA[<p>ResponseEntity란, httpentity를 상속받는, <code>결과 데이터</code>와 <code>HTTP 상태 코드</code>를 직접 제어할 수 있는 클래스이다.</p>
<p>ResponseEntity에는 사용자의  HttpRequest에 대한 응답 데이터가 포함된다.</p>
<p>또한, HTTP 아케텍쳐 형태에 맞게 Response를 보내주는 것에도 의미가 있다.</p>
<p>에러코드와 같은 http 상태코드를 전송하고 싶은 데이터와 함께 전송 → 조금 더 세밀한 제어가 필요한 경우에 사용된다.</p>
<p>ResponseEntity는 HttpEntity를 상속받고 사용자의 응답 데이터가 포함된 클래스이기 때문에</p>
<ol>
<li><strong>HttpStatus</strong></li>
<li><strong>HttpHeaders</strong></li>
<li><strong>HttpBody</strong></li>
</ol>
<p>를 포함한다.</p>
<p><strong>HTTP Header/Body 차이</strong></p>
<hr>
<p>http header에는 (요청/응답)에 대한 요구사항,</p>
<p>http body에는 그 내용이 적혀있고,</p>
<p>Response header 에는 웹서버가 웹브라우저에 응답하는 메시지가 들어있고, Reponse body에 데이터 값이 들어가있다</p>
<p><strong>요약</strong></p>
<p>→ ResponseEntity 클래스를 사용하면, 결과값! 상태코드! 헤더값!을 모두 프론트에 넘겨줄 수 있고, 에러코드 또한 섬세하게 설정해서 보내줄 수 있다는 장점이 있다!</p>
<p>참고 블로그</p>
<p><a href="https://thalals.tistory.com/268">ResponseEntity란  -  개념, 구조, 사용법, 사용하는 이유</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JWT 에 대해서]]></title>
            <link>https://velog.io/@kim-youngjae/JWT-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</link>
            <guid>https://velog.io/@kim-youngjae/JWT-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</guid>
            <pubDate>Thu, 01 Jun 2023 02:35:45 GMT</pubDate>
            <description><![CDATA[<p>JWT 탄생 배경</p>
<p>브라우저 ↔ 서버 사이에서 정보(id, pw …)들을 주고 받을 때 쿠키를 사용하고 이는 요청을 하고 다시 요청을 할 때 같은 요청임을 의미하는 입장권이 개념이었다.</p>
<p>그런데 앱 같은 경우,</p>
<p>아이폰, 안드로이드 앱 ↔ 웹서버 간은 <strong>쿠키 발행을 하지 않는다.</strong> 앱은 웹이 아니기 때문</p>
<p><strong>웹</strong> </p>
<hr>
<p>요청 : ID/PW</p>
<p>요청 : 제목/내용 → 한 번 인증을 하고 나면 그 다음에는 id/pw 를 다시 보내지 않아도 된다 (쿠키가 대신 해줌)</p>
<p>요청 : 제목/내용</p>
<p>웹은 쿠키가 요청마다 계속 ID/PW를 계속 가지고 다닐 수 있는 기능이 있다.</p>
<p><strong>앱</strong></p>
<hr>
<p>요청 : ID/PW, 제목/내용</p>
<p>요청 : ID/PW, 제목/내용</p>
<p>요청 : ID/PW, 제목/내용</p>
<p>초창기 앱은 계속 ID/PW를 모든 요청 시 마다 계속 보냈었다.</p>
<p>앱은 브라우저가 아니기 때문에 쿠키가 없어서 ID/PW를 계속 해서 가지고 다닐 수 있는 수단이 없다.</p>
<p>그래서 요청마다 계속 정보를 넘겨주어야 했었다.</p>
<p>앱 시작</p>
<ul>
<li>아이디 비번을 입력</li>
<li>앱이 서버에게 아이디, 비번이 유효한지 물어본다.</li>
<li>유효한 아이디와 비번이면 그 정보를 영구 저장한다.</li>
<li>하지만 그래도 요청(글쓰기, 좋아요, 인증이 필요한 활동 등등)이 있을 때 마다 계속해서 id, pw를 요청에 담아서 넘겨주어야했다.</li>
</ul>
<p>그래서 쿠키와 같은 역할을 위해서</p>
<p>토큰 ( == 아이디, 비번)</p>
<ul>
<li>아이디 비번 입력</li>
<li>앱이 서버에게 해당 아이디 비번 유효한지 확인</li>
<li>유효하면 서버는 토큰을 발급해주고 아이디와 비번을 영구 저장한다.</li>
</ul>
<h1 id="🤔-토큰을-사용하면-괜찮을까">🤔 토큰을 사용하면 괜찮을까?</h1>
<hr>
<p>기존에 아이디와 비번을 요청 정보에 담아서 넘겨주는 방식을 토큰이 대신한다..</p>
<p>근데 토큰 역시 아이디와 비번을 대체하는 수단이라서 이 역시 해킹의 노출에 취약하다.</p>
<p><strong>개선된 것은 하나가 있다..!</strong></p>
<p>바로 개인 정보라서 인증이 가능하지만 아이디와 비번이 쌩으로 노출되지 않아서 해킹을 당해도 토큰이 노출된 것이지 아이디와 비번은 그대로 남아 있기에 비밀번호를 변경하지 않아도 된다는 것이다…</p>
<p>하지만 여전히 좋은 방식은 아니다. → 왜?.. → 요청마다 계속해서 db select가 발생하기 때문이다.</p>
<h2 id="토큰은-또-단점이-존재했다">토큰은 또 단점이 존재했다.</h2>
<hr>
<p>아무 의미 없는 난수 따위를 사용했어서 길어지기 시작하면 그냥 쓸데없는 값일 뿐이도 그 값 자체가 의미하는 것이 없었다.</p>
<h1 id="jwt-json-web-token">JWT (Json Web Token)</h1>
<hr>
<p>개인정보와 개인키 등을 base64 기반으로 인코딩한 결과 조합을 해시 암호화된 값들로 구성된 토큰인 jwt가 나왔다.</p>
<p>이는 값 자체가 복호화를 하면 의미가 있는 값들로 이루어져 있기 때문에 기존의 토큰보다 조금 개선된 방식이다. </p>
<p>또한 jwt는 최초 인증 후 db select가 일어나지 않아 효율면에서 토큰 보다 더 좋다!</p>
<p>여기서 db를 안거치면 믿을 수 있는 정보가 아니냐 라고 생각할 수 있는데, 시크릿 키를 포함하고 있기 때문에 복호화 후 서버의 시크릿 키와 대조를 하기 때문에 믿을 수 있다.</p>
<p>그래서 정보가 도중에 바뀌어도 서버의 시크릿키를 가지고 정보가 조작되었는지 아닌지의 유무를 알 수 있다..!</p>
<p>서버 사이드에서 이렇게 시크릿키를 가지고 있다.</p>
<pre><code class="language-yaml">custom:
  jwt:
    secretKey: secretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKey</code></pre>
<p>원문의 시크릿 키를 가지고 base64 로 인코딩 한 후 인코딩한 결과를 해시 암호화를 적용해서 암호화 한다.</p>
<pre><code class="language-java">String keyBase64Encoded = Base64.getEncoder().encodeToString(secretKeyPlain.getBytes()); // 원문을 Base64로 인코딩
// Base64 인코딩된 키를 이용하여 SecretKey 객체를 만든다.
SecretKey secretKey = Keys.hmacShaKeyFor(keyBase64Encoded.getBytes()); // 인코딩 한 결과를 암호화</code></pre>
<p>그리고 인코딩과 암호화된 시크릿 키는 하나만 존재해야 하고 시크릿 키를 요청할 때마다 키가 유효하다면 일관된 키를 반환해야 한다.</p>
<pre><code class="language-java">private SecretKey _getSecretKey() { // 시크릿 키를 가져온다
    String keyBase64Encoded = Base64.getEncoder().encodeToString(secretKeyPlain.getBytes());
    return Keys.hmacShaKeyFor(keyBase64Encoded.getBytes());
}

public SecretKey getSecretKey() { // 시크릿키를 가져오는 메서드
    if (cachedSecretKey == null) cachedSecretKey = _getSecretKey(); // 시크릿 키가 존재하지 않으면 가지고 있는 시크릿 키를 base64인코딩 후 암호화

    return cachedSecretKey;
}</code></pre>
<p>getSecretKey() 메서드를 실행할 때에 이미 유효한 키가 존재하는지 여부를 묻고 없으면 생성 후 반환</p>
<p>있다면 원래 있던 (캐시된) 시크릿 키를 반환하는 메서드이다.</p>
<p>읽다가 깔끔하게 정리가 잘 되어 참고하였다.</p>
<p><a href="https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC#thankYou">🌐 JWT 토큰 인증 이란? (쿠키 vs 세션 vs 토큰)</a></p>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fb7f9c6e-79bd-469c-87d6-7c9b2abd4a42/Untitled.png" alt="Untitled"></p>
<p>실습할 땐 헤더를 만들지 않았지만 payload에 해당하는 claim 이 토큰 유효 기간과 함께 담긴다.</p>
<p>claim : 토큰에서 사용할 정보의 조각 → 서버와 클라이언트가 주고 받는 시스템에서 사용될 정보들에 대한 내용을 담고 있다.</p>
<pre><code class="language-java">Map&lt;String, Object&gt; claims = new HashMap&lt;&gt;();
claims.put(&quot;id&quot;, 1L);
claims.put(&quot;username&quot;, &quot;admin&quot;);

// 지금으로부터 5시간의 유효기간을 가지는 토큰을 생성
String accessToken = jwtProvider.genToken(claims, 60 * 60 * 5);</code></pre>
<p>실제 엑토큰을 생성하는 부분인 genToken() 메서드를 들여다 보자</p>
<pre><code class="language-java">public String genToken(Map&lt;String, Object&gt; claims, int seconds) {
    long now = new Date().getTime(); // 현재 시간
    Date accessTokenExpiresIn = new Date(now + 1000L * seconds); // 매개 변수로 들어온 시간을 밀리로 바꿔서 현재 시간에 더해줌

    return Jwts.builder() // jwts 객체를 생성해서 반환 (실제 토큰을 생성하는 부분)
            .claim(&quot;body&quot;, Ut.json.toStr(claims)) // jwt 의 body 부분에 저장할 claim 을 json
            .setExpiration(accessTokenExpiresIn)
            .signWith(getSecretKey(), SignatureAlgorithm.HS512)
            .compact();
}</code></pre>
<p>payload 부분과 (헤더가 있었다면 (헤더 + 페이로드) 부분) 이 body로 들어가는 것을 볼 수 있다.</p>
<p>그리고 토큰 만료 기간을 정해주고 (setExpiration), 시크릿 키를 해시 암호화 해준 뒤 합쳐준다.</p>
<p><strong>질문:  claim() 메서드 매개변수 “body”의 의미가 뭘까?</strong></p>
<hr>
<p>payload가 되어야 하지 않을까?</p>
<p><strong>ChatGPT로 얻은 해답</strong></p>
<hr>
<p><strong><code>claim()</code></strong> 메서드의 첫 번째 매개변수는 클레임의 이름을 나타냅니다. 클레임의 이름은 문자열로 지정되며, 보통 문자열 형태의 식별자를 사용합니다. 위 코드에서는 &quot;body&quot;라는 이름의 클레임을 사용하고 있습니다.</p>
<p>&quot;body&quot; 클레임은 주로 JWT의 본문(body)에 해당하는 데이터를 담는 용도로 사용됩니다. 일반적으로 사용자 정의 데이터를 &quot;body&quot; 클레임에 저장하여 JWT의 내용을 구성합니다. 클레임의 값은 객체 또는 문자열 형태일 수 있습니다.</p>
<p>위 코드에서는 <strong><code>Ut.json.toStr(claims)</code></strong>를 통해 <strong><code>claims</code></strong> 객체를 JSON 문자열로 변환한 후, &quot;body&quot; 클레임의 값으로 지정하고 있습니다. <strong><code>Ut.json.toStr()</code></strong> 메서드는 이전에 설명한대로 <strong><code>Map&lt;String, Object&gt;</code></strong> 객체를 JSON 문자열로 변환하는 역할을 합니다.</p>
<p>따라서, 위 코드에서 &quot;body&quot; 클레임은 <strong><code>claims</code></strong> 객체를 JSON 문자열로 변환한 값으로 설정되며, JWT의 payload에 해당 데이터가 포함되어 전송될 수 있습니다. 이렇게 함으로써 JWT는 토큰 내에 사용자 정의 데이터를 담을 수 있게 되며, 클라이언트나 서버에서 해당 정보를 활용할 수 있습니다.</p>
<p>이렇게 얻은 엑세스 토큰은 다음과 같이 생겼다!!!</p>
<pre><code>accessToken : eyJhbGciOiJIUzUxMiJ9.eyJib2R5Ijoie1wiaWRcIjoxLFwidXNlcm5hbWVcIjpcImFkbWluXCJ9IiwiZXhwIjoxNjg0MjU3NTIxfQ.kh7U8BzumJh12s4opNjwybtgelvwAPiathC3OSdmuEDQ7GumeeU_bjXutaEplQlD8B1q0vsklJfJ2ZjeHbTt-A</code></pre><p>jwt 토큰 생성 방식을 통해 직접 엑세스 토큰을 만들어 보는 시간을 가지면서 jwt의 원리와 구성에 대해 알 수 있었던 시간이었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[신뢰 구간에 대하여]]></title>
            <link>https://velog.io/@kim-youngjae/%EC%8B%A0%EB%A2%B0-%EA%B5%AC%EA%B0%84%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@kim-youngjae/%EC%8B%A0%EB%A2%B0-%EA%B5%AC%EA%B0%84%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Mon, 15 Aug 2022 13:56:17 GMT</pubDate>
            <description><![CDATA[<p>신뢰 구간이란 특정구간에 미지의 모수가 포함될 확률을 말한다.</p>
<p>ex) 95% 신뢰구간 = 이 구간에 미지의 모수가 포함될 확률이 95%라는 뜻</p>
<p>모수(parameter)</p>
<ul>
<li>모집단(population)의 특성을 나타내는 수치</li>
<li>모평균, 모분산, 모표준편차, 모비율, 모상관관계 등이 있다.</li>
</ul>
<p>예를 좀 더 구체적으로...
만약 누군가가 점추정를 통해 &quot;A후보의 지지율은 44.3%입니다&quot;라고 말한다면, 자신감 있어 보이더라도 틀린 말이 될 수 있다. 실제 지지율이 44.8%라면 말이다. 이와 같은 <strong>점추정</strong>은 틀릴 가능성이 높다.
반면 <strong>구간추정</strong>을 통해 &quot;A후보의 지지율은 신뢰수준 95%로 신뢰구간 41.3%~47.3% 내에 있습니다&quot;라고 말한다면, 좀 더 안전하다. 물론 구간추정도 틀릴 수 있지만, 점추정에 비하면 틀릴 가능성이 적다.</p>
<p><del>뭔가 말만 그럴듯하게 하는거 같기도 하고...</del></p>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/d8098890-2a45-4fac-ad39-838e4976cada/image.png" alt=""></p>
<p><a href="https://bskyvision.com/entry/%EB%AA%A8%ED%8F%89%EA%B7%A0%EC%9D%98-%EC%8B%A0%EB%A2%B0%EA%B5%AC%EA%B0%84-%EC%B6%94%EC%A0%95%ED%95%98%EA%B8%B0">사진 및 내용 출처</a></p>
<p>신뢰수준 1-$\alpha$가 0.95 95%라면 $\alpha$ = 0.05 모수가 신뢰구간에 포함되지 못할 확률이 $\alpha \over 2$로 존재</p>
<h2 id="신뢰구간을-추정할-때는-상황에-따라-다른-확률분포를-사용">신뢰구간을 추정할 때는 상황에 따라 다른 확률분포를 사용!</h2>
<ul>
<li><p>모 분산 $\sigma^2$ 알고 있을 때 (모분산 알기가 쉽지 않음)</p>
<ul>
<li>표본 크기와 상관없이 정규분포 사용</li>
</ul>
</li>
<li><p>$\sigma^2$ 모르는데 표본 크기가 충분히 큼 -&gt; 정규분포 활용</p>
</li>
<li><p>$\sigma^2$ 모르는데 표본 크기가 충분히 크지 않을 때 -&gt; t-분포 활용(하지만 t분포 사용하려면 모집단이 정규분포를 따라야 함)</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[그래프 구현]]></title>
            <link>https://velog.io/@kim-youngjae/%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@kim-youngjae/%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 11 Aug 2022 07:10:07 GMT</pubDate>
            <description><![CDATA[<p>그래프를 구현하는 방법은 두 가지로 나뉜다.</p>
<ol>
<li><p>인접 행렬을 활용한 그래프 구현</p>
</li>
<li><p>인접 리스트(ArrayList)를 활용한 그래프 구현</p>
</li>
</ol>
<h1 id="인접행렬을-활용한-그래프-구현">인접행렬을 활용한 그래프 구현</h1>
<pre><code class="language-java">package testcases;

import java.io.*;

public class Test {

    public static void printGraph(int[][] graph) {
        for(int i = 1; i &lt; graph.length; i++) {
            for(int j = 1; j &lt; graph.length; j++) {
                System.out.print(graph[i][j] + &quot; &quot;);
            }
            System.out.println();
        }
    }

    public static void putEdge(int[][] graph, int x, int y) {
        graph[x][y] = 1;
        graph[y][x] = 1;
    }

    public static void main(String[] args) throws IOException {
        int n = 5; //그래프 정점의 개수
        int[][] graph = new int[n+1][n+1]; //index를 1부터 맞추기 위해 n+1

        putEdge(graph, 1, 2);
        putEdge(graph, 1, 3);
        putEdge(graph, 1, 4);
        putEdge(graph, 2, 3);
        putEdge(graph, 2, 5);
        putEdge(graph, 3, 4);
        putEdge(graph, 4, 5);

        printGraph(graph);
    }
}</code></pre>
<h1 id="인접-리스트를-활용한-그래프-구현">인접 리스트를 활용한 그래프 구현</h1>
<pre><code class="language-java">package testcases;

import java.io.*;
import java.util.ArrayList;

public class Test {

    public static void print(ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph) {
        for (int i = 1; i &lt; graph.size(); i++) {
            ArrayList&lt;Integer&gt; node = graph.get(i); // 2차원 리스트 graph의 i번째를 arraylist로 가져옴
            System.out.print(&quot;node&quot;+&quot;[&quot;+i+&quot;] : &quot;);
            for (int j = 0; j &lt; node.size(); j++)
                System.out.print(node.get(j)+ &quot;-&gt;&quot;);
            System.out.println();
        }
    }

    public static void putEdge(ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph, int x, int y) {
        graph.get(x).add(y); // get(): 해당 번지의 값을 가져옴 
        graph.get(y).add(x);
    }

    public static void main(String[] args) throws IOException {
        ArrayList&lt;ArrayList&lt;Integer&gt;&gt; graph = new ArrayList&lt;&gt;();

        for (int i = 0; i &lt;= 5; i++)
            graph.add(new ArrayList&lt;&gt;());

        putEdge(graph, 1, 2);
        putEdge(graph, 1, 3);
        putEdge(graph, 1, 4);
        putEdge(graph, 2, 3);
        putEdge(graph, 2, 5);
        putEdge(graph, 3, 4);
        putEdge(graph, 4, 5);

        //        System.out.println(graph);
        //        ArrayList&lt;Integer&gt; node = graph.get(3);
        //        System.out.println(node);

                print(graph); 
    }
}</code></pre>
<h1 id="각각의-장단점">각각의 장단점</h1>
<table>
<thead>
<tr>
<th align="center">------</th>
<th align="center">인접 행렬</th>
<th align="center">인접리스트</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>시간복잡도</strong></td>
<td align="center">$O(N^2)$ 정점 N * N 만큼 필요</td>
<td align="center">$O(N)$ N : 간선의 개수</td>
</tr>
<tr>
<td align="center"><strong>두 정점의 연결 여부</strong></td>
<td align="center">graph[x][y] 의 값으로 한번에 확인</td>
<td align="center">graph<x> 의 원소에서 y가 나올때까지 탐색</td>
</tr>
<tr>
<td align="center">인접 노드 파악 여부</td>
<td align="center">N * N만큼 반복문을 돌아 확인한다.</td>
<td align="center">각 리스트에 담겨있는 원소를 확인한다.</td>
</tr>
</tbody></table>
<ul>
<li><p>행렬의 경우</p>
<p>두 정점이 연결되있는지를 확인하는 방법이 쉽다. 
graph[x][y]의 값을 바로 확인해서 유무를 판단할 수 있기 때문이다.
단, 정점이 N개인 경우, 행렬을 만들기 위해선 N * N만큼의 공간이 필요하게 된다.</p>
<p>무방향 그래프의 경우는 절반의 공간이 낭비되는 셈이다.</p>
</li>
<li><p>리스트의 경우</p>
<p>실제 연결된 노드들만 리스트 원소에 담겨있으므로 공간 복잡도가 N(간선)이다.</p>
<p>다만, 두 정점 x, y가 연결되있는지 알고 싶다면 노드x 리스트로 들어가 원소 y가 있는지 처음부터 쭉 탐색해야 하므로 행렬보다 더 많은 시간이 소요된다.</p>
</li>
</ul>
<p>둘 다 각각 장단점을 가지고 있으므로 상황에 따라 맞게 골라쓰면 된다.</p>
<blockquote>
<p>간선이 많은 그래프의 경우, 인접 행렬을 통해 빠르게 연결 여부를 확인할 수 있다.</p>
</blockquote>
<blockquote>
<p>반면 간선이 적은 그래프의 경우는 인접 리스트를 통해 인접 노드를 빠르게 확인할 수 있다.</p>
</blockquote>
<p>🙇‍♂️출처🙇‍♂️ : <a href="https://born2bedeveloper.tistory.com/42">https://born2bedeveloper.tistory.com/42</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[내가 잘 몰라서 정리하는 시간 복잡도]]></title>
            <link>https://velog.io/@kim-youngjae/%EB%82%B4%EA%B0%80-%EC%9E%98-%EB%AA%B0%EB%9D%BC%EC%84%9C-%EC%A0%95%EB%A6%AC%ED%95%98%EB%8A%94-%EC%8B%9C%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84</link>
            <guid>https://velog.io/@kim-youngjae/%EB%82%B4%EA%B0%80-%EC%9E%98-%EB%AA%B0%EB%9D%BC%EC%84%9C-%EC%A0%95%EB%A6%AC%ED%95%98%EB%8A%94-%EC%8B%9C%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84</guid>
            <pubDate>Fri, 05 Aug 2022 04:06:43 GMT</pubDate>
            <description><![CDATA[<p>정리에 앞서서 편입을 하여 SW공학을 전공하게 되면서 3학년 때 기본적인 알고리즘과 자료구조에 대해서 공부를 마지막으로 정말 제대로 자료구조와 알고리즘에 대해서 열의를 가지고 공부를 하지 않은 내 자신에게 너무 미안해서...</p>
<p>나 자신에게 남는 공부를 하고 싶다는 생각을 하게 되어 차근차근 정리 해보려고 한다.</p>
<blockquote>
<p>천리길도 첫발을 내딛는 것 부터가 시작이다. 도저언!!!</p>
</blockquote>
<hr>
<p></br></br></p>
<h1 id="시간-복잡도">시간 복잡도</h1>
<ul>
<li><p>입력된 데이터가 출력할 때까지 걸린 시간
  알고리즘이 수행되는 시간</p>
</li>
<li><p>시간 복잡도가 낮다 -&gt; 입력-출력까지의 시간이 짧다고 생각하자
  시간 복잡도가 높다 -&gt; 입력-출력까지의 시간이 길게 걸린다</p>
</li>
</ul>
<h2 id="점진적-표기법">점진적 표기법</h2>
<p>표기법에는 3가지가 있다.</p>
<pre><code>1. 오메가 표기법(Ω) : 제일 좋은 경우

2. 세타 표기법 (Θ) : 평균적인 경우

3. 빅오 표기법 (O) : 제일 나쁜 경우</code></pre><p><img src="https://velog.velcdn.com/images/kim-youngjae/post/d57e69dd-46ef-46b9-a303-d6b9c03b8c0e/image.png" alt=""></p>
<p>출처: <a href="https://www.bigocheatsheet.com/">https://www.bigocheatsheet.com/</a></p>
<h2 id="시간-복잡도-계산">시간 복잡도 계산</h2>
<p>시간 복잡도는 일반적으로 빅오 표기법으로 나타냅니다.</p>
<p>연산 횟수가 다항식으로 표현될 경우, 최고차항을 제외한 모든 항과 최고차항의 계수를 제외시켜 나타냅니다.</p>
<p>예를 들어 입력 크기가 n이라고 했을 때 다음과 같이 표기합니다.</p>
<p>$T(n) = n^2 + 2n + 3 = O(n^2)$ : 최고차항만 나타냄.
$T(n) = 4n = O(n)$ : 최고차항의 계수는 제외함.</p>
</br>

<p><strong>예제</strong></p>
<pre><code class="language-java">    static int func(int n) {
        int sum = 0; // 대입: 1
        int i = 0; // 대입: 1

        for(i = 0; i &lt; n; i++) { // 반복 수행: n, 대입: 1
            sum += i; // 대입: n
        }
        for(i = 0; i &lt; n; i++) { //반복 수행: n, 대입: 1
            sum += i; //대입: n
        }
        return sum;
    }</code></pre>
<p>시간 복잡도는 4n + 5 따라서 $O(n)$ 으로 표기한다.</p>
<h3 id="on2">$O(n^2)$</h3>
<hr>
<p>반복문 안에 반복문이 있는 경우</p>
<pre><code class="language-java">static void func(int[] arr) {
        for(int i = 0; i &lt; arr.length; i++) {
            for(int j = 1; j &lt; arr.length; j++) {
                System.out.println(arr[i] + arr[j]);
            }
        }
    }</code></pre>
<h3 id="olog-n">$O(log n)$</h3>
<hr>
<p>i의 증가율이 2배씩 증가할 때</p>
<pre><code class="language-java">static void func(int n) {
        int i = 0;

        while(i &lt; n) {
            System.out.println(i);
            i *= 2;
        }
    }</code></pre>
<h3 id="onlogn">$O(n*logn)$</h3>
<hr>
<p>$O(n)$ 과 $O(logn)$이 중첩된 형태</p>
<pre><code class="language-java">    static void func(int n) {

        for(int j = 0; j &lt; n; j++) {

            int i = 0;

            while(i &lt; n) {
                System.out.printf(&quot;%d %d&quot;, i, j);
                i *= 2;
            }            
        }
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[R 헷갈릴 만한 용어 정리]]></title>
            <link>https://velog.io/@kim-youngjae/R-%ED%97%B7%EA%B0%88%EB%A6%B4-%EB%A7%8C%ED%95%9C-%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@kim-youngjae/R-%ED%97%B7%EA%B0%88%EB%A6%B4-%EB%A7%8C%ED%95%9C-%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 02 Aug 2022 14:10:09 GMT</pubDate>
            <description><![CDATA[<h1 id="na--null">NA &amp; NULL</h1>
<ul>
<li>NA 와 NULL 모두 결측 값을 의미한다.</li>
</ul>
<h2 id="nanot-available">NA(Not Available)</h2>
<ul>
<li><span style="color: red">공간을 차지하는 결측값을</span> 의미</li>
<li>비교할 값이 존재하지 않으므로 어떤 것과 비교를 하더라도 NA를 반환<blockquote>
<p>즉, 연산을 할 때 에러를 띄우진 않는다. 모두 NA를 반환할 뿐.</p>
</blockquote>
</li>
</ul>
<h2 id="null">NULL</h2>
<ul>
<li><span style="color: red">공간을 차지하지 않는 결측값을</span> 의미</li>
</ul>
<h2 id="nan">NaN</h2>
<ul>
<li>Not a Number : 음수의 제곱근을 구하려고 시도하는 것과 같은 경우에 오류와 함께 숫자가 아님을 반환한다.</li>
</ul>
<h1 id="산술-연산자">산술 연산자</h1>
<ul>
<li>생각보다 헷갈리는 것들이 있다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">산술 연산자</th>
<th align="center">내용</th>
</tr>
</thead>
<tbody><tr>
<td align="center">+</td>
<td align="center">덧셈</td>
</tr>
<tr>
<td align="center">-</td>
<td align="center">뺄셈</td>
</tr>
<tr>
<td align="center">*</td>
<td align="center">곱셈</td>
</tr>
<tr>
<td align="center">/</td>
<td align="center">나눗셈</td>
</tr>
<tr>
<td align="center">%/%</td>
<td align="center">두 숫자의 나눗셈의 몫</td>
</tr>
<tr>
<td align="center">%%</td>
<td align="center">두 숫자의 나눗셈의 나머지</td>
</tr>
<tr>
<td align="center">^, **</td>
<td align="center">거듭제곱</td>
</tr>
<tr>
<td align="center">exp()</td>
<td align="center">자연상수의 거듭제곱</td>
</tr>
</tbody></table>
<h1 id="벡터">벡터</h1>
<ul>
<li><p><u>타입이 같은 여러 데이터를 하나의 행으로 저장하는 1차원 데이터 구조</u></p>
</li>
<li><p>c(1,2,3,4,5), c(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;) c(1:3) = c(1,2,3)</p>
</li>
</ul>
<h1 id="행렬">행렬</h1>
<ul>
<li><p>2차원 구조를 가진 벡터</p>
</li>
<li><p>벡터의 성질을 가지므로 행렬에 저장된 <u>모든 데이터는 같은 타입</u>이어야 한다</p>
</li>
</ul>
<pre><code class="language-Rstudio">m1 = matrix(c(2,3,4,5), nrow = 2); m1 # 기본적으로 열부터 들어간다</code></pre>
<p>결과</p>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/4e31290d-4b09-4c3e-b290-cca35a78aaac/image.png" alt=""></p>
<ul>
<li>byrow=True 조건을 주면 행으로 저장된다.</li>
</ul>
<hr>
<h1 id="배열">배열</h1>
<ul>
<li><p>3차원 이상의 구조를 갖는 벡터</p>
</li>
<li><p>array를 사용하여 배열을 만들 수 있으나 몇 차원 구조를 갖는지 dim옵션에 명시해야 한다.</p>
</li>
<li><blockquote>
<p>그렇지 않으면 1차원 벡터가 생성된다.</p>
</blockquote>
</li>
<li><p>2행 2열 행렬이 3차원으로 이루어진 배열
<img src="https://velog.velcdn.com/images/kim-youngjae/post/a853b410-792f-4528-8e7a-749cebef7c12/image.png" alt=""></p>
</li>
</ul>
<h1 id="리스트">리스트</h1>
<ul>
<li><u>데이터 타입/구조에 상관없이 사용자가 원하는 모든 것을 저장</u>할 수 있는 자료구조</li>
</ul>
<p>첫 번째 성분 l1[[1]] : a, 숫자형 데이터</p>
<p>두 번째 성분 l1[[2]] : test1, 백터</p>
<p>세 번째 성분 l1[[3]] : m1, 2행 2열 행렬</p>
<p>네 번째 성분 l1[[4]]: a1, 2행 2열 행렬이 3차원으로 이루어진 배열</p>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/7baef7fc-e493-431e-9320-ea31df117863/image.png" alt=""></p>
<ul>
<li>리스트의 각 성분들을 인덱싱하는 방법</li>
</ul>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/546341c7-fd2d-4551-8d9e-94d98784ef5d/image.png" alt=""></p>
<hr>
<h1 id="데이터-프레임">데이터 프레임</h1>
<ul>
<li><p>데이터 분석을 위한 2차원 구조</p>
</li>
<li><p>행렬과 같은 모양이지만 여러 개의 벡터로 구성, <u>각 열은 서로 다른 타입의 데이터를 가질 수 있다.</u></p>
</li>
</ul>
<hr>
<h1 id="r-내장-함수">R 내장 함수</h1>
<ul>
<li>paste() : 문자열을 이어 붙인다.
<img src="https://velog.velcdn.com/images/kim-youngjae/post/324a3300-a45c-49ea-8934-2fe59e542bdc/image.png" alt=""></li>
</ul>
<ul>
<li><p>seq() : 시작값, 끝값, 간격으로 수열을 생성한다.</p>
</li>
<li><p>rep() : 주어진 데이터를 일정 횟수만큼 반복한다.</p>
</li>
<li><p>rm() : 대입 연산자에 의해 생성된 변수를 삭제한다.</p>
</li>
<li><p>ls() : 현재 생성된 변수들의 리스트를 보여준다.</p>
</li>
<li><p>print() : 값을 콘솔창에 출력한다.</p>
</li>
</ul>
<h1 id="날짜를-다루는-함수">날짜를 다루는 함수</h1>
<ul>
<li><p>format(Sys.Date(), ‘%a’)  : 요일조회</p>
</li>
<li><p>format(Sys.Date(), ‘%b’)  : 축약된 월 이름 조회 (fab)</p>
</li>
<li><p>format(Sys.Date(), ‘%B’)  : 전체 월 이름 조회 (faburary)</p>
</li>
<li><p>format(Sys.Date(), ‘%d’)  : 두자리 숫자의 일조회</p>
</li>
<li><p>format(Sys.Date(), ‘%m’)  : 두자리 숫자의 월조회</p>
</li>
<li><p>format(Sys.Date(), ‘%y’)  : 두자리 숫자의 연도 조회</p>
</li>
<li><p>format(Sys.Date(), ‘%Y’)  : 네자리 숫자의 연도 조회</p>
</li>
</ul>
<h1 id="데이터프레임에-활용되는-함수들">데이터프레임에 활용되는 함수들</h1>
<ul>
<li><p>data.frame(벡터, 벡터, 벡터,…) : 벡터들을 통해 데이터프레임 생성. 이때 벡터들은 서로 다른 타입일 수 있음</p>
</li>
<li><p>rbind(df1, df2) : 두 데이터프레임을 행으로 결합</p>
</li>
<li><p>cbind(df1, df2) : 두 데이터프레임을 열로 결합</p>
</li>
<li><p><code>new[newdata$a=1]</code>  : new 데이터프레임에서 a=1인 값만 조회
  <code>new[new$변수1&gt;4 &amp; new$변수2 &gt; 5,  c(변수3, 변수4)]</code> : 데이터셋의 변수1과 변수2가 각각 4보다 크고 5보다 큰 조건을 만족하는 경우 변수3과 변수4만을 조회</p>
</li>
<li><p>subset(df, select=열이름) : df에서 열이름만 선택</p>
</li>
<li><p>subset(df, select=c(열이름, 열이름,…,열이름) : df에서 나열된 열을 모두 선택</p>
</li>
<li><p>subset(df, select=열이름, subset=(조건)) : 조건에 맞는 행의 열이름만 선택</p>
</li>
<li><p>subset(df, select=-”열이름＂) : 해당 열만 제거</p>
</li>
<li><p>colnames(df)=newnames  : df의 열이름 변경</p>
</li>
<li><p>rownames(df)=newnames : df의 행이름 변경</p>
</li>
<li><p>NA_cleaning &lt;- na.omit(df) : df에 NA가 들어있는 행 삭제</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[추정/가설검정에 관하여]]></title>
            <link>https://velog.io/@kim-youngjae/%EC%B6%94%EC%A0%95%EA%B0%80%EC%84%A4%EA%B2%80%EC%A0%95%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@kim-youngjae/%EC%B6%94%EC%A0%95%EA%B0%80%EC%84%A4%EA%B2%80%EC%A0%95%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Tue, 26 Jul 2022 09:45:51 GMT</pubDate>
            <description><![CDATA[<h1 id="추정">추정</h1>
<p>추정은 크게 2가지로 나눈다</p>
<ul>
<li><p><strong>점추정</strong></p>
</li>
<li><p><strong>구간추정</strong></p>
</li>
</ul>
<h2 id="1-점추정">1. 점추정</h2>
<ul>
<li><p><u>모수가 특정한 값일 것</u>이라고 추정하는 것</p>
</li>
<li><p>표본의 평균 중위수, 최빈값 등을 사용 -&gt; 표본의 값을 사용</p>
</li>
</ul>
<blockquote>
<p>점추정량의 조건</p>
</blockquote>
<ul>
<li><ol>
<li>불편성: 추정량 기댓값은 모집단의 모수와 차이가 없다</li>
</ol>
</li>
<li><ol start="2">
<li>효율성: 분산이 작을수록 좋다</li>
</ol>
</li>
<li><ol start="3">
<li>일치성: 표본 크기가 커지면, 추정량이 모수와 거의 같아진다</li>
</ol>
</li>
<li><ol start="4">
<li>충족성: 추정량은 모수에 대하여 모든 정보를 제공한다</li>
</ol>
</li>
</ul>
<hr>
<h2 id="2-구간추정">2. 구간추정</h2>
<ul>
<li><p><u>모수가 특정한 구간에 있을 것이라고 추정</u></p>
</li>
<li><p>모분산 $\sigma^2$ 을 알고 있는지의 유무에 따라
  알려진 경우 -&gt; $\sigma$ 사용
  알려져 있지 않은 경우 -&gt; $S$ (표본 분산) 사용</p>
</li>
</ul>
<hr>
<h1 id="가설검정">가설검정</h1>
<h2 id="귀무가설-h_0">귀무가설 ($H_0$)</h2>
<ul>
<li><u>비교하는 값과 차이가 없다, 동일하다, 유효하지 않다</u> 등을 기본 개념으로 하는 가설</li>
</ul>
<h2 id="대립가설-h_1">대립가설 ($H_1$)</h2>
<ul>
<li>뚜렷한 증거가 있을 때 주장하는 가설</li>
</ul>
<h2 id="span-stylecolor-yellow유의-수준span"><span style="color: yellow">유의 수준</span></h2>
<ul>
<li><p>귀무가설을 기각하게 되는 확률의 크기</p>
</li>
<li><p>귀무가설이 옳은데도 이를 기각하는 확률의 크기
  -&gt; 1종 오류를 허용하는 확률</p>
</li>
</ul>
<p>난 이걸 진짜 개념을 공부할 때 만큼은 완벽하게 이해했다고 생각했지만 <del>(다시 보면 까먹고 돌아서면 까먹어서..)</del></p>
<p>예를 들어보자!!</p>
<p>예시는 <a href="https://hsm-edu.tistory.com/732">이 블로그</a>의 예시를 참고 하였다.</p>
<p>장꾸는 제약회사에서 일을 하고있다. 탈모 치료약을 개발하였는데 효과가 좋은지 검정을 하고 싶다. 임상시험을 위해서 환자 100명을 모집하였고 약을 투여해서 전과후를 측정하였다. 이때의 귀무가설은 다음과 같습니다.</p>
<p>$H_0$ : 투약전과 후의 머리카락 갯수는 같다(차이가 없다)</p>
<p>귀무가설이 채택되면 회사는 망합니다. 귀무가설은 우리가 거짓으로 만들고 싶은 가설입니다. </p>
<p>대립가설은 귀무가설에 반대되는 가설입니다. 이 경우는 단순히 다르다가 아니라 부등호가 붙어야 합니다.</p>
<p>$H_1$ : 투약 후가 전보다 머리카락의 수가 많다!(차이가 난다!)</p>
<p>즉, 대립가설은 우리가 주장하는 가설입니다. 우리는 귀무가설을 기각하고 대립가설을 채택하고 싶음</p>
<p>하지만 이때 총 4가지의 상황이 발생할 수 있습니다.</p>
<ol>
<li>귀무가설이 참이고 참으로 판별 -&gt; (옳은 결정)</li>
</ol>
<p><span style="color: red">2. 귀무가설이 참인데 거짓으로 판별(1종 오류)</span> -&gt; (오류)</p>
<ol start="3">
<li><p>귀무가설이 거짓인데 참으로 판별(2종 오류) -&gt; (오류)</p>
</li>
<li><p>귀무가설이 거짓인데 거짓으로 판별 -&gt; (옳은 결정)</p>
</li>
</ol>
<p>1종오류와 2종오류를 예제에 적용해보자</p>
<blockquote>
<p>1종오류 : 탈모를 치료하는 약이 실제로 효과가 없는데 있다고 판별함</p>
</blockquote>
<blockquote>
<p>2종오류 : 탈모를 치료하는 약이 실제로 효과가 있는데 효과가 없다고 판별함</p>
</blockquote>
<p>포인트는 더 심각한 상황을 판단을 해야합니다!!
2종오류의 결과는 제약회사의 개발 비용을 날리게 됩니다. 이것도 충분히 심각한 상황이긴합니다만 1종오류의 결과로 수많은 탈모인들이 탈모약을 구매하고 복용하였지만 실제로는 효과가 없는 상황입니다. 그리고 이 복용으로 인해 다른 질병이 발생할 수 있는 상황입니다.</p>
<p>그래서 1종오류를 통제하는 것입니다. 이를 통제하기 위해 p-value라는 유의수준을 사용합니다.</p>
<hr>
<blockquote>
<p>추가적으로 내용을 수정해야한다면 바로 고치겠습니다. 조금 더 좋은 예제가 있다면 알려주세요..!
많은 도움이 될 것 같습니다. 감사합니다.</p>
</blockquote>
<hr>
<h1 id="모수비모수-검정에-대해서">모수/비모수 검정에 대해서</h1>
<h2 id="모수적-검정">모수적 검정</h2>
<ul>
<li><p>모집단의 분포에 대한 가정</p>
</li>
<li><p><span style="color: red">검정 방법</span>: 관측된 자료를 이용 <u>(표본 평균, 표본 분산)</u></p>
</li>
</ul>
<h2 id="비모수적-검정">비모수적 검정</h2>
<ul>
<li><p>관측 자료가 특정 분포를 따른다고 가정할 수 없을 때</p>
</li>
<li><p>자료의 수가 많지 않거나 서열관계를 나타내는 경우 이용</p>
</li>
<li><p><span style="color: red">검정 방법</span>: 관측값들의 <u>순위나 두 관측값 사이의 부호 등을</u> 활용</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[확률 분포 종류]]></title>
            <link>https://velog.io/@kim-youngjae/%ED%99%95%EB%A5%A0-%EB%B6%84%ED%8F%AC-%EC%A2%85%EB%A5%98</link>
            <guid>https://velog.io/@kim-youngjae/%ED%99%95%EB%A5%A0-%EB%B6%84%ED%8F%AC-%EC%A2%85%EB%A5%98</guid>
            <pubDate>Mon, 25 Jul 2022 12:44:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이산/연속 확률 변수 종류와 정의 특징을 알아보자</p>
</blockquote>
<h1 id="1-이산형-확률변수">1) 이산형 확률변수</h1>
<h2 id="span-stylecolor-yellow베르누이-확률분포span"><span style="color: yellow"><strong>베르누이 확률분포</strong></span></h2>
<ul>
<li>결과가 2개만 나오는 경우(ex: 동전 던지기, 시험의 합격/불합격 등)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/288bed28-5530-46be-9703-436f84ad08c8/image.png" alt=""></p>
<h2 id="이항분포">이항분포</h2>
<ul>
<li><p><u>베르누이 시행을</u> n번 반복했을 때 k번 성공할 확률
<img src="https://velog.velcdn.com/images/kim-youngjae/post/947450e2-09b5-479f-8603-de6fb7d21de5/image.png" alt=""></p>
</li>
<li><p>성공할 확률 p 0이나 1에 가깝지 않고 n이 충분히 크면 이항분포는 정규분포에 가까워 진다</p>
<h2 id="기하분포">기하분포</h2>
</li>
<li><p>성공확률이 p인 <u>베르누이 시행에서</u> 첫번째 성공이 있기까지 <u>x번 실패할 확률</u></p>
</li>
</ul>
<h2 id="다항분포">다항분포</h2>
<ul>
<li>이항분포를 확장한 것으로 세가지 이상의 결과를 가지는 반복 시행에서 발생하는 확률 분포</li>
</ul>
<h2 id="포아송분포">포아송분포</h2>
<ul>
<li><p>시간과 공간 내에서 발생하는 사건의 발생횟수에 대한 확률분포</p>
</li>
<li><p>응용</p>
<ul>
<li>책에 오타가 5page당 10개씩 나온다고 할 때, 한 페이지에 오타가 3개 나올 확률</li>
<li>어떤 시간 동안 톨게이트를 통과하는 차량의 수</li>
</ul>
</li>
<li><p>정해진 시간 안에 어떤 사건이 일어날 횟수에 대한 기댓값을 $$\lambda$$ 라고 했을 때, 그 사건이 $$k$$ 회 일어날 확률은 다음과 같다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/b6b30e82-a7c7-4d72-8fb7-e422ae9ceede/image.png" alt=""></p>
<hr>
<h1 id="2-연속형-확률변수">2) 연속형 확률변수</h1>
<blockquote>
<p>가능한 값이 실수의 어느 특정구간 전체에 해당하는 확률 변수
확률 밀도 함수를 이용하여 분포를 표현할 수 있는 확률분포</p>
</blockquote>
<p>확률 밀도 함수 $$f(x)$$는 다음 두 조건을 만족하여야 한다.</p>
<ul>
<li>모든 실수값 $$x$$에 대해 $$f(x) &gt;= 0$$</li>
<li><img src="https://velog.velcdn.com/images/kim-youngjae/post/48a3c3e3-8f94-4851-ab0a-a71b2205760c/image.png" alt=""></li>
</ul>
<h2 id="정규분포">정규분포</h2>
<ul>
<li><p>평균이 $\mu$이고, 표준편차가 $\sigma$인 $x$의 확률 밀도 함수</p>
</li>
<li><p>표준편차가 클 경우 퍼져보이는 그래프가 나타난다.</p>
</li>
<li><p>정규분포는 2개의 매개 변수 평균 $\mu$ 과 표준편차 $\sigma$ 에 대해 모양이 결정되고, 이때의 분포를 $N(\mu,\sigma^{2})$로 표기한다. 특히, 평균이 0이고 표준편차가 1인 정규분포 $N(0,1)$을 표준 정규 분포(standard normal distribution)라고 한다.</p>
</li>
<li><p>정규 분포 밀도 함수에서 $Z={X-\mu \over \sigma}$를 통해 X(원점수)를 Z(Z점수)로 정규화함으로써 <u>평균이 0, 표준편차가 1인 표준정규분포를 얻을 수 있다.</u></p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/kim-youngjae/post/5d5f61e5-f6c7-4dd0-bb8a-7993ccf4ba3a/image.png" alt=""></p>
<blockquote>
<p> 붉은 색: 표준정규분포 <u>좌우가 대칭</u></p>
</blockquote>
<blockquote>
<p>왜도</p>
</blockquote>
<ul>
<li>$m &gt; 0$ : 오른쪽으로 긴 꼬리를 갖는 분포 (위 녹색 분포)</li>
<li>$m = 0$ : 좌우 대칭인 분포</li>
<li>$m &lt; 0$ : 왼쪽으로 긴 꼬리를 갖는 분포</li>
</ul>
<blockquote>
<p>첨도</p>
</blockquote>
<ul>
<li>$m &gt; 0 $ : 표준 정규 분포 보다 더 뾰족함 위 파란 분포</li>
<li>$m = 0 $ : 표준 정규 분포와 유사함</li>
<li>$m &lt; 0 $ : 표준 정규 분포보다 덜 뾰족함 (위 노란색 분포)</li>
</ul>
<h2 id="지수분포">지수분포</h2>
<ul>
<li><p>어떤 사건이 발생할 때까지 경과 시간에 대한 연속 확률 분포</p>
</li>
<li><p>ex) 콜센터에 전화가 걸려올 때까지의 시간, 전자레인지의 수명시간</p>
</li>
<li><p><img src="https://velog.velcdn.com/images/kim-youngjae/post/64973373-5b1a-4971-9d0d-92e1a12480f8/image.png" alt=""></p>
</li>
</ul>
<h2 id="t-분포">t-분포</h2>
<ul>
<li><p>$\bar x$와 관련</p>
</li>
<li><p>표준정규분포와 같이 평균이 0을 중심으로 좌우가 동일한 분포를 따름
  하지만 정규분포보다 더 퍼져있고 자유도가 커질수록 정규분포에 가까워 진다.</p>
</li>
</ul>
<h2 id="x2-분포">$X^2$-분포</h2>
<ul>
<li><p><u>모평균과 모분산이 알려지지 않은</u> 모집단의 모분산에 대한 가설 검정에 사용되는 분포</p>
</li>
<li><p><img src="https://velog.velcdn.com/images/kim-youngjae/post/6e093caa-1930-4f8c-aa93-7b2cc52f97e1/image.png" alt=""></p>
</li>
</ul>
<h2 id="f-분포">F-분포</h2>
<ul>
<li>두 집단간 <u>분산의</u> 동일성 검정에 사용되는 검정 통계량의 분포</li>
</ul>
<blockquote>
<p>사진 출처: 위키백과</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[통계 분석의 이해]]></title>
            <link>https://velog.io/@kim-youngjae/%ED%86%B5%EA%B3%84-%EB%B6%84%EC%84%9D%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@kim-youngjae/%ED%86%B5%EA%B3%84-%EB%B6%84%EC%84%9D%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Mon, 25 Jul 2022 12:04:23 GMT</pubDate>
            <description><![CDATA[<h1 id="통계-자료-획득-방법">통계 자료 획득 방법</h1>
<h2 id="1-전수-조사">1. 전수 조사</h2>
<ul>
<li>대상 집단 모두를 조사하는데 많은 비용과 시간이 소요</li>
<li>특별한 경우를 제외하고는 사용하지 않는다</li>
</ul>
<br/>

<h2 id="2-표본조사">2. 표본조사</h2>
<ul>
<li>모집단에서 샘플을 추출하여 진행하는 조사</li>
<li>모집단: 조사하고자 하는 대상 집단 전체</li>
<li>원소: 모집단을 구성하는 하나하나의 개체</li>
<li>표본: 조사하기위해 추출한 모집단의 일부 원소</li>
<li><code>모수</code>: 표본 관측에 의해 구하고자 하는 모집단에 대한 정보</li>
</ul>
<blockquote>
<p>통계학을 모수를 찾아나가는 과정이라고도 한다.</p>
</blockquote>
<h2 id="3-표본-추출-방법4가지">3. 표본 추출 방법(4가지)</h2>
<h3 id="단순-랜덤-추출법">단순 랜덤 추출법</h3>
<ul>
<li>각 샘플에 번호를 부여해 임의의 n개를 추출하는 방법(비복원, 복원 추출)<h3 id="계통-추출법">계통 추출법</h3>
</li>
<li>번호를 부여한 샘플을 나열해 놓은 뒤 k개씩 구간을 띄워가며 n개의 표본을 선택하는 방법.<h3 id="집락-추출법군집-추출법">집락 추출법(군집 추출법)</h3>
</li>
<li>군집으로 구분하고 군집별로 단순 랜덤 추출법을 수행하는 방법.<h3 id="층화-추출법">층화 추출법</h3>
</li>
<li>이질적인 원소들로 구성된 모집단에서 각 계층을 고루 대표할 수 있도록 표본을 추출하는 방법</li>
<li>유사한 원소끼리 몇 개의 층을 나누어 각 층에서 랜덤 추출하는 방법.</li>
</ul>
<hr>
<h1 id="측정">측정</h1>
<table>
<thead>
<tr>
<th align="left">척도</th>
<th align="left">가나</th>
<th align="left">다라</th>
</tr>
</thead>
<tbody><tr>
<td align="left">명목척도</td>
<td align="left">측정대상이 어느 집단에 속하는지 분류할 때 사용(성별, 출생지 구분)</td>
<td align="left"><strong>질적척도</strong>(범주형 자료, 숫자들의 크기 차이가 계산이 되지 않는 척도</td>
</tr>
<tr>
<td align="left">순서척도</td>
<td align="left">측정 대상의 서열관계를 관측하는 척도(만족도, 선호도, 학년, 신용등급)</td>
<td align="left"></td>
</tr>
<tr>
<td align="left"><strong>구간척도</strong></td>
<td align="left">측정 대상이 갖고 있는 <u>속성의 양을</u> 측정하는 것으로 구간이나 구간 사이의 <u>간격이 의미가 있는</u> 자료 (<u>온도</u>,지수)</td>
<td align="left"><strong>양적척도</strong>(수치형 자료, 숫자들의 크기 차이를 계산할 수 있는 척도)</td>
</tr>
<tr>
<td align="left"><strong>비율척도</strong></td>
<td align="left">간격(차이)에 대한 비율이 의미를 가지는 자료, <u>절대적 기준인 0이 존재</u>하고 <u>사칙연산이 가능</u>하며 제일 많은 정보를 가지는 척도(<u>무게</u>, 나이, 시간, 거리)</td>
<td align="left"></td>
</tr>
</tbody></table>
<blockquote>
<p>구간 척도, 비율 척도에 대한 비교가 시험에 나오는 단골 비교 대상!!!
명목척도, 순서척도는 비교는 가능, 서로 계산은 불가능
구간척도, 비율척도는 비교도 가능하고 값들의 계산도 가능</p>
</blockquote>
<hr>
<h1 id="통계-분석">통계 분석</h1>
<h2 id="기술-통계">기술 통계</h2>
<ul>
<li>sample에 대한 특성인 평균, 표준편차, 중위수, 최빈값, 그래프, 왜도, 첨도 등을 구하는 것</li>
</ul>
<h2 id="통계적-추론추측-통계">통계적 추론(추측 통계)</h2>
<ol>
<li>모수 추정</li>
</ol>
<ul>
<li>표본집단으로부터 <strong>모집단의 특성인 모수(평균, 분산 등)를 분석</strong>하여 모집단을 추론</li>
</ul>
<ol start="2">
<li>가설검정</li>
</ol>
<ul>
<li>대상 집단에 대해 특정한 가설을 설정</li>
<li>옳은지 그른지에 대한 채택 여부 결정</li>
</ul>
<ol start="3">
<li>예측</li>
</ol>
<ul>
<li>미래의 불확실성을 해결해 효율적인 의사결정을 위해 활용</li>
<li>시계열분석, 회귀분석 등)</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>