<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>castle.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 11 Mar 2024 13:18:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>castle.log</title>
            <url>https://velog.velcdn.com/images/hosung-222/profile/862fabf3-7849-4889-8289-8a4e559760e9/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. castle.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hosung-222" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[카프카(Kafka)가 꼭 필요한 이유]]></title>
            <link>https://velog.io/@hosung-222/%EC%B9%B4%ED%94%84%EC%B9%B4Kafka%EA%B0%80-%EA%BC%AD-%ED%95%84%EC%9A%94%ED%95%9C-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@hosung-222/%EC%B9%B4%ED%94%84%EC%B9%B4Kafka%EA%B0%80-%EA%BC%AD-%ED%95%84%EC%9A%94%ED%95%9C-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Mon, 11 Mar 2024 13:18:33 GMT</pubDate>
            <description><![CDATA[<p>누구나 모놀로식 아키텍처로 개발을 해온 사람이라면 피해갈 수 없는 문제가 있다.
바로 커플링(Coupling)이다. 무수히 많은 로직들이 엉켜 결국 유지보수하는데 많은 시간을 소비해본 경험이 있을 것이다.</p>
<p>카프카를 이용해 DDD패턴으로 설계하면 이와 같은 문제를 해결할 수 있다. </p>
<h2 id="카프카">카프카</h2>
<p><img src="https://velog.velcdn.com/images/hosung-222/post/0bfccfed-021a-4649-b8be-cdb8bd4501af/image.png" alt=""></p>
<p>카프카를 사용하는 주된 목적은 커플링을 줄이기위해 발신자와 수신자를 서로 의존하지 않는 상태로 서비스 아키텍처를 가져가기 위해 사용된다. </p>
<p>기존에는 하나의 소스 시스템에 여러 타겟 시스템이 붙어 수신해야했다. 이 때문에 타겟 시스템별 데이터 수신 차이가 발생했다. 이를 극복하기 위해 소스 시스템을 늘리면 구조가 복잡해지고 각 시스템들 사이의 데이터 포맷과 처리방식이 달라 확장 및 소비에 어려움이 있었다.
이런 문제를 깔끔하게 해결해주는 것이 바로 카프카이다. </p>
<p>카프카는 메시지 큐를 사용하는데 그 중에서도 Pub/Sub 방식으로 토픽이라 부르는 하나의 메시지 통로를 사용하여 메시지를 &#39;발행&#39; 하고 정책에 의해 구독중엔 메시지를 &#39;소비&#39;한다.</p>
<p>따라서 각각의 다른 기능들에 의존하지 않게되고 자신의 정책에 따라 필요한 메시지만 수신해 처리하고 다른 처리가 필요한 경우 다시 이벤트를 새로 발행하기만 하면된다.</p>
<h3 id="카프카의-특징">카프카의 특징</h3>
<ul>
<li>메시지를 파일 시스템으로 저장해 메시지 유실 우려가 적다.</li>
<li>소비자가 정책에 의해 처리할 수 있는 메시지만 가져온다.</li>
<li>대량의 데이터를 높은 처리량과 낮은 지연 시간으로 처리할 수 있는 기능을 제공한다.</li>
</ul>
<h3 id="카프카의-구성">카프카의 구성</h3>
<p>카프카는 필수로 주키퍼(zookeeper)와 같은 분산 애플리케이션 코디네이터가 필요하다. 카프카를 클러스터로 구성할 때 각각의 서버를 브로커(Broker)라고 하는데 이러한 코디네이터가 브로커들을 관리한다. 브로커들은 각각 토픽 파티션을 가지며 항상 3개 이상의 브로커로 운영된다.</p>
<p>카프카는 이벤트를 생성하는 생성자(Producer) 이벤트를 소비하는 소비자(Consumer)가 있다.
이 중 소비자(Consumer)는 여러 소비자들이 하나로 묶여 소비자 그룹(Consumer Group)을 형성한다. 
이러한 소비자 그룹이 메시지를 소비할 때 Pub된 메시지를 어디까지 소비했는지에 대한 위치를 Offset이라고 한다. 만약 소비자 서버가 죽었다면 Offset을 통해 서버가 다시 살아났을때 다음 메시지를 수신할 곳을 체크할 수 있다.</p>
<p>카프카에서 메시지가 이동하는 통로는 Topic이라고 한다. 하나의 카프카에서 여러개의 메시지가 발행되고 소비될 때 이러한 Topic을 이용하여 원하는 메시지를 찾을 수 있다. 이러한 토픽을 분산처리하는 단위인 Partition이 있다. Partition을 이용하면 하나의 토픽에 병렬처리를 할 수 있는데 한번 Partition을 늘리면 줄일 수 없기 때문에 파티션을 늘릴때는 신중히 늘려야 한다.
<img src="https://velog.velcdn.com/images/hosung-222/post/11c575d8-7c4d-4143-9893-890297593443/image.png" alt=""></p>
<p>또한 카프카는 Key값을 설정하지 않는다면 메시지를 라운드-로빈(Round-robin) 방식으로 Partition들에게 분배하기 때문에 순서가 보장되야 하는 메시지는 꼭 Key값을 지정해 주어야 한다. </p>
<blockquote>
<p>Partition 0, Partition1 이 있다고 가정해보자 주문 이벤트가 발생한 후 주문 취소 이벤트가 발생했다. 만약 Key값을 지정하지 않는다면 두 이벤트가 다른 Partition으로 들어가 처리 순서가 뒤바뀔 수 있다. 즉, 주문 취소가 먼저 처리될 수 있다는 뜻이다.</p>
</blockquote>
<h3 id="카프카-스케일링">카프카 스케일링</h3>
<p>카프카를 스케일링할 때 권고사항은 다음과 같다.</p>
<h4 id="1-모든-브로커-리소스-사용률이-현저히-높으면-새로운-브로커를-추가한다">1. 모든 브로커 리소스 사용률이 현저히 높으면 새로운 브로커를 추가한다.</h4>
<h4 id="2-메시지의-병목현상이-발생할-경우-해당-토픽의-파티션을-증가한다">2. 메시지의 병목현상이 발생할 경우 해당 토픽의 파티션을 증가한다.</h4>
<ul>
<li>파티션이 많을 수록 파일 핸들러가 증가 → 적절하게 사용해야한다.</li>
<li>파티션은 증가되면 줄이는 방법이 없다.</li>
<li>컨슈머 그룹내의 컨슈머 개수와 동등한 파티션 개수 설정 권고된다.</li>
</ul>
<h4 id="3-message-lagging이-높을-경우-처리하는-컨슈머를-증가한다">3. Message Lagging이 높을 경우 처리하는 컨슈머를 증가한다.</h4>
<ul>
<li>컨슈머 그룹별로 그룹 코디네이터가 각 컨슈머 그룹을 관리한다.</li>
<li>컨슈머 수가 변경되면 그룹내에서 소유권 이관작업이 발생 → 리밸런싱 된다.</li>
<li>컨슈머는 폴링(poling)하거나 커밋할 때 Heartbeat 메시지를 그룹 코디네이터에게 전달한다.</li>
<li>그룹 코디네이터가 일정기간 컨슈머의 하트비트를 받지 못하면 해당 컨슈머를 장애로 판단하고 리밸런싱 수행한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security (5) 로그인 검증 로직]]></title>
            <link>https://velog.io/@hosung-222/Spring-Security-5-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B2%80%EC%A6%9D-%EB%A1%9C%EC%A7%81</link>
            <guid>https://velog.io/@hosung-222/Spring-Security-5-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B2%80%EC%A6%9D-%EB%A1%9C%EC%A7%81</guid>
            <pubDate>Thu, 28 Dec 2023 15:19:42 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hosung-222/post/9434118f-6981-4c4d-8af9-b5f7e900aa40/image.png" alt=""></p>
