<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>at work</title>
        <link>https://velog.io/</link>
        <description>나만 알아보면 된다는 마음으로 작더라도 조금씩</description>
        <lastBuildDate>Mon, 29 Dec 2025 01:05:10 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>at work</title>
            <url>https://images.velog.io/images/park-nahyun/profile/2f7ab4ca-d3a2-4559-8f6a-373b6696ca07/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. at work. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/park-nahyun" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[OSCP]]></title>
            <link>https://velog.io/@park-nahyun/OSCP</link>
            <guid>https://velog.io/@park-nahyun/OSCP</guid>
            <pubDate>Mon, 29 Dec 2025 01:05:10 GMT</pubDate>
            <description><![CDATA[<ul>
<li>온라인 인증서 상태 프로토콜(OCSP)은 X.509를 이용한 전자서명 인증서의 폐지 상태를 파악하는 데 사용되는 인터넷 프로토콜
인증서 폐기 목록을 대체하기 위해 만들어짐.</li>
<li>공개 키 기반 구조의 인증서 폐기 목록과 관련된 문제들을 검증하기 위한 것</li>
</ul>
<p>출처 : <a href="https://ko.wikipedia.org/wiki/%EC%98%A8%EB%9D%BC%EC%9D%B8_%EC%9D%B8%EC%A6%9D%EC%84%9C_%EC%83%81%ED%83%9C_%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C">https://ko.wikipedia.org/wiki/%EC%98%A8%EB%9D%BC%EC%9D%B8_%EC%9D%B8%EC%A6%9D%EC%84%9C_%EC%83%81%ED%83%9C_%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[dmesg]]></title>
            <link>https://velog.io/@park-nahyun/dmesg</link>
            <guid>https://velog.io/@park-nahyun/dmesg</guid>
            <pubDate>Mon, 29 Dec 2025 00:50:05 GMT</pubDate>
            <description><![CDATA[<p>커널 링(ring) 버퍼를 출력하거나 제어</p>
<ul>
<li>시스템이 부팅할 때마다 로딩되는 시스템 정보의 로그 메시지를 가지고 있다.</li>
<li>리눅스 커널 버전과 gcc 버전, CPU 정보 등 부팅 시의 내용을 포함하여 시스템 정보를 살펴볼 때 유용하다.</li>
</ul>
<p>출처 : <a href="https://terms.naver.com/entry.naver?docId=4125610&amp;cid=59321&amp;categoryId=59321">https://terms.naver.com/entry.naver?docId=4125610&amp;cid=59321&amp;categoryId=59321</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자기 전에 GPT랑 스프링 시큐리티 기초 대화]]></title>
            <link>https://velog.io/@park-nahyun/%EC%9E%90%EA%B8%B0-%EC%A0%84%EC%97%90-GPT%EB%9E%91-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EA%B8%B0%EC%B4%88-%EB%8C%80%ED%99%94</link>
            <guid>https://velog.io/@park-nahyun/%EC%9E%90%EA%B8%B0-%EC%A0%84%EC%97%90-GPT%EB%9E%91-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EA%B8%B0%EC%B4%88-%EB%8C%80%ED%99%94</guid>
            <pubDate>Wed, 19 Mar 2025 15:39:53 GMT</pubDate>
            <description><![CDATA[<p>업무 관련 내용은 편집함.</p>
<p>_
👧🏻 아까 스프링 시큐리티의 인증 방법 물어본 거 생각 나?_</p>
<p>🤖 아마 인증 방식을 고민하면서,</p>
<p><strong>1. 세션 기반 인증
2. JWT 기반 인증
3. OAuth 2.0 또는 소셜 로그인
4. API Key 또는 Basic Auth</strong></p>
<p>이런 옵션 중에서 어떤 게 적절할지 물어봤던 것 같아.
혹시 이 부분 더 정리해줄까? 아니면 다른 방향으로 고민이 생겼어?</p>
<hr>
<p><em>👧🏻 일단 2-1-3-4 순서대로 설명해줄래? 어떤 비즈니스 상황에 쓰는지도. 간략하게 말해줘 더 궁금한건 내가 질문할게.</em></p>
<p>🤖 ㅇㅋ.</p>
<p><strong>2. JWT 기반 인증</strong></p>
<p>✅ 어떤 상황에서?
REST API 기반 MSA, 모바일/웹 클라이언트 분리된 환경
서버에서 세션을 관리하지 않고, 확장성이 필요한 경우</p>
<p>✅ 코드 예시 (Spring Security + JWT)</p>
<pre><code class="language-java">// JWT 토큰 생성 (UserDetailsService를 통해 유저 검증)
public String generateToken(String username) {
    return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1일
            .signWith(SignatureAlgorithm.HS256, secretKey)
            .compact();
}
// JWT 필터 (인증 과정)
public class JwtFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String token = extractToken(request);
        if (token != null &amp;&amp; validateToken(token)) {
            UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(getUsernameFromToken(token), null, getAuthorities(token));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }
}</code></pre>
<p><strong>1. 세션 기반 인증</strong></p>
<p>✅ 어떤 상황에서?
내부 시스템(ERP, 사내 서비스), 상태 관리가 필요할 때
JWT보다 간단한 구현이 필요할 때</p>
<p>✅ 코드 예시 (Spring Security + 세션 로그인)</p>
<pre><code class="language-java">@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -&gt; auth
            .anyRequest().authenticated()
        )
        .formLogin(Customizer.withDefaults()) // 기본 로그인 페이지 활성화
        .sessionManagement(session -&gt; session
            .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) // 세션 유지
        );
    return http.build();
}</code></pre>
<p><strong>3. OAuth 2.0 인증</strong></p>
<p>✅ 어떤 상황에서?
소셜 로그인 (구글, 카카오, 네이버 등)
외부 인증 제공자를 활용할 때 (OAuth 서버를 직접 운영할 수도 있음)</p>
<p>✅ 코드 예시 (Spring Security + OAuth2.0 로그인)</p>
<pre><code class="language-java">@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -&gt; auth
            .anyRequest().authenticated()
        )
        .oauth2Login(Customizer.withDefaults()); // OAuth2 로그인 활성화
    return http.build();
}</code></pre>
<p><strong>4. API Key / Basic Auth</strong></p>
<p>✅ 어떤 상황에서?
외부 시스템 간 연동 (API 호출)
단순한 인증이 필요한 경우</p>
<p>✅ 코드 예시 (Basic Auth)</p>
<pre><code class="language-java">@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -&gt; auth
            .anyRequest().authenticated()
        )
        .httpBasic(Customizer.withDefaults()); // Basic Auth 활성화
    return http.build();
}</code></pre>
<hr>
<p>👧🏻 1. 세션이 뭔데 왜 쓰는데. 2, 3, 4에선 세션 왜 안쓰는데? 장단점.
2. JWT가 뭔데 왜 쓰는데. 1, 3, 4에선 왜 안쓰는데? 장단점</p>
<p>🤖 
*<em>1. 세션(Session)이 뭔데? 왜 쓰는데?
*</em>👉 서버가 사용자의 로그인 상태를 유지하기 위해 사용하는 저장 공간.</p>
<p>로그인하면 서버가 세션을 만들고, 클라이언트(브라우저)에 JSESSIONID라는 쿠키를 줌.
이후 요청할 때 JSESSIONID 쿠키를 보내면, 서버가 해당 세션을 조회해서 로그인 상태를 유지함.</p>
<p><strong>📌 왜 2, 3, 4에서는 세션을 안 쓰는데?</strong></p>
<p>✅ JWT(2)에서는?</p>
<p>JWT는 토큰을 직접 주고받으면서 인증하므로 서버가 세션을 저장할 필요 없음.
API 서버가 여러 개일 때(JWT는 Stateless), 세션 기반은 부담이 됨(Scale-out 어려움).
✅ OAuth(3)에서는?</p>
<p>OAuth는 외부 인증 제공자가 사용자를 인증하고, 토큰을 제공함.
서버가 로그인 상태를 유지할 필요 없음(토큰 검증만 하면 됨).
✅ API Key/Basic Auth(4)에서는?</p>
<p>API 호출마다 인증 정보를 보내므로 세션 유지가 필요 없음.
RESTful API 원칙: Stateless(상태를 유지하지 않음)</p>
<p><strong>📌 세션 기반 인증의 장단점</strong>
✅ 장점</p>
<p>상태 유지: 로그인 후 계속 인증된 상태 유지 가능.
보안성: 세션은 서버에서 관리되므로, 토큰을 클라이언트가 보관하는 JWT보다 안전할 수 있음.
기존 웹 애플리케이션과 잘 맞음 (Spring MVC + JSP 같은 전통적인 웹 서비스).</p>
<p>❌ 단점</p>
<p>확장성 문제(Scale-out 어려움): 서버 여러 대가 필요하면 세션 동기화(Sticky Session, Redis 등)를 해야 함.
모바일/SPA에는 불리함: API 서버와 프론트엔드가 분리된 경우, 클라이언트가 세션을 관리하기 어려움.</p>
<p><strong>2. JWT(Json Web Token)가 뭔데? 왜 쓰는데?</strong>
👉 사용자의 인증 정보를 포함한 토큰(JSON 형식)을 서버가 발급하고, 클라이언트가 요청마다 보냄.</p>
<p>서버는 JWT를 검증하고 인증된 사용자만 API를 사용할 수 있도록 함.
세션 없이 Stateless(상태 유지 X) 하므로 서버 부담이 적음.</p>
<p><strong>📌 왜 1, 3, 4에서는 JWT를 안 쓰는데</strong></p>
<p>✅ 세션(1)에서는?</p>
<p>웹 애플리케이션(ERP, 전통적인 웹)에서는 상태 유지가 중요해서 JWT보다 세션이 더 적절함.
JWT는 매 요청마다 토큰을 검증해야 하므로 서버 리소스 부담이 클 수 있음.
✅ OAuth(3)에서는?</p>
<p>OAuth 자체가 인증을 제공하는 방식이므로, JWT 없이도 OAuth 토큰을 활용할 수 있음.
OAuth에서 JWT를 쓰기도 하지만, OAuth = JWT는 아님.
✅ API Key/Basic Auth(4)에서는?</p>
<p>API Key는 단순한 키 값만 전달하면 되므로 JWT처럼 토큰을 생성하고 검증할 필요 없음.
Basic Auth는 사용자명/비밀번호를 매번 보내기 때문에 JWT 필요 없음.</p>
<p><strong>📌 JWT 인증의 장단점</strong>
✅ 장점</p>
<p>Stateless: 세션 저장소 필요 없음 → 확장성 뛰어남.
모바일/SPA와 잘 맞음: API 서버와 클라이언트가 분리된 환경에서 적절.
다중 서버(분산 시스템)에서 유리: 서버 간 세션 공유 필요 없음.</p>
<p>❌ 단점</p>
<p>보안 취약점: 토큰이 노출되면 누구나 사용할 수 있음(탈취 위험 → HttpOnly/Secure 설정 필요).
갱신 어려움: 세션 기반처럼 상태를 유지하는 게 아니라, JWT가 만료되면 재발급 필요함(리프레시 토큰 필요).
토큰 크기 문제: 세션보다 데이터가 커질 수 있음(서버가 저장하는 것이 아니라 클라이언트가 보관).</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[@Autowired 주입 방식 3가지]]></title>
            <link>https://velog.io/@park-nahyun/Autowired-%EC%A3%BC%EC%9E%85-%EB%B0%A9%EC%8B%9D-3%EA%B0%80%EC%A7%80</link>
            <guid>https://velog.io/@park-nahyun/Autowired-%EC%A3%BC%EC%9E%85-%EB%B0%A9%EC%8B%9D-3%EA%B0%80%EC%A7%80</guid>
            <pubDate>Tue, 25 Feb 2025 15:19:08 GMT</pubDate>
            <description><![CDATA[<p>1️⃣ 필드 주입 (권장 X)</p>
<pre><code class="language-java">@Component
public class UserService {
    @Autowired
    private UserRepository userRepository;
}</code></pre>
<p>✅ 장점: 코드 간결
❌ 단점:</p>
<p>DI 프레임워크 없이 테스트 어려움 (필드 직접 설정 불가)
불변성(immutable) 보장 안됨
Spring에 강하게 결합됨 (외부에서 변경 불가)
📌 → 필드 주입은 거의 쓰지 않는 게 좋음!</p>
<p>2️⃣ 세터 주입 (가급적 X)</p>
<pre><code class="language-java">@Component
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}</code></pre>
<p>✅ 장점: 필요할 때만 의존성을 변경 가능
❌ 단점:</p>
<p>객체 생성 후에도 의존성이 바뀔 수 있어 불변성 보장 안됨.
의존성이 없으면 객체 생성이 실패할 수도 있음.
📌 → 보통 사용하지 않음. 특별한 경우에만 사용.</p>
<p>3️⃣ 생성자 주입 (💡 추천)</p>
<p>@Component
public class UserService {
    private final UserRepository userRepository;</p>
<pre><code>@Autowired  // (Spring Boot 4.x부터는 생략 가능)
public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
}</code></pre><p>}
✅ 장점:</p>
<p>불변성 보장 (final 사용 가능)
Spring에 덜 의존적 (@Autowired 없어도 Spring Boot 4.x에서는 자동 주입됨)
테스트가 쉬움 (의존성을 직접 주입 가능)
📌 → 가장 권장되는 방식!</p>
<p>📌 private final + 생성자 주입 방식</p>
<pre><code class="language-java">@RequiredArgsConstructor
@Component
public class UserService {
    private final UserRepository userRepository;
}</code></pre>
<p>@RequiredArgsConstructor → 모든 final 필드에 대한 생성자 자동 생성
Spring Boot 4.x에서는 @Autowired 없이도 자동 주입됨
가장 깔끔한 코드 → 이 방식 추천!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[@Setter를 남발하지 말자]]></title>
            <link>https://velog.io/@park-nahyun/Setter%EB%A5%BC-%EB%82%A8%EB%B0%9C%ED%95%98%EC%A7%80-%EB%A7%90%EC%9E%90</link>
            <guid>https://velog.io/@park-nahyun/Setter%EB%A5%BC-%EB%82%A8%EB%B0%9C%ED%95%98%EC%A7%80-%EB%A7%90%EC%9E%90</guid>
            <pubDate>Tue, 25 Feb 2025 15:09:53 GMT</pubDate>
            <description><![CDATA[<p>📌 @Setter를 남발하면 안 되는 이유 (안 쓰는 게 좋다는 의견)</p>
<ol>
<li><p>불변성(Immutable) 깨짐 
모든 필드에 @Setter를 달면 어디서든 값이 변경될 수 있어 객체 안정성↓
해결책: 필요한 필드에만 setter 제공</p>
</li>
<li><p>객체 캡슐화(Encapsulation) 원칙 위배 
필드를 무조건 수정할 수 있으면 객체 내부 규칙을 지키기 어려움.
예) password를 암호화 없이 바로 바꿀 수 있는 setter가 있으면 보안 취약</p>
</li>
<li><p>객체의 일관성이 깨질 가능성 
setter 없이 생성자/빌더 패턴(@Builder)으로 객체 생성하면 객체 일관성 유지 가능
User user = new User(); user.setEmail(null); → 이런 코드 방지</p>
</li>
</ol>
<p>📌 Setter를 쓰지 않는 대안 (객체의 안전한 값 변경 방법)
✅ 1. 생성자(생성 시 값 설정) + 불변 객체 사용</p>
<p>생성할 때만 값을 설정하고, 이후에는 변경 불가능하게 만듦.
이점: 객체 일관성이 유지됨.</p>
<pre><code class="language-java">@Getter
public class User {
    private final String email;
    private final String nickname;

    public User(String email, String nickname) {
        this.email = email;
        this.nickname = nickname;
    }
}</code></pre>
<p>⚠️ 문제점:</p>
<p>객체 생성 후에는 값을 변경할 수 없음 → 일부 필드는 변경 가능해야 하는 경우가 있음.</p>
<p>✅ 2. @Builder 패턴 사용 (가독성 + 불변성 유지)</p>
<p>값을 직접 변경하는 것이 아니라, 새로운 객체를 생성하는 방식.</p>
<pre><code class="language-java">@Getter
@Builder
@AllArgsConstructor
public class User {
    private final String email;
    private final String nickname;
}</code></pre>
<p>⚠️ 문제점:</p>
<p>객체를 새로 만들어야 하므로 성능 면에서 부담이 있을 수 있음.</p>
<p>✅ 3. 비즈니스 메서드 사용 (값 변경을 위한 명확한 메서드 제공)</p>
<p>필요한 값만 변경하는 메서드를 제공하여, 객체의 일관성을 유지함.
Setter를 직접 열어두지 않고, 비즈니스 로직을 포함한 메서드에서 값 변경.</p>
<pre><code class="language-java">@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String nickname;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private Role role;

    // 📌 Setter 대신 비즈니스 메서드 사용
    public void changeNickname(String newNickname) {
        if (newNickname == null || newNickname.trim().isEmpty()) {
            throw new IllegalArgumentException(&quot;닉네임은 비어있을 수 없습니다.&quot;);
        }
        this.nickname = newNickname;
    }

    public void changePassword(String newPassword) {
        if (newPassword.length() &lt; 8) {
            throw new IllegalArgumentException(&quot;비밀번호는 최소 8자 이상이어야 합니다.&quot;);
        }
        this.password = newPassword; // 보통 암호화 후 저장
    }
}</code></pre>
<p>✅ 이점</p>
<p>User.setNickname(&quot;newName&quot;) 같은 무분별한 변경을 막을 수 있음.
로직을 추가하여 값 변경에 대한 유효성 검사를 수행 가능.
도메인 규칙을 강제할 수 있음 (e.g. 닉네임 길이 제한).</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MSA 연습 프로젝트 구조]]></title>
            <link>https://velog.io/@park-nahyun/MSA-%EC%97%B0%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@park-nahyun/MSA-%EC%97%B0%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Wed, 19 Feb 2025 06:01:31 GMT</pubDate>
            <description><![CDATA[<pre><code>user-service/
 ├── src/
 │   ├── main/
 │   │   ├── java/com/lab/userservice/
 │   │   │   ├── application/       # 애플리케이션 서비스 계층 (유즈케이스)
 │   │   │   │   ├── port/
 │   │   │   │   │   ├── in/
 │   │   │   │   │   │   ├── UserUseCase.java
 │   │   │   │   │   │   ├── AuthenticationUseCase.java
 │   │   │   │   │   ├── out/
 │   │   │   │   │   │   ├── LoadUserPort.java
 │   │   │   │   │   │   ├── SaveUserPort.java
 │   │   │   │   ├── service/
 │   │   │   │   │   ├── UserService.java
 │   │   │   │   │   ├── AuthenticationService.java
 │   │   │   ├── domain/            # 도메인 모델 (핵심 비즈니스 로직)
 │   │   │   │   ├── model/
 │   │   │   │   │   ├── User.java
 │   │   │   ├── infrastructure/    # 인프라 계층 (DB, 보안 등)
 │   │   │   │   ├── adapter/
 │   │   │   │   │   ├── persistence/
 │   │   │   │   │   │   ├── JpaUserRepository.java
 │   │   │   │   │   ├── security/
 │   │   │   │   │   │   ├── JwtProvider.java
 │   │   │   │   │   │   ├── SecurityConfig.java
 │   │   │   ├── interfaces/        # API 컨트롤러 계층
 │   │   │   │   ├── adapter/
 │   │   │   │   │   ├── UserController.java
 │   │   │   │   │   ├── AuthenticationController.java
 │   │   ├── resources/
 │   │   │   ├── application.yml
 │   ├── test/
 │   │   ├── java/com/lab/userservice/
 │   │   │   ├── service/
 │   │   │   │   ├── AuthenticationServiceTest.java</code></pre><p>개별 서비스 구조</p>
<pre><code>crypto-payment-system/  # 루트 디렉토리
 ├── eureka-server/        # 서비스 디스커버리
 │   ├── src/main/java/com/lab/eurekaserver/
 │   │   ├── EurekaServerApplication.java
 │   │   ├── application.yml
 ├── api-gateway/          # API Gateway
 │   ├── src/main/java/com/lab/apigateway/
 │   │   ├── ApiGatewayApplication.java
 │   │   ├── application.yml
 ├── user-service/         # 사용자 계정 및 잔액 관리
 │   ├── src/main/java/com/lab/userservice/
 │   │   ├── UserServiceApplication.java
 │   │   ├── controller/UserController.java
 │   │   ├── service/UserService.java
 │   │   ├── repository/UserRepository.java
 │   │   ├── model/User.java
 │   │   ├── application.yml
 ├── payment-service/      # 결제 승인 및 암호화폐 트랜잭션 처리
 │   ├── src/main/java/com/lab/paymentservice/
 │   │   ├── PaymentServiceApplication.java
 │   │   ├── controller/PaymentController.java
 │   │   ├── service/PaymentService.java
 │   │   ├── repository/PaymentRepository.java
 │   │   ├── model/Payment.java
 │   │   ├── application.yml
 ├── transaction-service/  # 결제 기록 저장
 │   ├── src/main/java/com/lab/transactionservice/
 │   │   ├── TransactionServiceApplication.java
 │   │   ├── controller/TransactionController.java
 │   │   ├── service/TransactionService.java
 │   │   ├── repository/TransactionRepository.java
 │   │   ├── model/Transaction.java
 │   │   ├── application.yml
 ├── notification-service/  # 알림 서비스 (선택)
 │   ├── src/main/java/com/lab/notificationservice/
 │   │   ├── NotificationServiceApplication.java
 │   │   ├── service/NotificationService.java
 │   │   ├── application.yml</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[DDD 간단 개요]]></title>
            <link>https://velog.io/@park-nahyun/DDD-%EA%B0%84%EB%8B%A8-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@park-nahyun/DDD-%EA%B0%84%EB%8B%A8-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Mon, 03 Feb 2025 21:30:02 GMT</pubDate>
            <description><![CDATA[<p>참고 영상
<a href="https://youtu.be/4QHvTeeTsj0?si=1M6OgXB0b5MHC-ib">https://youtu.be/4QHvTeeTsj0?si=1M6OgXB0b5MHC-ib</a></p>
<p>Domain Driven Design</p>
<ol>
<li>도메인 모델과 로직에 집중</li>
<li>유비쿼터스 언어(보편적 언어) 사용</li>
<li>Software Entity와 Domain간 개념의 일치
: 분석 모델 - 설계 - 코드 개념의 일치 </li>
</ol>
<h3 id="주요-용어">주요 용어</h3>
<h1 id="ddd-핵심-개념">DDD 핵심 개념</h1>
<h2 id="1-bounded-context">1. Bounded Context</h2>
<ul>
<li><p><strong>정의:</strong><br>도메인 모델이 일정한 경계 내에서 일관된 언어와 개념으로 정의되는 영역을 의미.<br>하나의 Bounded Context 내에서는 특정 용어와 모델이 통일되어 사용되지만, 다른 컨텍스트에서는 동일한 용어가 다른 의미로 사용될 수 있다.</p>
</li>
<li><p><strong>주요 특징:</strong>  </p>
<ul>
<li>도메인의 복잡성을 분리하고 관리할 수 있는 <strong>논리적 경계</strong>를 제공.</li>
<li>각 컨텍스트는 독립적으로 발전하거나 변경될 수 있다.</li>
<li>팀 간의 협업이나 시스템 통합 시 <strong>명확한 경계</strong>를 통해 혼동을 줄여야 .</li>
</ul>
</li>
</ul>
<hr>
<h2 id="2-context-map">2. Context Map</h2>
<ul>
<li><p><strong>정의:</strong><br>조직 내 또는 시스템 내 여러 Bounded Context 간의 관계와 상호작용을 시각적으로 표현한 지도 또는 다이어그램을 의미.</p>
</li>
<li><p><strong>주요 특징:</strong>  </p>
<ul>
<li>각 Bounded Context의 역할, 책임, 그리고 경계를 파악하는 데 도움을 준다.</li>
<li>컨텍스트 간의 데이터 흐름, 통합 방식, 의존 관계(예: upstream/downstream, 공유 커널 등)를 명시.</li>
<li>시스템 전체의 <strong>전반적인 아키텍처와 협업 관계</strong>를 이해하는 데 유용.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="3-aggregate">3. Aggregate</h2>
<ul>
<li><p><strong>정의:</strong><br>도메인 모델 내에서 관련된 여러 객체(Entity, Value Object 등)를 하나의 <strong>일관성 있는 단위</strong>로 묶은 집합을 의미.<br>Aggregate는 항상 하나의 <strong>Aggregate Root</strong>를 가지며, 외부에서는 이 루트를 통해서만 Aggregate 내부의 객체에 접근할 수 있다.</p>
</li>
<li><p><strong>주요 특징:</strong>  </p>
<ul>
<li><strong>일관성 경계:</strong><br>Aggregate 내부의 상태 변경은 Aggregate Root를 통해 관리되어, 비즈니스 규칙과 불변성을 보장한다.</li>
<li><strong>단일 진입점:</strong><br>외부 시스템이나 다른 Aggregate는 항상 Aggregate Root를 통해 상호작용.</li>
<li><strong>트랜잭션 경계:</strong><br>보통 하나의 Aggregate 내에서 트랜잭션이 완료되어야 일관성이 유지.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Knuth의 Method]]></title>
            <link>https://velog.io/@park-nahyun/Knuth%EC%9D%98-Method</link>
            <guid>https://velog.io/@park-nahyun/Knuth%EC%9D%98-Method</guid>
            <pubDate>Fri, 24 Jan 2025 12:38:36 GMT</pubDate>
            <description><![CDATA[<p>Knuth의 방법: 무작위로 하나를 선택하는 알고리즘
Knuth의 방법은 입력 데이터(여기서는 단어들)를 배열이나 리스트에 저장하지 않고도, 입력된 데이터 중 하나를 균등한 확률로 무작위로 선택할 수 있도록 설계된 알고리즘입니다.</p>
<ol>
<li><p>첫 번째 단어를 읽었을 때는 무조건 그 단어가 <strong>&quot;챔피언(champion)&quot;</strong>이 됩니다.
(아직 다른 선택지가 없기 때문입니다.)</p>
</li>
<li><p>두 번째 단어를 읽었을 때, 이 단어가 챔피언이 될 확률은 $\frac{1}{2}$입니다.</p>
</li>
<li><p>세 번째 단어를 읽었을 때, 이 단어가 챔피언이 될 확률은 $\frac{1}{3}$입니다.</p>
<ul>
<li>확률 $\frac{1}{3}$로 새로운 단어를 챔피언으로 선택합니다.</li>
<li>실패하면 기존 챔피언을 유지합니다.</li>
</ul>
</li>
<li><p>이 과정을 반복하면서 i번째 단어를 읽을 때마다 해당 단어를 챔피언으로 선택할 확률을 $\frac{1}{i}$로 계산합니다.</p>
</li>
<li><p>모든 단어를 읽은 뒤, 최종적으로 남아있는 챔피언이 선택된 단어가 됩니다.</p>
</li>
</ol>
<p>무슨 말이세요..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS RDS connection timeout]]></title>
            <link>https://velog.io/@park-nahyun/AWS-RDS-connection-timeout</link>
            <guid>https://velog.io/@park-nahyun/AWS-RDS-connection-timeout</guid>
            <pubDate>Sat, 28 Dec 2024 11:55:03 GMT</pubDate>
            <description><![CDATA[<p>사이드프로젝트를 위해 AWS RDS에 postgresql DB를 구성 중.
DB를 생성했으나 DBeaver에서 접속 시 connection timeout 발생.</p>
<h3 id="public-액세스-설정을-했나요">Public 액세스 설정을 했나요?</h3>
<p><img src="https://velog.velcdn.com/images/park-nahyun/post/50352a26-8f77-45c8-ae09-cb29a80dcd3e/image.png" alt=""></p>
<p><em><strong>네</strong></em></p>
<h3 id="vpc-보안-그룹의-인바운드-규칙을-설정했나요">VPC 보안 그룹의 인바운드 규칙을 설정했나요?</h3>
<p><em><strong>지금 할게요</strong></em></p>
<p><img src="https://velog.velcdn.com/images/park-nahyun/post/655f3d43-a900-4b4e-ae7f-ae00ca638277/image.png" alt=""></p>
<ul>
<li>VPC 보안 그룹 : 인스턴스에 대한 네트워크 트래픽을 제어하는 AWS의 가상 방화벽.</li>
<li>유형 : PostgreSQL 데이터베이스 서버에 대한 인바운드 설정을 하겠다는 뜻(TCP, 포드 자동 설정)</li>
<li>0.0.0.0/0: IPv4의 모든 주소를 허용, ::0: IPv6의 모든 주소를 허용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[가비지(garbage)의 정체]]></title>
            <link>https://velog.io/@park-nahyun/%EA%B0%80%EB%B9%84%EC%A7%80garbage%EC%9D%98-%EC%A0%95%EC%B2%B4%EC%B2%B4</link>
            <guid>https://velog.io/@park-nahyun/%EA%B0%80%EB%B9%84%EC%A7%80garbage%EC%9D%98-%EC%A0%95%EC%B2%B4%EC%B2%B4</guid>
            <pubDate>Mon, 23 Dec 2024 13:52:27 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/park-nahyun/post/aa31a19c-b3db-498e-8c99-cf2284420281/image.jpg" alt=""></p>
<p>자바의 기초를 다시 다지는 중..</p>
<p>아주 사소한 건데 JVM에 &#39;가비지 콜렉션&#39;이 있다는 걸 알면서도 그 &#39;가비지&#39;의 정체를 정확하게 한마디로 요약할 줄을 몰랐다.</p>
<p><strong>_가비지 = 참조가 끊긴 인스턴스
_</strong></p>
<p>스택의 변수가 참조하고 있던 힙의 인스턴스.. 이 참조가 끊기면 쓰레기가 되어 JVM에게 처리되고 마는 것이다..</p>
<p>쓰임새가 없는 삶이란.. 이런 것이다..
가비지가 되지 않기위해.. 오늘도 정진.. 공부..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CURL 명령어]]></title>
            <link>https://velog.io/@park-nahyun/CURL-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@park-nahyun/CURL-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Thu, 12 Dec 2024 06:36:54 GMT</pubDate>
            <description><![CDATA[<h3 id="curl">CURL?</h3>
<p>HTTP 및 기타 네트워크 프로토콜을 통해 데이터를 송수신하는 데 사용. 
주로 API 호출, 파일 다운로드, 서버 상태 확인 등 다양한 네트워크 작업에 활용.</p>
<h4 id="기본-구문">기본 구문</h4>
<pre><code>curl [옵션] [URL]</code></pre><h4 id="주요-옵션">주요 옵션</h4>
<ul>
<li><p>서버로 기본적인 GET 요청을 보냄.</p>
<pre><code>curl https://example.com</code></pre></li>
<li><p>데이터를 POST 방식으로 서버에 보냄.</p>
<pre><code>curl -X POST -d &quot;key1=value1&amp;key2=value2&quot; https://example.com/api</code></pre></li>
<li><p>JSON 데이터를 보낼 경우:</p>
<pre><code>curl -X POST -H &quot;Content-Type: application/json&quot; -d &#39;{&quot;key&quot;:&quot;value&quot;}&#39; https://example.com/api</code></pre></li>
<li><p>HTTP 요청에 헤더를 추가</p>
<pre><code>curl -H &quot;Authorization: Bearer &lt;token&gt;&quot; https://example.com/api</code></pre></li>
<li><p>파일을 다운로드하여 저장</p>
<pre><code>curl -O https://example.com/file.zip</code></pre></li>
<li><p>파일을 서버로 업로드</p>
<pre><code>curl -X POST -F &quot;file=@path/to/file&quot; https://example.com/upload</code></pre></li>
<li><p>응답을 파일로 저장:</p>
<pre><code>curl -o output.txt https://example.com</code></pre></li>
<li><p>응답 헤더만 보기:</p>
<pre><code>curl -I https://example.com</code></pre></li>
<li><p>리디렉션 자동 처리:</p>
<pre><code>curl -L https://short.url</code></pre></li>
</ul>
<p>요청 시간 확인:</p>
<pre><code>curl -w &quot;Time taken: %{time_total}\n&quot; -o /dev/null -s https://example.com</code></pre><p>기본 인증(Basic Auth):</p>
<pre><code>curl -u username:password https://example.com</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[관계형 데이터베이스의 ACID 특성]]></title>
            <link>https://velog.io/@park-nahyun/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%9D%98-ACID-%ED%8A%B9%EC%84%B1</link>
            <guid>https://velog.io/@park-nahyun/%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%9D%98-ACID-%ED%8A%B9%EC%84%B1</guid>
            <pubDate>Wed, 11 Dec 2024 06:18:14 GMT</pubDate>
            <description><![CDATA[<h3 id="acid란">ACID란?</h3>
<p>원자성(Atomicity), 일관성(Consistency), 독립성(Isolation), 지속성(Durability)의 앞 글자.</p>
<p>데이터베이스에서 수행하는 일련의 처리를 트랜잭션이라고 하는데 이 트랜잭션 단위가 ACID의 특성을 갖는다.</p>
<ul>
<li>원자성 : 트랜잭션은 모두 실행되거나 실행되지 않아야 한다.</li>
<li>일관성 : 정해진 데이터베이스의 규칙을 만족해야 한다. 
ex) 학생 번호가 반드시 입력되어야 하는데, 학생 번호 없이 학생 정보가 추가되는 경우 일관성이 위배된다.</li>
<li>독립성 : 트랜잭션을 단독으로 실행할 때나 동시에 여러개를 실행할 때 결과가 같아야 한다.</li>
<li>지속성 : 하드웨어 등의 장애가 있어도 완료된 트랜잭션의 결과는 손실되지 않아야 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[피그마의 hierarchy]]></title>
            <link>https://velog.io/@park-nahyun/%ED%94%BC%EA%B7%B8%EB%A7%88%EC%9D%98-hierarchy</link>
            <guid>https://velog.io/@park-nahyun/%ED%94%BC%EA%B7%B8%EB%A7%88%EC%9D%98-hierarchy</guid>
            <pubDate>Mon, 09 Dec 2024 07:09:03 GMT</pubDate>
            <description><![CDATA[<h2 id="project-hierarchy">Project hierarchy</h2>
<p><img src="https://velog.velcdn.com/images/park-nahyun/post/3f3e8123-7d98-4f20-a345-f73d085a8055/image.png" alt=""></p>
<p>Team - 말 그대로 팀 협업 공간.
Team &gt; Progect &gt; File, File, File...</p>
<p>하지만 모든 File이 Team에 소속될 필요는 없다.</p>
<p>Draft - 팀에서 공식화되지 않은 작업파일, 일종의 초안용
Draft &gt; File, File, File...</p>
<h2 id="canvas-hierarchy">Canvas hierarchy</h2>
<p><img src="https://velog.velcdn.com/images/park-nahyun/post/4f1b7cf9-d6e7-4413-b273-88d023764392/image.png" alt=""></p>
<p>왼쪽 레이어
오른쪽 속성
아래 툴바</p>
<p>가운데 캔버스 - 그림을 그릴 수 있는 영역
프레임 - 실제 앱이 만들어지는 영역, 기획서를 만들 때도 프레임을 만들어 놓고 프레임 안에 내용을 넣어서 문서를 만듦
엘리먼트 - 프레임 안에 들어가는 요소들
섹션 - 같은 플로우의 프레임 혹은 요소들을 묶은 것, 섹션을 묶어서 다른 섹션으로 만들기 가능.</p>
<p>페이지 &gt; 캔퍼스 &gt; 섹션 &gt; 프레임 &gt; 다른 프레임 혹은 엘리먼트</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[피그마와 피그잼]]></title>
            <link>https://velog.io/@park-nahyun/%ED%94%BC%EA%B7%B8%EB%A7%88%EC%99%80-%ED%94%BC%EA%B7%B8%EC%9E%BC</link>
            <guid>https://velog.io/@park-nahyun/%ED%94%BC%EA%B7%B8%EB%A7%88%EC%99%80-%ED%94%BC%EA%B7%B8%EC%9E%BC</guid>
            <pubDate>Mon, 09 Dec 2024 07:00:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/park-nahyun/post/0e045354-e61a-479c-b42a-6536725ba3f5/image.png" alt=""></p>
<p>피그마 홈 화면에서 다음과 같이 두 종류의 파일을 생성할 수 있다.</p>
<h3 id="디자인-파일">디자인 파일</h3>
<ul>
<li>UI를 설계하고 프로토타입핑을 할 수 있다.</li>
<li>와이어프레임을 그리는 용도로 사용할 수 있다.</li>
<li>스마트폰, 브라우저 등등의 해상도에 맞게 UI를 디자인 하여 개발자에게 전달할 수 있다.</li>
<li>주로 디자이너들, 개발자와 협업하는 쪽이 많이 쯤</li>
</ul>
<h3 id="피그잼">피그잼</h3>
<ul>
<li>협업에 더 중점</li>
<li>아이디어 모으거나, 브레인스토밍 하거나 유저 플로우를 그릴 때</li>
<li>다양한 사람들이 협업하며 작업할 수 있는 연결 보드.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[EventBroker & 중개자 패턴]]></title>
            <link>https://velog.io/@park-nahyun/EventBroker-%EC%A4%91%EA%B0%9C%EC%9E%90-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@park-nahyun/EventBroker-%EC%A4%91%EA%B0%9C%EC%9E%90-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Tue, 24 Sep 2024 09:51:44 GMT</pubDate>
            <description><![CDATA[<p>EventBroker와 중개자 패턴(Mediator Pattern)은 모두 객체 간의 상호작용을 관리하는 데 사용되지만, 몇 가지 주요 차이점이 있습니다. 아래에서 각각의 개념과 그 차이점을 설명하겠습니다.</p>
<p>EventBroker
정의: EventBroker는 주로 이벤트 기반 시스템에서 이벤트를 발생시키고 수신하는 역할을 합니다. 여러 객체가 이벤트를 발행하고, 다른 객체가 그 이벤트를 수신하여 처리할 수 있도록 중재하는 기능을 수행합니다.
용도: 이벤트 기반 아키텍처에서 주로 사용되며, 다양한 이벤트를 중앙에서 관리하고 전달하는 기능을 제공합니다. 객체 간의 느슨한 결합을 유지하는 데 도움이 됩니다.
구현 방식: 주로 addListener, dispatch 등의 메서드를 통해 이벤트 리스닝과 이벤트 발생을 처리합니다. 이벤트가 발생하면 관련된 모든 리스너가 호출됩니다.
중개자 패턴 (Mediator Pattern)
정의: 중개자 패턴은 객체 간의 직접적인 상호작용을 줄이기 위해 중개자 역할을 하는 객체를 도입하는 구조입니다. 이를 통해 객체 간의 결합도를 낮추고, 서로의 관계를 더 쉽게 관리할 수 있습니다.
용도: 복잡한 상호작용을 관리하고, 객체 간의 의존성을 줄이며, 시스템을 더 이해하기 쉽게 만드는데 주로 사용됩니다.
구현 방식: 중개자는 여러 객체를 참조하며, 이들 간의 상호작용을 조정합니다. 클라이언트는 중개자를 통해 다른 객체에 메시지를 전달하거나 요청을 수행합니다.
주요 차이점
목적:</p>
<p>EventBroker: 이벤트 기반의 통신을 관리하는 데 중점을 둡니다.
중개자 패턴: 객체 간의 직접적인 상호작용을 줄이고, 복잡성을 관리하는 데 중점을 둡니다.
상호작용 방식:</p>
<p>EventBroker: 이벤트를 발행하고, 해당 이벤트를 수신하는 리스너를 호출하는 방식으로 동작합니다. 일반적으로 이벤트를 발생시키는 주체와 이를 수신하는 주체가 분리됩니다.
중개자 패턴: 중개자가 여러 객체 간의 직접적인 관계를 관리합니다. 객체는 중개자를 통해 서로 상호작용하며, 중개자가 이를 조정합니다.
유연성:</p>
<p>EventBroker: 다양한 이벤트를 추가할 수 있는 유연성을 제공하지만, 특정 이벤트의 흐름을 추적하기 어려울 수 있습니다.
중개자 패턴: 명확한 책임과 역할 분담을 통해 객체 간의 관계를 명확히 하지만, 중개자 객체가 너무 복잡해질 수 있는 단점이 있습니다.
요약
EventBroker는 이벤트를 중재하여 객체 간의 통신을 관리하는 반면, 중개자 패턴은 객체 간의 상호작용을 조정하는 역할을 합니다. 두 개념은 목적과 사용 사례에 따라 선택하여 사용할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[commit 메세지 수정하기]]></title>
            <link>https://velog.io/@park-nahyun/commit-%EB%A9%94%EC%84%B8%EC%A7%80-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@park-nahyun/commit-%EB%A9%94%EC%84%B8%EC%A7%80-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 13 Aug 2024 00:37:40 GMT</pubDate>
            <description><![CDATA[<p>상여자는 커밋 메시지를 수정하지 않는다.
하지만 나는 하여자니까 수정 1억 번 함.</p>
<p>출처 : <a href="https://velog.io/@mayinjanuary/git-%EC%BB%A4%EB%B0%8B-%EB%A9%94%EC%84%B8%EC%A7%80-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0-changing-commit-message">https://velog.io/@mayinjanuary/git-%EC%BB%A4%EB%B0%8B-%EB%A9%94%EC%84%B8%EC%A7%80-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0-changing-commit-message</a></p>
<h4 id="1-commit이-remote-저장소에-올라가지-않은-경우">1. commit이 remote 저장소에 올라가지 않은 경우</h4>
<p>1-1. 가장 최근의 commit 수정</p>
<pre><code>git commit --amend</code></pre><p>1-2.  더 오래된 commit 수정 또는 한 번에 여러 commit 수정</p>
<pre><code>git log</code></pre><pre><code>git rebase -i HEAD~n  </code></pre><p>&nbsp;&nbsp;위의 명령어는 현재 작업 중인 브랜치의 가장 최근 commit n개를 보여주게 된다.</p>
<p>&nbsp;&nbsp;예)</p>
<pre><code>git rebase -i HEAD~2</code></pre><p><img src="blob:https://velog.io/3d253223-c021-4cf1-aced-39391d34ddae" alt="업로드중.."></p>
<p>&nbsp;&nbsp;여기서 커밋 옆의 pick 문구를 reword로 변경하여 저장하면
&nbsp;&nbsp;해당 커밋 메시지를 수정할 수 있는 창이 나옴. 수정 후 저장.</p>
<h4 id="2-commit이-remote-저장소에-올라간-경우">2. commit이 remote 저장소에 올라간 경우</h4>
<p>&nbsp;&nbsp; 위의 방법으로 commit 메시지를 수정한 후 강제로 push</p>
<pre><code>git push --force 브랜치이름</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[use strict]]></title>
            <link>https://velog.io/@park-nahyun/use-strict</link>
            <guid>https://velog.io/@park-nahyun/use-strict</guid>
            <pubDate>Thu, 25 Jul 2024 02:08:29 GMT</pubDate>
            <description><![CDATA[<p>출처  : <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Strict_mode">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Strict_mode</a>
<a href="https://www.w3schools.com/js/js_strict.asp">https://www.w3schools.com/js/js_strict.asp</a></p>
<p>js 니가 안 엄격하면 어떡할건데ㅋ</p>
<h3 id="엄격한-모드란">엄격한 모드란?</h3>
<ol>
<li>기존에는 조용히 무시되던 에러들을 throwing합니다. --&gt; 디버깅 쉬워짐</li>
<li>JavaScript 엔진의 최적화 작업을 어렵게 만드는 실수들을 바로잡습니다. 가끔씩 엄격 모드의 코드는 비-엄격 모드의 동일한 코드보다 더 빨리 작동하도록 만들어집니다. --&gt; 수행 속도 빨라짐</li>
<li>엄격 모드는 ECMAScript의 차기 버전들에서 정의 될 문법을 금지합니다. --&gt; 에러 예방</li>
</ol>
<p>use strict는 전역 스코프, 함수 내부에서 선언할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리눅스 방화벽 관련 명령어 정리]]></title>
            <link>https://velog.io/@park-nahyun/%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%B0%A9%ED%99%94%EB%B2%BD-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@park-nahyun/%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%B0%A9%ED%99%94%EB%B2%BD-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 26 Jun 2024 02:10:55 GMT</pubDate>
            <description><![CDATA[<p>무슨 뜻인지 찾아볼 시간 없고 일단 익혀라
sudo 명령임을 전제함 ~</p>
<h4 id="특정-포트-방화벽-열기">특정 포트 방화벽 열기</h4>
<pre><code> firewall-cmd --permanent --add-port=[포트]/tcp

 #포트 열고 재기동 해줘야함
 firewall-cmd --reload</code></pre><h4 id="포트-열렸는지-listen-중인지-확인">포트 열렸는지, LISTEN 중인지 확인</h4>
<pre><code>firewall-cmd --list-all

netstat -tuln | grep [포트]</code></pre><h4 id="selinux가-문제라면">selinux가 문제라면?</h4>
<pre><code># selinux 동작 중인지 확인
getenforce

# selinux 동작 끄기
setenfore 0</code></pre><p>selinux를 끄는 건 사실 비추천.
그런데 지금은 내가 만든 테스트 서버에서 어떻게든 테스트를 해야하는 상황임ㅜ 실제 개발계/운영계에서는 인프라 담당자들에게 맡길 것</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[yum이란? / yum 로컬 리포지토리 설정]]></title>
            <link>https://velog.io/@park-nahyun/yum%EC%9D%B4%EB%9E%80-yum-%EB%A1%9C%EC%BB%AC-%EB%A6%AC%ED%8F%AC%EC%A7%80%ED%86%A0%EB%A6%AC-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@park-nahyun/yum%EC%9D%B4%EB%9E%80-yum-%EB%A1%9C%EC%BB%AC-%EB%A6%AC%ED%8F%AC%EC%A7%80%ED%86%A0%EB%A6%AC-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Fri, 14 Jun 2024 04:33:40 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/park-nahyun/post/5624c375-d385-4e39-b447-be2b960460c5/image.jpg" alt="">
얘는 유미 ㅋ</p>
<p>예전에도 두어 번 저장해둔 내용이지만 걍 링크 긁어온 수준이라 다시 씀</p>
<p>출처 : <a href="https://myminju.tistory.com/21">https://myminju.tistory.com/21</a>
<a href="https://boring-notes.tistory.com/entry/CentOS-local-YUM-Repository-%EB%A7%8C%EB%93%A4%EA%B8%B0">https://boring-notes.tistory.com/entry/CentOS-local-YUM-Repository-%EB%A7%8C%EB%93%A4%EA%B8%B0</a></p>
<h2 id="yum">yum?</h2>
<ul>
<li>Yellowdog Update Modified의 약자로 레드햇 계열의 리눅스에서 사용하는 패키지 설치 관리 도구다.</li>
<li>패키지 의존성 문제를 자동으로 처리 : 설치, 업데이트, 삭제를 진행 → Spring(=rpm)에서 안되던 dependency 주입을 Springboot(=yum)에서 해주는 것과 유사(설명이 너무 찰떡이다 원글님 너무 감사합니다 감사합니다)</li>
</ul>
<h2 id="yum-로컬-리포지토리-설정">yum 로컬 리포지토리 설정</h2>
<ul>
<li>기본적으로 yum은 인터넷 상의 패키지 저장소 서버로부터 패키지를 다운 받아온다.(/etc/yum.conf와 /etc/yum.repos.d/에 패키지 저장소 서버 정보가 있음)</li>
<li>폐쇄망의 경우 인터넷이 되지 않기 때문에 서버의 로컬 환경에 저장소(리포지토리)를 구성할 필요가 있다.</li>
<li>기본적으로 linux 배포판에는 yum 저장소가 포함돼있다. 다만 인터넷 연결이 안된 상황에서는 저장소 내부의 패키지를 최신 버전으로 업데이트 하기 힘들다.(인터넷 되는 환경에서 최신 패키지를 가져와서 로컬 저장소에 복사하는 식으로 관리를 해야하는 듯..)</li>
</ul>
<ol>
<li>local repository가 위치할 폴더 만들기
나는 /opt 디렉토리 아래에 localrepo라는 이름의 디렉토리를 생성했다. 
왜 opt였냐 하면.. 추가 응용프로그램 패키지 설치 장소라 그래서.. /usr와 고민을 많이했다. 리눅스 디렉토리에 대한 감각도 더 키워야할 듯.
<a href="https://inpa.tistory.com/entry/LINUX-%F0%9F%93%9A-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC-%EA%B5%AC%EC%A1%B0">https://inpa.tistory.com/entry/LINUX-%F0%9F%93%9A-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC-%EA%B5%AC%EC%A1%B0</a></li>
</ol>
<ol start="2">
<li>OS iso 파일을 마운트</li>
</ol>
<ul>
<li><p>마운트 ? 마운트는 파일 시스템을 특정 디렉토리에 연결하는 과정을 의미합니다. 예를 들어, 외장 하드 드라이브나 USB 드라이브를 시스템에 연결하여 그 안의 파일에 접근할 수 있도록 하는 것입니다.</p>
</li>
<li><p>서버를 처음 구성하고 centOS를 설치할 때 iso 이미지 파일을 사용했다. 그럼 서버 내에 이미 iso가 있는거 아냐?? 하고 챗사수께 여쭤봤더니 그게 아니란다. 윈도우 설치할 때 cd를 사용하고 설치 완료 후에 도로 뺀 것과 비슷한듯? 이제 나는 윈도우 cd 내에 있는 다른 것들을 다시 받고 싶으니 cd를 다시 넣어야 한다. 그게 지금의 마운트 과정이다.</p>
</li>
<li><p>마운트 포인트로 사용하는 디렉토리는 /media와 /mnt가 있다. media는 OS에서 자동으로 마운팅해주는 포인트고 mnt는 사용자가 직접 마운트 하는 경로로 사용된다고 한다. 예를 들어 컴퓨터에 usb를 꽂아서 os에 자동으로 마운트 한다면 media 폴더에 위치.. 출처는 위에 있는 링크. 나는 내가 직접 마운트를 해야하므로 mnt 디렉토리에 iso 파일을 옮겨뒀다.</p>
</li>
</ul>
<pre><code>mount -o loop /mnt/CentOS-7-x86_64-DVD-2009.iso /mnt/iso</code></pre><ul>
<li>다음과 같이 입력.루프백 장치(loopback device)를 사용하여 파일을 마운트하겠다는 뜻. (-o 옵션)<ul>
<li>루프백 장치(loopback device)는 리눅스에서 일반 파일을 블록 장치처럼 취급하여 마운트할 수 있게 해주는 가상 장치입니다. 이를 통해 ISO 파일과 같은 디스크 이미지 파일을 실제 디스크처럼 시스템에 마운트하고, 그 내용을 탐색할 수 있습니다.</li>
</ul>
</li>
<li><blockquote>
<p>하드웨어가 필요 없고 다양한 파일 형식을 블록 장치처럼 마운트할 수 있다.
<img src="https://velog.velcdn.com/images/park-nahyun/post/b4551947-b1be-4c03-815b-390a0e8e60f7/image.PNG" alt=""></p>
</blockquote>
</li>
</ul>
<ol start="3">
<li>package 복사 + 붙여넣기 
마운트를 완료하면 iso 안에 있던 파일들이 보임. 이 중에 Packages 폴더를 내가 로컬 리포지토리로 사용할 경로에 복사 + 붙여넣기. 
<img src="https://velog.velcdn.com/images/park-nahyun/post/d1700268-5cf9-4ea8-ad43-a74a415ef7a0/image.PNG" alt=""></li>
</ol>
<ol start="4">
<li>yum 리포지토리 지정
packages를 붙여넣기한 경로를 yum 리포지토리라고 지정을 해야한다. 이 때 createrepo 명령어를 사용해야하는데..
```
root@localhost localrepo]# createrepo /opt/localrepo</li>
</ol>
<p>-bash: createrepo: command not found</p>
<pre><code>ㅋ createrepo command를 모른대ㅋ 당연함.
createrepo도 설치해서 써야하는 도구임.

그래서 packages 안에 있는 createrepo.rpm을 먼저 설치 해보기로 한다.

![](https://velog.velcdn.com/images/park-nahyun/post/c7c69a5a-6b37-4bd2-a9b8-8ac7ddd2984a/image.PNG)

ㅋ..
createrepo를 설치하려면 의존성 패키지들이 설치가 안돼있어서 설치 못한다고 나옴.. 그래서 또 필요한 의존성들을 다 설치해주고 createrepo 패키지까지 설치함.

이젠 createrepo 명령이 된다!

rpm -Uvh(upgrade, verbose, hash --&gt; 이미 설치된 패키지가 있으면 업그레이드, 없으면 새로 설치 / 자세한 정보 출력 / 설치 진행 상황을 &#39;#&#39; 해시 마크로 표시)


![](https://velog.velcdn.com/images/park-nahyun/post/4e49d8f2-2fc0-4d68-af8f-424d59c1d190/image.PNG)

worker들아 열심히 일했구나..

- Worker(작업자 프로세스) : 컴퓨팅에서 여러 작업을 병렬로 수행하기 위해 사용되는 개념

명령어 하나 칠 때마다 모르는 개념이 7억 개씩 나와서 당황스럽다..^^


5. /etc/yum.repos.d 에 local.repo설정
이제 /etc/yum.repos.d 위의 경로를 로컬 리포지토리로 설정하는 파일을 만들어야하는데.. /etc/yum.repos.d가 없다;;
yum이 제대로 설치되지 않았다면 저게 없다는데, 아무래도 OS를 min 버전으로 설치해서 정말 최소한의 패키지만 들어있었던 듯.. 다음부턴 절대로 min을 쓰지 않으리..

다시 packages에서 yum 관련 rpm들을 전부 설치했다. 그랬더니 /etc/yum.repos.d 경로와 repo 설정 파일들이 생성됨!
</code></pre><p>vi local-CentOS-7.repo</p>
<pre><code>파일을 생성한다.

</code></pre><p>[CentOS7-local-repo] 
name=CentOS Local Repository // 리포지토리 ID를 설정한다. YUM 설정 파일에서 리포지토리를 식별하는데 사용된다.</p>
<p>baseurl=file:///root/local-repo/CentOS-7 // 리포지토리가 위치한 경로를 설정한다. 
gpgcheck=0 // GPG 서명 검사 비활성화(뭔지 모름)
enabled=1 // 리포지토리 활성화</p>
<p>```</p>
<p>이 때 다른 repo 파일들의 enabled를 0으로 만들고 다른 곳으로 백업해두는게 좋다. (yum.repos.d에 local.repo만 있도록)</p>
<ol start="6">
<li>확인
<img src="https://velog.velcdn.com/images/park-nahyun/post/c7225dd5-d326-454d-a7d4-f14bd772c905/image.PNG" alt=""></li>
</ol>
<p>되네요~ㅋ
끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[가끔씩 내 어플리케이션이 멈추는 이유(스레드, 가비지 컬렉션)]]></title>
            <link>https://velog.io/@park-nahyun/%EA%B0%80%EB%81%94%EC%94%A9-%EB%82%B4-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%9D%B4-%EB%A9%88%EC%B6%94%EB%8A%94-%EC%9D%B4%EC%9C%A0%EC%8A%A4%EB%A0%88%EB%93%9C-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98</link>
            <guid>https://velog.io/@park-nahyun/%EA%B0%80%EB%81%94%EC%94%A9-%EB%82%B4-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%9D%B4-%EB%A9%88%EC%B6%94%EB%8A%94-%EC%9D%B4%EC%9C%A0%EC%8A%A4%EB%A0%88%EB%93%9C-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98</guid>
            <pubDate>Fri, 31 May 2024 04:46:38 GMT</pubDate>
            <description><![CDATA[<p>자바 소켓 통신 관련 공부를 하다가 발견한 내용.</p>
<p>내용 출처 : 자바 네트워크 소녀 네티</p>
<p>블로킹 + 클라이언트가 접속할 때마다 스레드를 새로 생성하는 로직으로 소켓 통신을 한다고 가정했을 때 스레드가 게송 생성되어 서버 소켓의 병목 현상과 자바 힙 메모리의 부족 현상이 발생할 수 있다.</p>
<p>그래서 스레드 풀링을 사용하기도 한다.
스레드를 미리 여러 개 만들어서 풀 안에 넣어  놓고 클라이언트가 서버에 접속하면 플에서 가용 스레드를 가져와서 처리하고.. 작업이 끝나면 다시 스레드
여러 클라이언트가 서버에 붙으면 스레드</p>
<p>즉 스레드 풀의 크기(풀 안에 들어가는 스레드 개수?)가 곧 동시 접속 수가 되겠다.
동시접속 수를 늘리기 위해 스레드 풀을 자바 힙이 허용하는 최대 한도까지 늘리는 것이 옳은가? &gt;&gt;</p>
<ol>
<li>자바 가비지 컬랙션
스레드 풀을 자바 힙이 허용하는 최대치로 늘려서 자바 프로세스를 동작시키면 당연히 가비지 컬랙션의 대상이 되는 객체 수가 늘어난다. 가비지 컬랙션이 동작할 때는 다른 스레드를 멈추게 되는데 그러면 어플리케이션이 먹통이 된 것처럼 보인다.</li>
</ol>
<p>이 부분 때문에 글을 쓰게 됨.
나는 소스 코드를 짤 때 스레드 같은 걸 신경쓰지 않고 짰는데 가끔 동작하다가 어플리케이션이 멈추는 경우가 있었다. 그게 다 내가 스레드 관리를 못해서.. 가비지 컬렉터가 열일 하느라 그랬던게 아닌지..</p>
<ol start="2">
<li>운영체제에서 사용되는 컨텍스트 스위칭
한 프로세스에서 수행되는 스레드들이 CPU 점유를 위해서 자신의 상태를 변경하는 작업.
수많은 스레드가 실행되면 CPU 자원을 획득하기 위해 경쟁하면서 CPU 자원을 소모하기 때문에 실제로 작업에 사용할 CPU 자원이 적어지게 된다.</li>
</ol>
<p>결론 : 블로킹 방식은 필요할 때만 쓰자</p>
]]></description>
        </item>
    </channel>
</rss>