<p>Security Config에 설정한대로 LoginForm을 통해 날라오는 로그인 요청에 대해 Security가 검증을 하게된다.</p>
<p><code>UserDetailsService</code>와 <code>UserDetails</code>을 구현해 주어야 DB에 저장된 회원 정보로 부터 아이디 검증을 진행할 수 있다.</p>
<h2 id="userdetailsservice">UserDetailsService</h2>
<hr>
<blockquote>
<p>Spring Security에서 유저의 정보를 가져오는 인터페이스다.</p>
</blockquote>
<pre><code class="language-java">@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements **UserDetailsService** {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User userData = userRepository.findByUsername(username);

        if (userData != null) {
            return new CustomUserDetails(userData);
        }
        return null;
    }
}</code></pre>
<ul>
<li>DB에서 유저가 저장되어있는 테이블에 접근하기 위해 <code>UserRepository</code>를 주입해준다.</li>
<li>커스텀 서비스를 만들어 <code>UserDetailsService</code>를 implements해준 후 필수로 구현해야 하는 <code>loadUserByUsername</code> 메서드 를 구현해준다.<ul>
<li>userData가 null이 아니면 생성자를 통해 CustomUserDetails에 user객체를 담아서 보내준다.</li>
</ul>
</li>
</ul>
<h2 id="userdetails">UserDetails</h2>
<hr>
<blockquote>
<p>Spring Security에서 사용자 정보를 담는 인터페이스다.</p>
</blockquote>
<p>데이터베이스로 부터 특정한 userName에 대한 데이터를 가져오고 해당 데이터를 userDetails 클래스에 넣어서 SecurityConfig에 전달해 주면 SecurityConfig에서 userName에 대한 password, role 들을 검증하고 완료시 스프링 세션에 저장해서 사용자 접근 허용해준다.</p>
<p>→ DTO에 해당하는 역할을 한다.</p>
<pre><code class="language-java">public class CustomUserDetails implements **UserDetails** {

    private User user;

    public CustomUserDetails(User user){
        this.user = user;
    }

    // 사용자의 특정한 권한에 대해 return 해주는 메서드 (ex role 값)
    @Override
    public Collection&lt;? extends GrantedAuthority&gt; getAuthorities() {

        Collection&lt;GrantedAuthority&gt; collection = new ArrayList&lt;&gt;();
        collection.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return user.getUserRole().getValue();
            }
        });
        return collection;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security (4) 회원 가입]]></title>
            <link>https://velog.io/@hosung-222/Spring-Security-4-%ED%9A%8C%EC%9B%90-%EA%B0%80%EC%9E%85</link>
            <guid>https://velog.io/@hosung-222/Spring-Security-4-%ED%9A%8C%EC%9B%90-%EA%B0%80%EC%9E%85</guid>
            <pubDate>Wed, 27 Dec 2023 14:57:18 GMT</pubDate>
            <description><![CDATA[<h2 id="회원가입">회원가입</h2>
<hr>
<p>로그인 시 회원 정보를 통해 인증, 인가 작업을 진행하기 위해 사용자로 부터 회원가입을 진행한 후 DB에 회원 정보를 저장한다.</p>
<h2 id="회원가입-로직">회원가입 로직</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/hosung-222/post/85f5fdfd-d311-402d-aa28-a5f5cde65a4e/image.png" alt=""></p>
<ol>
<li>회원가입 요청을 Controller가 받는다.</li>
<li>회원가입 로직 Service를 호출한다.<ul>
<li>DB에 이미 동일한 회원이 존재하는지 검증한다.(existBy)</li>
</ul>
</li>
<li>DTO의 유저 데이터를 엔티티에 매핑한다.<ul>
<li>비밀번호는 bCryptPasswordEncoder가 제공하는 encode메서드를 이용해서 암호화해서 매핑한다</li>
</ul>
</li>
<li>레포지토리의 save를 이용해 저장한다.</li>
</ol>
<blockquote>
<p>SecurityConfig class 설정 부분에 permitAll() 부분에 회원가입 요청도 추가해주어 로그인하지 않은 사용자도 접근을 허용해 주어야 한다.</p>
</blockquote>
<h2 id="회원-중복-검증-처리-로직">회원 중복 검증, 처리 로직</h2>
<hr>
<p>중복 가입이 발생하는 상황을 방지하기 위해 백엔드단에서 반드시 중복을 검증하고 처리하는 로직을 작성해야한다.</p>
<h3 id="중복-예방">중복 예방</h3>
<p><code>@Column(unique = true)</code>를 이용해 해당 값이 유일할 수 있도록 설정하기.</p>
<h3 id="중복-검증">중복 검증</h3>
<p>JPA의 <code>existsBy~</code> 를 커스텀해서 사용하기</p>
<ul>
<li>존재하는지 <code>boolean</code> 값 으로 retrun된다.</li>
</ul>
<h3 id="프론트에서-중복-검증">프론트에서 중복 검증</h3>
<p><code>httpXMLRequest</code>를 통해 백엔드에 구현해둔 API에 이미 존재하는지 검증하는 로직이 필요하다.</p>
<h3 id="가입-관련-문자-정규식-처리">가입 관련 문자 정규식 처리</h3>
<ul>
<li>아이디 자리 수</li>
<li>아이디의 특수문자 포함 여부</li>
<li>admin과 같은 아이디 사용 불가</li>
<li>비밀번호 자리 수</li>
<li>비밀 번호 특수문자 포함 여부</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security (3) BCrypt 암호화 메소드]]></title>
            <link>https://velog.io/@hosung-222/Spring-Security-3-BCrypt-%EC%95%94%ED%98%B8%ED%99%94-%EB%A9%94%EC%86%8C%EB%93%9C</link>
            <guid>https://velog.io/@hosung-222/Spring-Security-3-BCrypt-%EC%95%94%ED%98%B8%ED%99%94-%EB%A9%94%EC%86%8C%EB%93%9C</guid>
            <pubDate>Wed, 27 Dec 2023 13:04:48 GMT</pubDate>
            <description><![CDATA[<h2 id="시큐리티-암호화">시큐리티 암호화</h2>
<hr>
<p>로그인을 진행하면 ID와 Password를 시큐리티에서 받아 검증을 하는데 이때 비밀번호는 단방향 해시 암호화를 진행하여 저장되어 있는 비밀번호와 대조한다.</p>
<p>→ 회원가입시 비밀번호에 대해서 암호화를 진행하여 저장해야 한다.</p>
<h3 id="bcrypt-password-encoder">Bcrypt Password Encoder</h3>
<blockquote>
<p>Spring Security 프레임워크는 암호화를 위해 Bcrypt Password Encoder 클래스를 제공한다.</p>
</blockquote>
<ul>
<li>Bcrypt 해싱함수를 사용해서 Password를 인코딩해주는 메서드와 사용자의 의해 제출된 Password와 저장소에 저장되어 있는 Password의 일치 여부를 확인해주는 메서드를 제공한다.</li>
<li>Bcrypt Password Encoder를 Return 하는 메서드를 만들어 @Bean 으로 등록하여 사용하면 된다.</li>
</ul>
<h3 id="단방향-해시-암호화">단방향 해시 암호화</h3>
<ol>
<li><strong>양방향</strong> : 데이터를 암호화하고 그것을 다시 원본 데이터로 되돌릴 수 있는 알고리즘 사용<ol>
<li><strong>대칭키</strong> : 암호화와 복호화에 동일한 키를 사용(동일한 키를 가진 두 사람 사이에서는 통신이 가능)</li>
<li><strong>비대칭키</strong> : 공개키와 개인키를 사용(공개키는 누구나 사용할 수 있지만, 개인키는 자신만이 가지고 있어야 해독)</li>
</ol>
</li>
<li><strong>단방향</strong> : (암호화된 값을 다시 원본 데이터로 역으로 되돌릴 수 없는 방식)<ol>
<li><strong>해시</strong> : 입력값을 특정한 길이의 고정된 값으로 변환시키는 알고리즘(원본 값을 알 수 없다)</li>
</ol>
</li>
</ol>
<h2 id="security-config-암호화-bean-추가">Security Config 암호화 Bean 추가</h2>
<hr>
<pre><code class="language-java">@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {

    return new BCryptPasswordEncoder(); // BCryptPasswordEncoder return
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security (2) 커스텀 로그인 작업]]></title>
            <link>https://velog.io/@hosung-222/Spring-Security-2-%EC%BB%A4%EC%8A%A4%ED%85%80-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%9E%91%EC%97%85</link>
            <guid>https://velog.io/@hosung-222/Spring-Security-2-%EC%BB%A4%EC%8A%A4%ED%85%80-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%9E%91%EC%97%85</guid>
            <pubDate>Wed, 27 Dec 2023 07:01:00 GMT</pubDate>
            <description><![CDATA[<h2 id="spring-configuration-class-작성-후"><strong>Spring Configuration Class 작성 후</strong></h2>
<hr>
<p>스프링 시큐리티 Config 클래스를 생성하여 인가 작업을 설정한 후에는 특정 경로에 대해 접근 했을 때 권한이 없는경우 자동으로 로그인 페이지로 리다이렉션 되지 않고 오류가 발생한다.</p>
<h2 id="커스텀-로그인-설정하기">커스텀 로그인 설정하기</h2>
<hr>
<p>Config 클래스를 설정하면 로그인 페이지 설정 또한 작업해주어야 한다.</p>
<pre><code class="language-java">@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{

        http
                .authorizeHttpRequests((auth) -&gt; auth
                        .requestMatchers(&quot;/&quot;, &quot;/login&quot;, &quot;/loginProc&quot;).permitAll()
                        .requestMatchers(&quot;/admin&quot;).hasRole(&quot;ADMIN&quot;)
                        .requestMatchers(&quot;/my/**&quot;).hasAnyRole(&quot;ADMIN&quot;, &quot;USER&quot;)
                        .anyRequest().authenticated()
                );

                //새로 추가된 코드
        http
                .formLogin((auth) -&gt; auth.loginPage(&quot;/login&quot;) // -- 1
                        .loginProcessingUrl(&quot;/loginProc&quot;) //  -- 2
                        .permitAll()                     // -- 3
                );

        http
                .csrf((auth) -&gt; auth.disable());      // -- 4


        return http.build();
    }
}</code></pre>
<ol>
<li><code>loginPage(&quot;/주소&quot;)</code> : 로그인 페이지가 어디있는지 주소 설정(로그인 권한이 없을 때 자동으로 해당 로그인 페이지로 시큐리티가 리다이렉션 해준다)</li>
<li><code>loginProcessingUrl(&quot;/주소&quot;)</code> : 로그인한 정보가 해당 주소로 넘겨지면 받아서 로그인 처리를 진행한다.</li>
<li><code>permitAll()</code> : 해당 경로를 모든 접근에 대해 허용</li>
<li><code>csrf</code> : 시큐리티의 위변조 방지 설정(Post 요청시 csrf Token도 보내주어야 로그인 진행된다.) → 개발 환경에서 비활성화 시키기 용</li>
</ol>
<blockquote>
<p>스프링부트 어플리케이션을 실행하면 자동으로 생성된 시큐리티 패스워드(security password) 값을 사용하여 로그인 가능하다.</p>
</blockquote>
<p>Id : user</p>
<p>Password : 자동 생성된 값</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security (1) 인가 작업 ]]></title>
            <link>https://velog.io/@hosung-222/Spring-Security-1-%EC%9D%B8%EA%B0%80-%EC%9E%91%EC%97%85</link>
            <guid>https://velog.io/@hosung-222/Spring-Security-1-%EC%9D%B8%EA%B0%80-%EC%9E%91%EC%97%85</guid>
            <pubDate>Thu, 14 Dec 2023 12:41:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hosung-222/post/8995f46b-d359-465b-abc9-57216441bf98/image.png" alt=""></p>
<h2 id="들어가며">들어가며</h2>
<p>스프링 시큐리티를 사용하며 단순히 코드를 가져오거나 정확히 어떤식으로 동작하는지 잘 모르고 사용하는 경우가 있었다. 시큐리티에 대해 하나씩 정리하는 용도로 작성하게 되었다.</p>
<ul>
<li>본 코드는 스프링부트 3.1.X~ 이상 버전으로 작성되었다.</li>
</ul>
<p>먼저 스프링 어플리케이션을 만들고 실행한다면 구조는 아래 사진과 같다.
<img src="https://velog.velcdn.com/images/hosung-222/post/17e3d3a8-d498-46f9-b212-846ed5dae1fe/image.png" alt=""></p>
<p>클라이언트가 요청을 보내면 해당 요청이 SpringBoot 어플리케이션에 도달하기 전에 먼저 Servlet Container라는 Tomcat 컨테이너를 지나서 요청이 SpringBoot에 전달된다.</p>
<p>여기서 Servlet Container는 여러개의 필터를 가지는데 요청은 이 필터들을 통과하며 들어온다.</p>
<h3 id="인가-작업">인가 작업</h3>
<p>이때 Spring Security 의존성을 추가하면 시큐리티 필터가 생기고 사용자의 요청을 가로채 아래와 같은 검증을 수행한다.</p>
<ol>
<li>요청 경로의 접근은 누구에게 열려있는지</li>
<li>로그인이 완료된 사용자인지</li>
<li>해당하는 역할을 가지고 있는지</li>
</ol>
<p>위와 같은 작업을 <strong>&quot;인가&quot;</strong> 작업이라고 한다.</p>
<h2 id="spring-configuration">Spring Configuration</h2>
<blockquote>
<p>인가 작업을 설정하는 Class</p>
</blockquote>
<p>Spring Configuration 클래스를 통해서 특정 경로 요청에 대해 동작을 할지말지 설정할 수 있다.</p>
<ul>
<li>기본적인 인가 작업은 모든 경로에 대해서 로그인을 하도록 되어있다. (처음 스프링 시큐리티 의존성을 추가하면 모든 경로에 대해 권한이 없어 로그인 화면이 나온다.)</li>
</ul>
<h3 id="클래스-파일-생성">클래스 파일 생성</h3>
<p><img src="https://velog.velcdn.com/images/hosung-222/post/102b5fbe-a00b-43d6-bff3-fa4cadbf8ecf/image.png" alt="">
위 사진과 같이 SecurityConfig.class 파일을 생성한다.</p>
<ul>
<li>@Configuration : 스프링 부트에게 설정파일임을 지정 해준다.</li>
<li>@EnableWebSecurity : 웹 보안 설정을 활성화 한다.(스프링 시큐리티 필터 체인이 동작하여 요청을 인가하고 인증한다)</li>
</ul>
<pre><code class="language-java">@Configuration 
@EnableWebSecurity 
public class SecurityConfig {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        http.authorizeHttpRequests((auth) -&gt; auth
                // 특정 경로에 대해 모든 사람 접근 허용(permitAll)
                .requestMatchers(&quot;/&quot;, &quot;/join&quot;, &quot;/login&quot;).permitAll()
                // 특정 경로에 대해 ADMIN 역할을 가진 사람 접근 허용(hasRole)
                .requestMatchers(&quot;/admin&quot;).hasRole(&quot;ADMIN&quot;)
                // 와일드 카드(**)를 사용하여 여러 id 값의 대한 경로들에 대해 여러 역할 허용(hasAnyRole)
                .requestMatchers(&quot;/mypage/**&quot;).hasAnyRole(&quot;ADMIN&quot;, &quot;USER&quot;)
                //위에서 처리하지 못한 모든 다른 요청에 대해 설정
                .anyRequest().authenticated()
        );
        return http.build(); //최종값은 http의 빌더 타입
    }
}</code></pre>
<p><em>해당 설정은 상단부터 동작이 되기 때문세 순서에 유의하자. (상단에서 먼저 모든 경로를 열면 아래 설정은 적용이 되지 않는다)</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[우아한 테크코스 6기] 프리코스 1주차 - 숫자 야구 게임]]></title>
            <link>https://velog.io/@hosung-222/%EC%9A%B0%EC%95%84%ED%95%9C-%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-6%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EC%88%AB%EC%9E%90-%EC%95%BC%EA%B5%AC-%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@hosung-222/%EC%9A%B0%EC%95%84%ED%95%9C-%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-6%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EC%88%AB%EC%9E%90-%EC%95%BC%EA%B5%AC-%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Tue, 07 Nov 2023 14:49:14 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hosung-222/post/dd7eb583-b19b-4a05-8f7e-c23557810160/image.png" alt=""></p>
<h2 id="야구-게임">야구 게임</h2>
<hr>
<p>프리코스 1주차 과제는 야구게임이였다.
간단히 설명하자면 1부터 9까지 서로 다른 수로 이루어진 3자리 수를 맞추는 게임이다.</p>
<ul>
<li>같은 자리에 같은 숫자라면 : + 1 스트라이크</li>
<li>다른 자리에 같은 숫자라면 : + 1 볼</li>
<li>만약 같은 숫자가 아무것도 없다면 : 낫싱</li>
</ul>
<p>문제는 나름 간단했다. 우선 먼저 구현을 목표로 열심히 코딩을 하였더니 테스트 코드를 통과하는데 두시간 정도 걸렸다. 
깃을 다루는 부분도 이미 깃을 통한 협업을 통해 프로젝트를 진행해보았기에 크게 문제가 되지 않았다. (깃을 잘 다루지 못하더라도 설명이 잘되어 있으니 걱정할 피룡가 없다.)</p>
<p>문제는 아래에 있었다.</p>
<h3 id="클린코드-작성">클린코드 작성</h3>
<hr>
<p>내 문제는 클린 코드였다... 
지금까지 코딩테스트 문제를 연습하던, 프로젝트를 하던 클린코드에 대해 큰 신경을 쓰지 않았다. 어느정도 학부생동안 배워왔던 &quot;객체지향 설계&quot; 라는 개념을 가지고 흉내내 왔을 뿐 정말 클린코드에 맞춰 코드를 작성해본적은 처음이였다. </p>
<h4 id="역할과-책임">역할과 책임?</h4>
<p>프리코스를 위해 이미 남들 다 읽어봤다는 &quot;객체지향의 사실과 오해&quot;를 읽었다. 읽은 후 느낀점은 내가 왜 이걸 프리코스 전에 읽지 않았는가 하는 후회였다. 정말 코드를 보는 시야가 조금 달라졌던 것 같다. 책의 내용을 완벽하게 숙지하지 못했지만 익힌 내용과 사람들이 공유해준 클린코드 작성법을 찾아보며 최대한 클린 코드로 코드를 리팩토링 하였다.</p>
<h3 id="다시-돌아보니">다시 돌아보니...</h3>
<hr>
<p>3주차에 돌입한 지금 보니 이때 코드도 정말 엉망이다@@@!!
객체 지향적이기 보다는 구조지향적 프로그래밍으로 구현이 된 것 같다...물론 이것도 1주차 이전의 나의 구현보다는 훨씬 성장한 거지만 지금 이 코드를 보자마자 단점들이 보이는 걸 보니 3주차가 끝나가는 지금 더 성장한걸 느낀다. 
(<del><em>물론 3주차에도 잘하는건 아니다 ㅜㅜ</em></del>)</p>
<p>학업도 밀려있어 지금 당장 1주차 코드를 수정하지는 못하겠지만.... 4주차가 끝난뒤 꼭 리팩토링을 마저 계속 할 것이다.</p>
<p><img src="https://velog.velcdn.com/images/hosung-222/post/d4b48430-16f2-4796-ae1f-300c73192adc/image.png" alt=""></p>
<h3 id="느낀점">느낀점</h3>
<hr>
<p>나름 프로젝트도 진행하고 성취를 이루면서 기고만장해있던 내 자신을 돌아볼 수 있는 계기였다. 아직 정말 자바에 부족한 점이 많고 배울 것이 많다는 것을 느꼈다. 또 프리코스 디스코드 방에서 공유되는 정보와 열정을 통해 내가 더 열심히 임하고 성장하는 걸 느끼며 개발자에게 좋은 개발 커뮤니티 활동은 큰 이점으로 다가온다는 것을 느낀다. </p>
<p>더 열심히 달려보겠습니다!! 모두 화이팅</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[우아한 테크코스 6기]  백엔드 서류 지원]]></title>
            <link>https://velog.io/@hosung-222/%EC%9A%B0%EC%95%84%ED%95%9C-%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-6%EA%B8%B0-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%9C%EB%A5%98-%EC%A7%80%EC%9B%90</link>
            <guid>https://velog.io/@hosung-222/%EC%9A%B0%EC%95%84%ED%95%9C-%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-6%EA%B8%B0-%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%9C%EB%A5%98-%EC%A7%80%EC%9B%90</guid>
            <pubDate>Tue, 07 Nov 2023 14:25:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hosung-222/post/3133ddf7-77d0-4561-8f29-9b89780f5a38/image.png" alt=""></p>
<h2 id="시작하며">시작하며...</h2>
<hr>
<p>원래 이러한 회고록을 작성해 본적이 없지만 우테코를 진행하며 사람들의 회고록을 보고 도움이 된 것이 커서 나도 나와 누군가에게 도움이 되기 위해 작성 해본다.</p>
<h3 id="일정">일정</h3>
<p><img src="https://velog.velcdn.com/images/hosung-222/post/8b3a1e2d-b568-4393-b35a-47728b23a41c/image.png" alt=""></p>
<h3 id="지원-동기">지원 동기</h3>
<p>나의 지원동기는 당연히 우테코라면 누구나 꿈꾸는 배움터기에 당연히 지원하고 싶었지만, 확실하게 지원하게 된 계기는 프리코스가 열렸다는 점에서이다. 예전에는 1차 합격 후 프리코스가 진행 되었지만 이제는 지원만 하면 프리코스를 진행할 수 있었다. 
4주간 어느정도 체험해볼 수 있는 기회를 마다할 수 없었기에 열심히 서류를 작성해서 제출을 했다. </p>
<hr>
<h3 id="서류작성">서류작성</h3>
<p>서류 작성을 조금 늦게 시작했다 ㅜㅜ 면접을 따로 보지 않기에 서류가 정말 중요한데 따로 첨삭을 받거나 많이 수정할 시간이 부족했다. 서류 질문은 거의 같은 거로 보아 미리 준비를 해두는 게 좋을 것 같다.</p>
<h4 id="1번-문항--효과적인-학습-방식과-경험">1번 문항 : 효과적인 학습 방식과 경험</h4>
<p>이 문항에 대해서 내가 고등학교 시절부터 느껴왔던 공부방법의 문제점과 대학을 진학 후 개발 공부를 하며 자연스럽게 깨달았던 나의 학습 방법에 대해 기술 하였다. </p>
<h4 id="2번-문항--성장-중-겪은-실패와-극복">2번 문항 : 성장 중 겪은 실패와 극복</h4>
<p>23년 여름방학 사이드 프로젝트를 경험하며 겪은 여러 실패들과 극복 방법에 대해 기술 했다. 평소 문제를 겪고 극복하는 과정에 있어서도 잘 기술해 두어야지 이런 문항에 잘 녹여낼 수 있을 것 같다. </p>
<h4 id="3번-문항--오랜-시간-몰입했던-경험-그리고-도전">3번 문항 : 오랜 시간 몰입했던 경험 그리고 도전</h4>
<p>내가 정말로 좋아했던 취미 생활에 대해 기술 하였다. 해당 취미를 하며 도전했던 부분까지 기술 하였는데 나 같은 경우에 엄청 빨리 불이 붙고 빨리 꺼져서 조금 더 장기적으로 수년 이상 몰입한 경험이 없어 아쉬웠다. </p>
<h4 id="4번-문항--원하는-프로그래머-모습">4번 문항 : 원하는 프로그래머 모습</h4>
<p>이 문항이 오히려 제일 난처했다. 당연히 사회에 헌신하는 개발자 ~이런식으로 적어야 할지 고민이 많았다. 너무 뻔한 내용은 별로일 것 같아 내가 정말 나아가고 싶은 방향성에 대해 내 목표와 함께 적었다.</p>
<hr>
<h3 id="돌아보며">돌아보며</h3>
<p>4주정도 지난 시점에서 회고록을 작성하며 서류 내용을 다시 읽었는데 확실히 아쉬운 점이 많이 보인다. 하지만 무엇보다 중요한 것은 문항별 경험이 제일 아쉬웠다. 조금 더 몰입해보고 도전해보고 그러면서 실패를 겪어보고 극복을 해본 스토리가 탄탄했다면 좋을 것 같다..</p>
]]></description>
        </item>
    </channel>
</rss>