<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Gani의 개발 기록</title>
    <link>https://kgee0503.tistory.com/</link>
    <description>풀스택 개발자가 되기 위해 공부하며 정리하는 기록 공간입니다.</description>
    <language>ko</language>
    <pubDate>Tue, 7 Apr 2026 08:33:23 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Gani053</managingEditor>
    <image>
      <title>Gani의 개발 기록</title>
      <url>https://tistory1.daumcdn.net/tistory/8456931/attach/61cca0114fab4387a354e65668696c52</url>
      <link>https://kgee0503.tistory.com</link>
    </image>
    <item>
      <title>request,response 정리</title>
      <link>https://kgee0503.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 이게 제일 헷갈렸다. req가 뭔지 res가 뭔지는 알겠는데 실제로 코드에서 어디서 어떻게 쓰이는지가 계속 안 잡혔다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;req, res&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;req (request)&lt;/b&gt; : 클라이언트가 서버한테 보내는 요청. 뭘 해달라는 거. URL, HTTP 메서드, 헤더, 바디 다 여기 담겨 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;res (response)&lt;/b&gt; : 서버가 클라이언트한테 돌려주는 응답. 처리 결과를 돌려주는 거. 상태코드, 헤더, 바디가 여기 담긴다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;brainfuck&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;클라이언트 --[req]--&amp;gt; 서버
클라이언트 &amp;lt;--[res]-- 서버&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프론트(Vue + axios)에서 req 보내기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios로 요청을 보내는 게 req를 만드는 거다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;cs&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;// GET 요청
const res = await axios.get('/api/vehicles')

// POST 요청
const res = await axios.post('/api/vehicles', {
  carNumber: '12가3456',
  ownerName: '홍길동'
})

// 헤더에 JWT 토큰 담아서 보내기
const res = await axios.get('/api/vehicles', {
  headers: {
    Authorization: `Bearer ${token}`
  }
})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios.get(), axios.post() 이게 req를 만들어서 서버에 보내는 거다. 반환값으로 받는 res가 서버에서 돌아온 응답이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답 데이터는 res.data로 꺼내 쓴다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;cs&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;const res = await axios.get('/api/vehicles')
console.log(res.data) // 서버가 보내준 데이터&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;백(Spring)에서 req 받고 res 돌려주기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트에서 보낸 req를 Spring 컨트롤러가 받는다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;@RestController
@RequestMapping(&quot;/api/vehicles&quot;)
public class VehicleController {

    // GET 요청 받기
    @GetMapping
    public ResponseEntity&amp;lt;List&amp;lt;Vehicle&amp;gt;&amp;gt; getVehicles() {
        List&amp;lt;Vehicle&amp;gt; list = vehicleService.getAll();
        return ResponseEntity.ok(list); // 200 OK + 데이터 반환
    }

    // POST 요청 받기 (바디에서 데이터 꺼내기)
    @PostMapping
    public ResponseEntity&amp;lt;Void&amp;gt; addVehicle(@RequestBody VehicleRequest request) {
        vehicleService.add(request);
        return ResponseEntity.status(201).build(); // 201 Created
    }
}
```

`@RequestBody` : req 바디에 담긴 JSON을 Java 객체로 변환해준다.
`ResponseEntity` : 상태코드랑 응답 바디를 직접 설정해서 돌려줄 수 있다.

---

## 전체 흐름 한눈에
```
[Vue]
axios.post('/api/vehicles', { carNumber: '12가3456' })
        &amp;darr; req (HTTP POST, body에 JSON 담아서 전송)

[Spring - JwtAuthenticationFilter]
Authorization 헤더에서 토큰 꺼내서 검증
        &amp;darr; 통과하면

[Spring - VehicleController]
@RequestBody로 바디 꺼냄
서비스 로직 실행
ResponseEntity로 결과 반환
        &amp;darr; res (HTTP 201, 결과 JSON)

[Vue]
res.data로 응답 데이터 꺼내서 사용&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 req가 axios에서 끝나는 줄 알았는데, Spring 필터 거치고 컨트롤러까지 들어오는 흐름이 연결돼 있는 거였다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;헷갈렸던 포인트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@RequestBody vs @RequestParam&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;// URL에 붙어오는 데이터 (?page=1&amp;amp;size=10)
@GetMapping
public ResponseEntity&amp;lt;?&amp;gt; getList(@RequestParam int page, @RequestParam int size) { }

// 바디에 JSON으로 담겨오는 데이터
@PostMapping
public ResponseEntity&amp;lt;?&amp;gt; add(@RequestBody VehicleRequest request) { }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET 요청은 보통 URL 파라미터, POST 요청은 보통 바디에 담아 보낸다. 처음엔 이걸 몰라서 계속 null 받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;axios res vs Spring ResponseEntity&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트에서 쓰는 res는 axios가 받아온 응답 객체고, Spring에서 쓰는 ResponseEntity는 백엔드가 응답을 만들어서 보내는 객체다. 이름이 비슷해서 헷갈렸는데 역할이 반대라고 보면 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느낀 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;req, res 개념 자체는 어렵지 않은데 프론트랑 백이 나눠져 있으니까 각각 어느 쪽에서 뭘 하는 건지 흐름이 안 잡혔던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에서 axios 요청 보내놓고 컨트롤러에서 왜 안 받히지 하면서 한참 헤맸는데, 결국 @RequestBody 빠뜨린 거였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 흐름을 한 줄로 놓고 보니까 훨씬 이해가 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트에서 만든 req가 필터 거쳐서 컨트롤러까지 들어오고, 컨트롤러에서 만든 res가 다시 프론트로 돌아가는 구조. 이 한번 머릿속에 그려지니까 이해가 조금 더 됐다.&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/9</guid>
      <comments>https://kgee0503.tistory.com/9#entry9comment</comments>
      <pubDate>Tue, 31 Mar 2026 14:23:00 +0900</pubDate>
    </item>
    <item>
      <title>IoC &amp;middot; DI &amp;middot; 빈 등록 정리</title>
      <link>https://kgee0503.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 IoC랑 DI 개념 정리했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 그동안 그냥 @Service 붙이면 되는 거 아닌가 하고 넘겼는데 제대로 짚고 가야 할 것 같아서 정리한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;IoC (Inversion of Control) - 제어의 역전&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직역하면 제어의 역전인데 처음엔 이게 무슨 말인지 몰랐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 이렇게 쓴다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;haxe&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;public class UserService {
    private UserRepository userRepository = new UserRepository();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 직접 new로 객체를 만드는 거다. 근데 Spring 쓰면 이걸 내가 안 해도 된다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring이 알아서 객체 만들고 넣어준다. 이게 IoC다. 객체를 내가 제어하는 게 아니라 Spring이 제어하니까 &quot;제어가 역전됐다&quot;는 거였다. 이름이 어렵게 느껴지는데 개념 자체는 별거 없었다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Bean (빈)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring이 관리하는 객체를 빈이라고 부른다. 그리고 그 빈들을 담아두는 공간이 IoC 컨테이너 (ApplicationContext).&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;빈 등록하는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 어노테이션으로 등록&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@Component
@Service
@Repository
@Controller&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 붙이면 Spring이 알아서 빈으로 등록해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Service, @Repository, @Controller 다 내부적으로 @Component 포함하고 있음. 역할 구분하려고 나눠놓은 거라고 한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@Service
public class ParkingService {
    // 그냥 이렇게만 해도 빈으로 등록됨
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. @Configuration + @Bean으로 직접 등록&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 라이브러리처럼 내가 소스코드를 못 건드리는 경우에 쓴다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@Configuration
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BCryptPasswordEncoder는 외부 클래스라서 @Component 못 붙이니까 이렇게 수동으로 등록하는 거다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에서 시큐리티 설정할 때 이 방식 썼는데 그때는 왜 이렇게 하는지 몰랐는데 이제 이해된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DI (Dependency Injection) - 의존성 주입&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IoC를 구현하는 방법이다. Spring이 빈끼리 연결해주는 방식.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주입 방법이 3가지가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 생성자 주입 (권장)&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@Service
public class VehicleService {

    private final VehicleRepository vehicleRepository;

    public VehicleService(VehicleRepository vehicleRepository) {
        this.vehicleRepository = vehicleRepository;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;final 쓸 수 있어서 불변성 보장되고, 순환 참조도 컴파일 시점에 잡힌다. Spring 공식 권장 방식.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 필드 주입 (비권장)&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;@Service
public class VehicleService {

    @Autowired
    private VehicleRepository vehicleRepository;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드가 짧아서 처음엔 이게 편해 보였는데 final 못 쓰고 테스트할 때 문제가 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. setter 주입&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;@Service
public class VehicleService {

    private VehicleRepository vehicleRepository;

    @Autowired
    public void setVehicleRepository(VehicleRepository vehicleRepository) {
        this.vehicleRepository = vehicleRepository;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 IoC, DI, 빈이 다 따로따로인 줄 알았는데 정리하고 보니까 결국 하나로 이어지는 개념이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택적&amp;nbsp;의존성&amp;nbsp;있을&amp;nbsp;때&amp;nbsp;쓰는&amp;nbsp;거라는데&amp;nbsp;솔직히&amp;nbsp;아직&amp;nbsp;이걸&amp;nbsp;쓸&amp;nbsp;상황이&amp;nbsp;잘&amp;nbsp;안&amp;nbsp;떠오른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;셋의 관계 정리&lt;/b&gt;&lt;br /&gt;IoC &lt;br /&gt;&amp;nbsp;└──&amp;nbsp;IoC&amp;nbsp;컨테이너가&amp;nbsp;Bean&amp;nbsp;생성&amp;middot;관리 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──&amp;nbsp;DI로&amp;nbsp;Bean&amp;nbsp;간&amp;nbsp;의존&amp;nbsp;관계&amp;nbsp;연결&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느낀 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 처음에 @Autowired 붙이면 되는 거 아닌가 하고 이해도 없이 쓰고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 프로젝트하다가 순환 참조 오류 터지고 나서야 왜 생성자 주입 써야 하는지 몸으로 깨달았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드 주입이 코드 짧아서 편해 보이는데 테스트 짤 때 의존성 못 넣어줘서 결국 다 생성자 주입으로 바꿨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그때부터 그냥 동작하니까 쓰는 거랑 이유 알고 쓰는 거 차이를 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring 처음 배울 때 제일 헷갈렸던 부분인데 이번에 제대로 정리하고 나니까 코드 읽는 게 좀 더 편해진 것 같다.&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/8</guid>
      <comments>https://kgee0503.tistory.com/8#entry8comment</comments>
      <pubDate>Tue, 31 Mar 2026 10:54:47 +0900</pubDate>
    </item>
    <item>
      <title>JWT(JSON Web Token)</title>
      <link>https://kgee0503.tistory.com/7</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;JWT 인증 방식이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 세션 방식은 서버에 로그인 정보를 저장하는 반면, JWT는 토큰에 사용자 정보를 담아서 클라이언트가 들고 다니는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 stateless하게 유지되고, 매 요청마다 토큰만 검증하면 되니까 확장성이 좋다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;전체 흐름&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;1. 로그인 요청 (username, password)
   &amp;darr;
2. 인증 성공 시 JWT 토큰 발급
   &amp;darr;
3. 클라이언트는 이후 요청마다 토큰을 헤더에 담아 전송
   Authorization: Bearer {token}
   &amp;darr;
4. 서버는 필터에서 토큰 검증 후 인증 처리
   &amp;darr;
5. 컨트롤러 접근&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주요 구성 요소&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. JwtTokenProvider&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JWT 토큰 생성, 검증, 정보 추출 담당&lt;/li&gt;
&lt;li&gt;비밀키로 서명해서 위변조 방지&lt;/li&gt;
&lt;li&gt;주요 메서드:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;createToken(): 사용자 정보 &amp;rarr; JWT 토큰 변환&lt;/li&gt;
&lt;li&gt;validateToken(): 토큰 유효성 검증&lt;/li&gt;
&lt;li&gt;getUsername(): 토큰에서 사용자명 추출&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. JwtAuthenticationFilter&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매 HTTP 요청마다 실행되는 필터&lt;/li&gt;
&lt;li&gt;Authorization 헤더에서 JWT 토큰 추출&lt;/li&gt;
&lt;li&gt;토큰 검증 후 SecurityContext에 인증 정보 설정&lt;/li&gt;
&lt;li&gt;이후 요청에서 인증된 사용자로 처리됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. SecurityConfig&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Spring Security 전체 설정&lt;/li&gt;
&lt;li&gt;CSRF 비활성화 (JWT 방식에서는 불필요)&lt;/li&gt;
&lt;li&gt;세션 사용 안 함 (STATELESS)&lt;/li&gt;
&lt;li&gt;URL별 접근 권한 설정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/api/auth/**: 누구나 접근 가능 (로그인, 회원가입)&lt;/li&gt;
&lt;li&gt;나머지: 인증 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;JWT 필터를 Spring Security 필터 체인에 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. AuthController&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로그인 엔드포인트 제공&lt;/li&gt;
&lt;li&gt;AuthenticationManager로 실제 인증 처리&lt;/li&gt;
&lt;li&gt;인증 성공 시 JWT 토큰 발급해서 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;동작 과정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로그인 시&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 username, password 전송&lt;/li&gt;
&lt;li&gt;AuthenticationManager가 DB에서 사용자 조회 및 비밀번호 검증&lt;/li&gt;
&lt;li&gt;성공하면 JWT 토큰 생성해서 반환&lt;/li&gt;
&lt;li&gt;클라이언트는 토큰 저장 (localStorage 등)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이후 API 요청 시&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트가 Authorization: Bearer {token} 헤더 포함해서 요청&lt;/li&gt;
&lt;li&gt;JwtAuthenticationFilter가 토큰 추출 및 검증&lt;/li&gt;
&lt;li&gt;유효하면 SecurityContext에 인증 정보 설정&lt;/li&gt;
&lt;li&gt;컨트롤러에서 인증된 사용자로 처리&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 포인트&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;세션 사용 안 함&lt;/b&gt;: 서버는 상태를 저장하지 않음 (stateless)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;토큰 기반 인증&lt;/b&gt;: 매 요청마다 토큰으로 인증&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비밀키로 서명&lt;/b&gt;: 토큰 위변조 방지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;만료 시간 설정&lt;/b&gt;: 보안을 위해 토큰 유효기간 제한&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;보안 고려사항&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JWT secret은 반드시 환경변수로 관리&lt;/li&gt;
&lt;li&gt;HTTPS 사용 필수 (토큰 탈취 방지)&lt;/li&gt;
&lt;li&gt;토큰 만료시간 적절히 설정 (보통 1시간~1일)&lt;/li&gt;
&lt;li&gt;Refresh Token 추가 구현 고려 (Access Token 재발급용)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느낀 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 JWT를 공부할 때는 필터, SecurityContext, Authentication 같은 개념들이 너무 많아서 헷갈렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 Spring Security 자체가 워낙 방대해서 어디서부터 손대야 할지 막막했는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 핵심은 &lt;b&gt;&quot;토큰을 어떻게 만들고, 어떻게 검증하느냐&quot;&lt;/b&gt; 였다.&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/7</guid>
      <comments>https://kgee0503.tistory.com/7#entry7comment</comments>
      <pubDate>Sat, 7 Feb 2026 22:13:04 +0900</pubDate>
    </item>
    <item>
      <title>REST API와 HTTP</title>
      <link>https://kgee0503.tistory.com/6</link>
      <description>&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-5-2&quot; data-message-id=&quot;7509404a-5d80-461b-b59f-d3a35184fa63&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드를 공부하다 보면 GET, POST, PUT, DELETE 같은 단어를 계속 보게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 그냥 요청 방식 이름 정도로만 알았는데, 정리해보니 REST API는 프론트와 백엔드가 서로 대화하는 방식에 대한 규칙이라는 느낌에 더 가까웠다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;REST API란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API는 프론트엔드와 백엔드가 데이터를 주고받기 위한 통신 규칙이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트는 화면을 만들고 버튼을 누르면 요청을 보내고, 백엔드는 데이터를 가져오거나 수정해서 응답을 준다. 이 둘이 직접 데이터베이스와 연결되는 게 아니라 항상 서버를 거쳐서 통신하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조를 단순하게 보면 이렇게 된다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;프론트 &amp;rarr; 백엔드 서버 &amp;rarr; 데이터베이스&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트는 DB에 직접 접근하지 않고 백엔드에게 &quot;이 데이터 줘&quot;, &quot;이거 저장해&quot; 같은 요청만 보낸다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프론트에서 DB에 직접 접근하지 않는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 &quot;그냥 프론트에서 DB 연결하면 빠르지 않나?&quot; 이 생각이 들었는데 실제로는 거의 사용하지 않는 구조였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 크게 세 가지였다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;보안 문제&lt;/b&gt;: DB 주소나 비밀번호가 브라우저에 그대로 노출된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;권한 관리 어려움&lt;/b&gt;: 누가 어떤 데이터를 수정하는지 통제가 힘들다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로직 처리 한계&lt;/b&gt;: 데이터 검증이나 조건 처리를 프론트에서 하기가 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 프론트는 DB가 아니라 항상 서버하고만 통신하게 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP 메서드 종류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API에서 가장 많이 쓰는 방식은 네 가지이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GET (조회)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 가져올 때 사용한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;GET /board
GET /board/3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/board &amp;rarr; 전체 목록 조회&lt;/li&gt;
&lt;li&gt;/board/3 &amp;rarr; id가 3번인 글 하나 조회&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;POST (생성)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 데이터를 만들 때 사용한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;POST /board&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;body에 제목, 내용 같은 데이터가 들어간다.&lt;/li&gt;
&lt;li&gt;데이터베이스 INSERT 느낌이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PUT (수정)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 데이터를 수정할 때 사용한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;gams&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;PUT /board&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수정할 id와 변경 내용을 같이 보낸다.&lt;/li&gt;
&lt;li&gt;UPDATE 개념에 가깝다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DELETE (삭제)&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;DELETE /board?id=3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 id 데이터를 삭제한다.&lt;/li&gt;
&lt;li&gt;DELETE SQL과 거의 같은 느낌이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프론트에서의 흐름 (axios 기준)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue나 React에서는 보통 axios나 fetch를 사용한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;axios.get('/board')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이 한 줄이 내부적으로는&lt;/p&gt;
&lt;pre id=&quot;code_1770470159064&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://localhost:8080/board&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 주소로 요청을 보내는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트에서는 단순히 함수 호출처럼 보이지만 실제로는 서버와 통신이 일어나는 구조다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느낀 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API는 단순히 요청 방식 이름을 외우는 게 아니라 프론트와 백엔드의 역할을 나누는 구조를 이해하는 게 더 중요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 기준은&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프론트는 &lt;b&gt;화면과 요청&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;백엔드는 &lt;b&gt;데이터와 로직&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;DB는 &lt;b&gt;서버를 통해서만 접근&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이라는 흐름이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조를 이해하고 나니 axios 코드가 단순한 함수가 아니라 &quot;서버와 대화하는 문장&quot;처럼 보이기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET은 &quot;이거 보여줘&quot;, POST는 &quot;이거 저장해줘&quot;, DELETE는 &quot;이거 지워줘&quot; 같은 명령문인 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 프론트와 백엔드는 각자 맡은 역할만 하고, REST API라는 약속된 규칙으로 대화하는 구조였다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/6</guid>
      <comments>https://kgee0503.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 2 Feb 2026 10:08:51 +0900</pubDate>
    </item>
    <item>
      <title>객체지향 프로그래밍(OOP)</title>
      <link>https://kgee0503.tistory.com/5</link>
      <description>&lt;p data-end=&quot;134&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;객체지향을 처음 배울 때는&lt;br /&gt;그냥 클래스 만들고 new 쓰는 문법 정도로만 생각했다.&lt;br /&gt;그런데 정리하다 보니 객체지향은 단순 문법이 아니라 &lt;b&gt;코드를 어떻게 나눌 것인가에 대한 설계 방식&lt;/b&gt;이라는 게 더 중요하다는 걸 알게 됐다.&lt;/p&gt;
&lt;hr data-end=&quot;139&quot; data-start=&quot;136&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;151&quot; data-start=&quot;141&quot; data-ke-size=&quot;size26&quot;&gt;객체지향이란?&lt;/h2&gt;
&lt;p data-end=&quot;245&quot; data-start=&quot;153&quot; data-ke-size=&quot;size16&quot;&gt;객체지향(Object Oriented Programming, OOP)은 프로그램을 기능 단위가 아니라 &lt;b&gt;객체(Object)&lt;/b&gt; 단위로 나누어 설계하는 방식이다.&lt;/p&gt;
&lt;p data-end=&quot;311&quot; data-start=&quot;247&quot; data-ke-size=&quot;size16&quot;&gt;객체는 단순한 데이터가 아니라 &lt;b&gt;상태(데이터)와 행동(기능)을 함께 가지고 있는 하나의 단위&lt;/b&gt;라고 이해했다.&lt;/p&gt;
&lt;p data-end=&quot;330&quot; data-start=&quot;313&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 자동차를 생각해 보면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;371&quot; data-start=&quot;332&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;350&quot; data-start=&quot;332&quot;&gt;색상, 속도 &amp;rarr; 데이터(필드)&lt;/li&gt;
&lt;li data-end=&quot;371&quot; data-start=&quot;351&quot;&gt;달린다, 멈춘다 &amp;rarr; 기능(메서드)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;415&quot; data-start=&quot;373&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 현실 세계의 개념을 코드로 표현하는 방식이 객체지향의 기본 구조이다.&lt;/p&gt;
&lt;hr data-end=&quot;420&quot; data-start=&quot;417&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;447&quot; data-start=&quot;422&quot; data-ke-size=&quot;size26&quot;&gt;클래스(Class)와 객체(Object)&lt;/h2&gt;
&lt;p data-end=&quot;516&quot; data-start=&quot;449&quot; data-ke-size=&quot;size16&quot;&gt;처음에 가장 헷갈렸던 개념이었다.&lt;br /&gt;정리해보니 &lt;b&gt;클래스는 설계도, 객체는 그 설계도로 만들어진 실제 결과물&lt;/b&gt;이었다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1769762375457&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Car {
    String color;
    int speed;

    void drive() {
        System.out.println(&quot;달린다&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1769762388632&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Car car1 = new Car();
Car car2 = new Car();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;753&quot; data-start=&quot;696&quot; data-ke-size=&quot;size16&quot;&gt;같은 설계도로 만들어졌지만 각각 다른 상태를 가질 수 있는 독립적인 존재가 객체라는 점이 중요했다.&lt;/p&gt;
&lt;hr data-end=&quot;758&quot; data-start=&quot;755&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;785&quot; data-start=&quot;760&quot; data-ke-size=&quot;size26&quot;&gt;필드(Field)와 메서드(Method)&lt;/h2&gt;
&lt;p data-end=&quot;807&quot; data-start=&quot;787&quot; data-ke-size=&quot;size16&quot;&gt;객체는 데이터와 기능을 함께 가진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;832&quot; data-start=&quot;809&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;821&quot; data-start=&quot;809&quot;&gt;필드 &amp;rarr; 상태 정보&lt;/li&gt;
&lt;li data-end=&quot;832&quot; data-start=&quot;822&quot;&gt;메서드 &amp;rarr; 행동&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769762404305&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
    String name;
    int age;

    void introduce() {
        System.out.println(&quot;자기소개&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-end=&quot;1009&quot; data-start=&quot;960&quot; data-ke-size=&quot;size16&quot;&gt;데이터와 기능을 하나의 단위로 묶는 것이 객체지향의 가장 기본적인 특징이라고 느꼈다.&lt;/p&gt;
&lt;hr data-end=&quot;1014&quot; data-start=&quot;1011&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1041&quot; data-start=&quot;1016&quot; data-ke-size=&quot;size26&quot;&gt;생성자(Constructor)와 this&lt;/h2&gt;
&lt;p data-end=&quot;1070&quot; data-start=&quot;1043&quot; data-ke-size=&quot;size16&quot;&gt;객체를 생성할 때 초기값을 설정하는 역할을 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1769762431431&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class User {
    String name;

    User(String name) {
        this.name = name;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;1251&quot; data-start=&quot;1174&quot; data-ke-size=&quot;size16&quot;&gt;this는 현재 객체 자신을 의미하고 필드와 매개변수를 구분할 때 사용된다는 점을 이해하고 나니 코드를 읽는 게 훨씬 편해졌다.&lt;/p&gt;
&lt;hr data-end=&quot;1256&quot; data-start=&quot;1253&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1279&quot; data-start=&quot;1258&quot; data-ke-size=&quot;size26&quot;&gt;캡슐화(Encapsulation)&lt;/h2&gt;
&lt;p data-end=&quot;1347&quot; data-start=&quot;1281&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 그냥 private 붙이는 문법이라고 생각했는데 정리하면서 보니 &lt;b&gt;데이터 보호가 핵심 목적&lt;/b&gt;이었다.&lt;/p&gt;
&lt;pre id=&quot;code_1769762451009&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Account {
    private int money;

    public void setMoney(int money) {
        this.money = money;
    }

    public int getMoney() {
        return money;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;1583&quot; data-start=&quot;1533&quot; data-ke-size=&quot;size16&quot;&gt;외부에서 직접 값을 변경하지 못하게 하고 메서드를 통해서만 접근하도록 만드는 구조이다.&lt;/p&gt;
&lt;hr data-end=&quot;1588&quot; data-start=&quot;1585&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1608&quot; data-start=&quot;1590&quot; data-ke-size=&quot;size26&quot;&gt;상속(Inheritance)&lt;/h2&gt;
&lt;p data-end=&quot;1645&quot; data-start=&quot;1610&quot; data-ke-size=&quot;size16&quot;&gt;기존 클래스의 기능을 물려받아 새로운 클래스를 만드는 개념이다.&lt;/p&gt;
&lt;pre id=&quot;code_1769762464399&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    void sound() {
        System.out.println(&quot;소리&quot;);
    }
}

class Dog extends Animal {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;1803&quot; data-start=&quot;1766&quot; data-ke-size=&quot;size16&quot;&gt;코드를 복사하지 않고 재사용할 수 있다는 점이 가장 큰 장점이었다.&lt;/p&gt;
&lt;hr data-end=&quot;1808&quot; data-start=&quot;1805&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1830&quot; data-start=&quot;1810&quot; data-ke-size=&quot;size26&quot;&gt;오버라이딩(Overriding)&lt;/h2&gt;
&lt;p data-end=&quot;1866&quot; data-start=&quot;1832&quot; data-ke-size=&quot;size16&quot;&gt;부모 클래스의 메서드를 자식 클래스에서 다시 정의하는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1769762476776&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Dog extends Animal {
    @Override
    void sound() {
        System.out.println(&quot;멍멍&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;2034&quot; data-start=&quot;1983&quot; data-ke-size=&quot;size16&quot;&gt;같은 이름의 메서드지만 객체에 따라 다른 동작을 하게 만들 수 있다는 점이 인상적이었다.&lt;/p&gt;
&lt;hr data-end=&quot;2039&quot; data-start=&quot;2036&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2061&quot; data-start=&quot;2041&quot; data-ke-size=&quot;size26&quot;&gt;다형성(Polymorphism)&lt;/h2&gt;
&lt;p data-end=&quot;2092&quot; data-start=&quot;2063&quot; data-ke-size=&quot;size16&quot;&gt;하나의 타입으로 여러 객체를 다룰 수 있는 개념이다.&lt;/p&gt;
&lt;pre id=&quot;code_1769762491303&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Animal a = new Dog();
a.sound();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;2205&quot; data-start=&quot;2140&quot; data-ke-size=&quot;size16&quot;&gt;타입은 Animal이지만 실제 동작은 Dog의 메서드가 실행된다.&lt;br /&gt;이 구조 덕분에 코드가 훨씬 유연해진다.&lt;/p&gt;
&lt;hr data-end=&quot;2210&quot; data-start=&quot;2207&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2228&quot; data-start=&quot;2212&quot; data-ke-size=&quot;size26&quot;&gt;인터페이스와 추상 클래스&lt;/h2&gt;
&lt;p data-end=&quot;2258&quot; data-start=&quot;2230&quot; data-ke-size=&quot;size16&quot;&gt;둘 다 &amp;ldquo;완성되지 않은 설계도&amp;rdquo;라는 공통점이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2314&quot; data-start=&quot;2260&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2284&quot; data-start=&quot;2260&quot;&gt;&lt;b&gt;인터페이스&lt;/b&gt; &amp;rarr; 기능의 규칙만 정의&lt;/li&gt;
&lt;li data-end=&quot;2314&quot; data-start=&quot;2285&quot;&gt;&lt;b&gt;추상 클래스&lt;/b&gt; &amp;rarr; 일부 구현 + 일부 미구현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2383&quot; data-start=&quot;2316&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 차이를 외우려고 했는데, &lt;b&gt;인터페이스는 규칙, 추상 클래스는 반쯤 구현된 설계도&lt;/b&gt;라고 이해하니 정리가 됐다.&lt;/p&gt;
&lt;hr data-end=&quot;2388&quot; data-start=&quot;2385&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2403&quot; data-start=&quot;2390&quot; data-ke-size=&quot;size26&quot;&gt;정리하면서 느낀 점&lt;/h2&gt;
&lt;p data-end=&quot;2477&quot; data-start=&quot;2405&quot; data-ke-size=&quot;size16&quot;&gt;객체지향은 단순히 문법을 배우는 개념이 아니라 &lt;b&gt;코드를 역할과 책임 기준으로 나누는 사고 방식&lt;/b&gt;이라는 점이 가장 중요했다.&lt;/p&gt;
&lt;p data-end=&quot;2494&quot; data-start=&quot;2479&quot; data-ke-size=&quot;size16&quot;&gt;클래스 몇 개 만드는 것보다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2562&quot; data-start=&quot;2496&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2514&quot; data-start=&quot;2496&quot;&gt;데이터와 기능을 어떻게 묶을지&lt;/li&gt;
&lt;li data-end=&quot;2525&quot; data-start=&quot;2515&quot;&gt;상속이 필요한지&lt;/li&gt;
&lt;li data-end=&quot;2542&quot; data-start=&quot;2526&quot;&gt;외부 접근을 막아야 하는지&lt;/li&gt;
&lt;li data-end=&quot;2562&quot; data-start=&quot;2543&quot;&gt;공통 규칙을 인터페이스로 만들지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2600&quot; data-start=&quot;2564&quot; data-ke-size=&quot;size16&quot;&gt;이런 고민을 하는 과정이 객체지향의 핵심이라는 걸 이해하게 됐다.&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/5</guid>
      <comments>https://kgee0503.tistory.com/5#entry5comment</comments>
      <pubDate>Fri, 30 Jan 2026 17:42:01 +0900</pubDate>
    </item>
    <item>
      <title>정규화와 정규형(Normalization &amp;amp; Normal Form)</title>
      <link>https://kgee0503.tistory.com/4</link>
      <description>&lt;p data-end=&quot;293&quot; data-start=&quot;172&quot; data-ke-size=&quot;size16&quot;&gt;데이터베이스를 공부하다 보면 정규화, 정규형이라는 개념이 계속 나온다.&lt;br /&gt;처음에는 그냥 테이블을 나누는 거라고 생각했는데, 정리해보니 &lt;b&gt;데이터 중복을 줄이고 이상현상을 막기 위한 설계 과정&lt;/b&gt;이라는 게 핵심이었다.&lt;/p&gt;
&lt;hr data-end=&quot;342&quot; data-start=&quot;339&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;358&quot; data-start=&quot;344&quot; data-ke-size=&quot;size26&quot;&gt;정규화와 정규형이란?&lt;/h2&gt;
&lt;p data-end=&quot;462&quot; data-start=&quot;360&quot; data-ke-size=&quot;size16&quot;&gt;정규화(Normalization)는 데이터베이스를 설계할 때&lt;br /&gt;&lt;b&gt;중복 데이터를 줄이고, 삽입&amp;middot;수정&amp;middot;삭제 시 발생하는 이상현상(아노말리)을 막기 위해 테이블을 분해하는 과정&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-end=&quot;526&quot; data-start=&quot;464&quot; data-ke-size=&quot;size16&quot;&gt;단순히 테이블을 쪼개는 게 목적이 아니라, &lt;b&gt;데이터 사이의 관계를 명확하게 정리하는 것&lt;/b&gt;이 더 중요하다.&lt;/p&gt;
&lt;p data-end=&quot;598&quot; data-start=&quot;528&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 고객 정보와 주문 정보를 한 테이블에 같이 넣으면, 고객 이름이나 전화번호가 주문할 때마다 계속 반복 저장된다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767968888869&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE order_info (
    order_id INT,
    customer_id INT,
    customer_name VARCHAR(20),
    customer_phone VARCHAR(20),
    product_name VARCHAR(20),
    product_price INT
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;805&quot; data-start=&quot;795&quot; data-ke-size=&quot;size16&quot;&gt;이런 구조에서는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;899&quot; data-start=&quot;806&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;836&quot; data-start=&quot;806&quot;&gt;고객 전화번호가 바뀌면 여러 행을 수정해야 하고&lt;/li&gt;
&lt;li data-end=&quot;864&quot; data-start=&quot;837&quot;&gt;아직 주문하지 않은 고객은 저장할 수 없고&lt;/li&gt;
&lt;li data-end=&quot;899&quot; data-start=&quot;865&quot;&gt;주문 기록을 지우면 고객 정보까지 같이 사라질 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;925&quot; data-start=&quot;901&quot; data-ke-size=&quot;size16&quot;&gt;이런 문제들을 해결하기 위해 정규화를 한다.&lt;/p&gt;
&lt;p data-end=&quot;1007&quot; data-start=&quot;927&quot; data-ke-size=&quot;size16&quot;&gt;정규형(Normal Form)은 &lt;b&gt;정규화를 거쳐 만들어진 테이블의 상태&lt;/b&gt;를 의미한다.&lt;br /&gt;즉, 정규화는 과정이고 정규형은 결과라고 이해했다.&lt;/p&gt;
&lt;hr data-end=&quot;1012&quot; data-start=&quot;1009&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1028&quot; data-start=&quot;1014&quot; data-ke-size=&quot;size26&quot;&gt;제1정규형 (1NF)&lt;/h2&gt;
&lt;p data-end=&quot;1091&quot; data-start=&quot;1030&quot; data-ke-size=&quot;size16&quot;&gt;제1정규형은 &lt;b&gt;모든 컬럼이 하나의 값만 가지는 상태&lt;/b&gt;이다.&lt;br /&gt;하나의 컬럼에 여러 값이 들어가면 안 된다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767968945137&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE student (
    student_id INT,
    name VARCHAR(20),
    phone VARCHAR(100)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1269&quot; data-start=&quot;1196&quot; data-ke-size=&quot;size16&quot;&gt;phone 컬럼에&lt;br /&gt;010-1111-2222, 010-3333-4444&lt;br /&gt;처럼 여러 값이 들어가 있으면 제1정규형이 아니다.&lt;/p&gt;
&lt;p data-end=&quot;1287&quot; data-start=&quot;1271&quot; data-ke-size=&quot;size16&quot;&gt;그래서 값을 나눠서 저장한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767968957264&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE student_phone (
    student_id INT,
    phone VARCHAR(20)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1424&quot; data-start=&quot;1375&quot; data-ke-size=&quot;size16&quot;&gt;제1정규형은 관계형 데이터베이스의 기본 조건이라서 모든 정규화는 여기서부터 시작한다.&lt;/p&gt;
&lt;hr data-end=&quot;1429&quot; data-start=&quot;1426&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1445&quot; data-start=&quot;1431&quot; data-ke-size=&quot;size26&quot;&gt;제2정규형 (2NF)&lt;/h2&gt;
&lt;p data-end=&quot;1529&quot; data-start=&quot;1447&quot; data-ke-size=&quot;size16&quot;&gt;제2정규형은 &lt;b&gt;제1정규형을 만족하면서 부분 함수 종속이 제거된 상태&lt;/b&gt;이다.&lt;br /&gt;이 개념은 기본키가 두 개 이상인 &lt;b&gt;복합키일 때&lt;/b&gt; 중요해진다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767968974288&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE order_detail (
    order_id INT,
    product_id INT,
    product_name VARCHAR(20),
    order_quantity INT,
    PRIMARY KEY (order_id, product_id)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1791&quot; data-start=&quot;1705&quot; data-ke-size=&quot;size16&quot;&gt;여기서 기본키는 (order_id, product_id)인데&lt;br /&gt;product_name은 order_id와는 상관없이 product_id에만 의존한다.&lt;/p&gt;
&lt;p data-end=&quot;1810&quot; data-start=&quot;1793&quot; data-ke-size=&quot;size16&quot;&gt;이게 바로 부분 함수 종속이다.&lt;/p&gt;
&lt;p data-end=&quot;1831&quot; data-start=&quot;1812&quot; data-ke-size=&quot;size16&quot;&gt;그래서 상품 정보를 따로 분리한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767968985728&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE product (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(20)
);

CREATE TABLE order_detail (
    order_id INT,
    product_id INT,
    order_quantity INT,
    PRIMARY KEY (order_id, product_id)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2117&quot; data-start=&quot;2065&quot; data-ke-size=&quot;size16&quot;&gt;제2정규형의 핵심은&lt;br /&gt;&lt;b&gt;일반 컬럼이 기본키 전체에 의존하도록 만드는 것&lt;/b&gt;이라고 이해했다.&lt;/p&gt;
&lt;hr data-end=&quot;2122&quot; data-start=&quot;2119&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2138&quot; data-start=&quot;2124&quot; data-ke-size=&quot;size26&quot;&gt;제3정규형 (3NF)&lt;/h2&gt;
&lt;p data-end=&quot;2183&quot; data-start=&quot;2140&quot; data-ke-size=&quot;size16&quot;&gt;제3정규형은 &lt;b&gt;제2정규형을 만족하면서 이행 함수 종속을 제거한 상태&lt;/b&gt;이다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767969021192&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE employee (
    emp_id INT PRIMARY KEY,
    dept_id INT,
    dept_name VARCHAR(20)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2305&quot; data-start=&quot;2295&quot; data-ke-size=&quot;size16&quot;&gt;이 테이블에서는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2350&quot; data-start=&quot;2306&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2326&quot; data-start=&quot;2306&quot;&gt;emp_id &amp;rarr; dept_id&lt;/li&gt;
&lt;li data-end=&quot;2350&quot; data-start=&quot;2327&quot;&gt;dept_id &amp;rarr; dept_name&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2419&quot; data-start=&quot;2352&quot; data-ke-size=&quot;size16&quot;&gt;이런 관계가 생긴다.&lt;br /&gt;즉, dept_name은 emp_id에 직접 의존하는 게 아니라 dept_id를 통해 의존한다.&lt;/p&gt;
&lt;p data-end=&quot;2450&quot; data-start=&quot;2421&quot; data-ke-size=&quot;size16&quot;&gt;이런 구조는 중복을 만들기 때문에 테이블을 분리한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767969034683&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE department (
    dept_id INT PRIMARY KEY,
    dept_name VARCHAR(20)
);

CREATE TABLE employee (
    emp_id INT PRIMARY KEY,
    dept_id INT
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2672&quot; data-start=&quot;2620&quot; data-ke-size=&quot;size16&quot;&gt;제3정규형은 &lt;b&gt;일반 컬럼이 다른 일반 컬럼에 의존하지 않게 만드는 단계&lt;/b&gt;라고 정리했다.&lt;/p&gt;
&lt;hr data-end=&quot;2677&quot; data-start=&quot;2674&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2695&quot; data-start=&quot;2679&quot; data-ke-size=&quot;size26&quot;&gt;BC 정규형 (BCNF)&lt;/h2&gt;
&lt;p data-end=&quot;2748&quot; data-start=&quot;2697&quot; data-ke-size=&quot;size16&quot;&gt;BC 정규형은 제3정규형보다 더 엄격한 형태이다.&lt;br /&gt;모든 결정자는 반드시 후보키여야 한다.&lt;/p&gt;
&lt;p data-end=&quot;2826&quot; data-start=&quot;2750&quot; data-ke-size=&quot;size16&quot;&gt;이론적으로는 가장 깔끔한 구조지만, 실제 프로젝트에서는 성능이나 쿼리 복잡도 때문에&lt;br /&gt;제3정규형까지만 적용하는 경우도 많다고 한다.&lt;/p&gt;
&lt;hr data-end=&quot;2831&quot; data-start=&quot;2828&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2847&quot; data-start=&quot;2833&quot; data-ke-size=&quot;size26&quot;&gt;제4정규형 (4NF)&lt;/h2&gt;
&lt;p data-end=&quot;2876&quot; data-start=&quot;2849&quot; data-ke-size=&quot;size16&quot;&gt;제4정규형은 &lt;b&gt;다가 종속을 제거한 상태&lt;/b&gt;이다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767969058730&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE student_info (
    student_id INT,
    hobby VARCHAR(20),
    certificate VARCHAR(20)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3055&quot; data-start=&quot;2992&quot; data-ke-size=&quot;size16&quot;&gt;한 학생이 여러 취미와 여러 자격증을 가질 수 있는데,&lt;br /&gt;이걸 한 테이블에 넣으면 불필요한 조합이 계속 생긴다.&lt;/p&gt;
&lt;p data-end=&quot;3069&quot; data-start=&quot;3057&quot; data-ke-size=&quot;size16&quot;&gt;그래서 각각 분리한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1767969072281&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE student_hobby (
    student_id INT,
    hobby VARCHAR(20)
);

CREATE TABLE student_certificate (
    student_id INT,
    certificate VARCHAR(20)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;3247&quot; data-start=&quot;3244&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3263&quot; data-start=&quot;3249&quot; data-ke-size=&quot;size26&quot;&gt;제5정규형 (5NF)&lt;/h2&gt;
&lt;p data-end=&quot;3335&quot; data-start=&quot;3265&quot; data-ke-size=&quot;size16&quot;&gt;제5정규형은 &lt;b&gt;조인 종속과 관련된 정규형&lt;/b&gt;이다.&lt;br /&gt;테이블을 나눴다가 다시 조인했을 때 원래 데이터와 완전히 같아야 한다.&lt;/p&gt;
&lt;p data-end=&quot;3380&quot; data-start=&quot;3337&quot; data-ke-size=&quot;size16&quot;&gt;실무에서는 거의 쓰이지 않고, 개념적으로만 이해하면 되는 단계라고 느꼈다.&lt;/p&gt;
&lt;hr data-end=&quot;3385&quot; data-start=&quot;3382&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3400&quot; data-start=&quot;3387&quot; data-ke-size=&quot;size26&quot;&gt;정리하면서 느낀 점&lt;/h2&gt;
&lt;p data-end=&quot;3470&quot; data-start=&quot;3402&quot; data-ke-size=&quot;size16&quot;&gt;정규화를 공부하면서 느낀 건&lt;br /&gt;&lt;b&gt;몇 정규형이냐&lt;/b&gt;보다 &lt;b&gt;왜 나눠야 하는지 설명할 수 있는지가 더 중요하다&lt;/b&gt;는 점이었다.&lt;/p&gt;
&lt;p data-end=&quot;3491&quot; data-start=&quot;3472&quot; data-ke-size=&quot;size16&quot;&gt;중요한 기준은 다음이라고 정리했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3561&quot; data-start=&quot;3493&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3510&quot; data-start=&quot;3493&quot;&gt;데이터 중복이 발생하는지&lt;/li&gt;
&lt;li data-end=&quot;3538&quot; data-start=&quot;3511&quot;&gt;수정&amp;middot;삭제&amp;middot;삽입 시 문제가 생길 수 있는지&lt;/li&gt;
&lt;li data-end=&quot;3561&quot; data-start=&quot;3539&quot;&gt;컬럼 간의 의존 관계가 논리적인지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3638&quot; data-start=&quot;3563&quot; data-ke-size=&quot;size16&quot;&gt;정규화는 정답 맞추기용 이론이 아니라, &lt;b&gt;데이터를 어떻게 설계해야 덜 꼬일지를 고민하는 과정&lt;/b&gt;이라는 걸 조금은 이해한 것 같다.&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/4</guid>
      <comments>https://kgee0503.tistory.com/4#entry4comment</comments>
      <pubDate>Fri, 9 Jan 2026 23:31:44 +0900</pubDate>
    </item>
    <item>
      <title>관계형 데이터베이스(RDB)</title>
      <link>https://kgee0503.tistory.com/3</link>
      <description>&lt;p data-end=&quot;261&quot; data-start=&quot;137&quot; data-ke-size=&quot;size16&quot;&gt;최근에 데이터베이스를 배우면서 알게 된 개념들을 정리해 두고 싶다는 생각이 들었다.&lt;br /&gt;단순히 &lt;b&gt;용어 외우기 &lt;/b&gt;수준이 아니라, 이게 왜 필요한지, 실제로 어떤 역할을 하는지 이해하고 넘어가는 게 중요할 것 같았기 때문이다.&lt;/p&gt;
&lt;hr data-end=&quot;266&quot; data-start=&quot;263&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;304&quot; data-start=&quot;268&quot; data-ke-size=&quot;size26&quot;&gt;데이터베이스란 결국 &lt;i&gt;데이터를 제대로 관리하기 위한 시스템&lt;/i&gt;&lt;/h2&gt;
&lt;p data-end=&quot;403&quot; data-start=&quot;306&quot; data-ke-size=&quot;size16&quot;&gt;데이터베이스를 한 줄로 표현하면,&lt;br /&gt;&lt;b&gt;많은 데이터를 안전하게 저장하고, 필요할 때 빠르게 꺼내 쓰고, 믿을 수 있게 관리하기 위한 시스템&lt;/b&gt;이라고 생각하면 이해가 쉬웠다.&lt;/p&gt;
&lt;p data-end=&quot;566&quot; data-start=&quot;405&quot; data-ke-size=&quot;size16&quot;&gt;단순히 파일에 저장하는 것이 아니라, 제대로 정리하고 구조화해서 관리하는 방식이기 때문에 현실 세계의 거의 모든 서비스가 데이터베이스 위에서 돌아간다고 해도 과장이 아닌 것 같다.&lt;br /&gt;회원 정보, 주문 기록, 결제 내역, 게시글 데이터 등 이런 모든 것들이 결국 데이터베이스에 저장된다.&lt;/p&gt;
&lt;hr data-end=&quot;571&quot; data-start=&quot;568&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;610&quot; data-start=&quot;573&quot; data-ke-size=&quot;size26&quot;&gt;관계형 데이터베이스(RDB), 표로 관리하는 가장 정돈된 방식&lt;/h2&gt;
&lt;p data-end=&quot;722&quot; data-start=&quot;612&quot; data-ke-size=&quot;size16&quot;&gt;그중에서도 가장 많이 사용되는 방식이 &lt;b&gt;관계형 데이터베이스(RDB)&lt;/b&gt;다.&lt;br /&gt;이건 데이터를 표(테이블) 형태로 관리하는 시스템인데, 엑셀 시트를 떠올리면 생각보다 훨씬 친숙하게 다가온다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;785&quot; data-start=&quot;724&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;744&quot; data-start=&quot;724&quot;&gt;하나의 표가 하나의 데이터 덩어리&lt;/li&gt;
&lt;li data-end=&quot;765&quot; data-start=&quot;745&quot;&gt;행(Row)은 실제 데이터 한 건&lt;/li&gt;
&lt;li data-end=&quot;785&quot; data-start=&quot;766&quot;&gt;열(Column)은 각각의 속성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;821&quot; data-start=&quot;787&quot; data-ke-size=&quot;size16&quot;&gt;여기까지만 이해해도 전체 구조가 크게 어렵게 느껴지지 않는다.&lt;/p&gt;
&lt;hr data-end=&quot;826&quot; data-start=&quot;823&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;841&quot; data-start=&quot;828&quot; data-ke-size=&quot;size26&quot;&gt;왜 관계형일까?&lt;/h2&gt;
&lt;p data-end=&quot;878&quot; data-start=&quot;842&quot; data-ke-size=&quot;size16&quot;&gt;배우면서 제일 인상 깊었던 부분이 바로 이 &lt;b&gt;관계&lt;/b&gt;라는 개념이다.&lt;/p&gt;
&lt;p data-end=&quot;946&quot; data-start=&quot;880&quot; data-ke-size=&quot;size16&quot;&gt;데이터를 하나의 큰 테이블에 몰아넣지 않고, 성격이 다른 데이터끼리 나눠서 저장한 뒤 서로 필요한 부분만 연결한다.&lt;/p&gt;
&lt;p data-end=&quot;954&quot; data-start=&quot;948&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;993&quot; data-start=&quot;955&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;967&quot; data-start=&quot;955&quot;&gt;회원은 회원 테이블&lt;/li&gt;
&lt;li data-end=&quot;980&quot; data-start=&quot;968&quot;&gt;상품은 상품 테이블&lt;/li&gt;
&lt;li data-end=&quot;993&quot; data-start=&quot;981&quot;&gt;주문은 주문 테이블&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1028&quot; data-start=&quot;995&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 나눠 놓고, 공통되는 값(키)을 통해 서로 연결한다.&lt;/p&gt;
&lt;p data-end=&quot;1073&quot; data-start=&quot;1030&quot; data-ke-size=&quot;size16&quot;&gt;이 구조 덕분에 데이터가 깔끔해지고, 중복이 줄어들고, 관리가 훨씬 쉬워진다.&lt;/p&gt;
&lt;hr data-end=&quot;1078&quot; data-start=&quot;1075&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1113&quot; data-start=&quot;1080&quot; data-ke-size=&quot;size26&quot;&gt;잘못 설계하면 생기는 문제, 이상 현상(Anomaly)&lt;/h2&gt;
&lt;p data-end=&quot;1179&quot; data-start=&quot;1115&quot; data-ke-size=&quot;size16&quot;&gt;친절하게 알려주는 부분만 있는 건 아니었다.&lt;br /&gt;설계를 잘 못하면 오히려 문제가 터질 수 있다는 것도 배우게 됐다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1281&quot; data-start=&quot;1181&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1215&quot; data-start=&quot;1181&quot;&gt;데이터를 추가하려는데 이상한 값까지 같이 넣어야 하는 상황&lt;/li&gt;
&lt;li data-end=&quot;1243&quot; data-start=&quot;1216&quot;&gt;같은 데이터를 여러 곳에서 수정해야 하는 상황&lt;/li&gt;
&lt;li data-end=&quot;1281&quot; data-start=&quot;1244&quot;&gt;데이터를 지우다가 없어지면 안 되는 정보까지 같이 삭제되는 상황&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1315&quot; data-start=&quot;1283&quot; data-ke-size=&quot;size16&quot;&gt;이런 문제들을 &lt;b&gt;이상 현상(Anomaly)&lt;/b&gt;라고 한다.&lt;/p&gt;
&lt;p data-end=&quot;1441&quot; data-start=&quot;1317&quot; data-ke-size=&quot;size16&quot;&gt;그래서 등장한 개념이 &lt;b&gt;정규화(Normalization)&lt;/b&gt;인데, 데이터를 적절히 나누고, 규칙적으로 정리해서 문제를 최소화하는 과정이라고 이해했다.&lt;br /&gt;말 그대로 &lt;b&gt;데이터를 건강하게 정리하는 작업&lt;/b&gt;이라는 느낌이었다.&lt;/p&gt;
&lt;hr data-end=&quot;1446&quot; data-start=&quot;1443&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1483&quot; data-start=&quot;1448&quot; data-ke-size=&quot;size26&quot;&gt;무결성과 제약 조건, 믿을 수 있는 데이터를 만드는 장치들&lt;/h2&gt;
&lt;p data-end=&quot;1553&quot; data-start=&quot;1485&quot; data-ke-size=&quot;size16&quot;&gt;또 하나 중요한 개념이 &lt;b&gt;무결성(Integrity)&lt;/b&gt;이다.&lt;br /&gt;데이터가 &amp;ldquo;올바른 상태&amp;rdquo;를 유지하도록 강제하는 개념이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1652&quot; data-start=&quot;1555&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1592&quot; data-start=&quot;1555&quot;&gt;Primary Key는 비어 있으면 안 되고, 중복될 수 없다.&lt;/li&gt;
&lt;li data-end=&quot;1624&quot; data-start=&quot;1593&quot;&gt;Foreign Key는 존재하는 값만 참조해야 한다.&lt;/li&gt;
&lt;li data-end=&quot;1652&quot; data-start=&quot;1625&quot;&gt;컬럼마다 허용되는 값의 규칙을 정할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1733&quot; data-start=&quot;1654&quot; data-ke-size=&quot;size16&quot;&gt;여기에 더해, 데이터베이스에는 제약 조건(Constraint)을 걸어서 실제로 규칙을 어기면 아예 저장 자체가 되지 않도록 만들 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1800&quot; data-start=&quot;1735&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1748&quot; data-start=&quot;1735&quot;&gt;PRIMARY KEY&lt;/li&gt;
&lt;li data-end=&quot;1762&quot; data-start=&quot;1749&quot;&gt;FOREIGN KEY&lt;/li&gt;
&lt;li data-end=&quot;1773&quot; data-start=&quot;1763&quot;&gt;NOT NULL&lt;/li&gt;
&lt;li data-end=&quot;1782&quot; data-start=&quot;1774&quot;&gt;UNIQUE&lt;/li&gt;
&lt;li data-end=&quot;1790&quot; data-start=&quot;1783&quot;&gt;CHECK&lt;/li&gt;
&lt;li data-end=&quot;1800&quot; data-start=&quot;1791&quot;&gt;DEFAULT&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1898&quot; data-start=&quot;1802&quot; data-ke-size=&quot;size16&quot;&gt;이런 것들이 전부 데이터 안전장치 역할을 한다는 걸 알게 되면서, &lt;b&gt;데이터베이스가 단순 저장소가 아니라, 신뢰성을 보장해 주는 시스템&lt;/b&gt;이라는 걸 더 확실히 느끼게 됐다.&lt;/p&gt;
&lt;hr data-end=&quot;1903&quot; data-start=&quot;1900&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1918&quot; data-start=&quot;1905&quot; data-ke-size=&quot;size26&quot;&gt;정리하면서 느낀 점&lt;/h2&gt;
&lt;p data-end=&quot;2059&quot; data-start=&quot;1920&quot; data-ke-size=&quot;size16&quot;&gt;처음 데이터베이스를 접했을 때는 그냥 &lt;b&gt;데이터 저장하는 곳&lt;/b&gt;&amp;nbsp;정도로 생각했다.&lt;br /&gt;하지만 배우고 정리하면서 느낀 건, 데이터베이스는 단순 저장을 넘어서 &lt;b&gt;데이터를 얼마나 안전하고 정확하게 관리할 수 있느냐&lt;/b&gt;를 책임지는 핵심 시스템이라는 점이었다.&lt;/p&gt;
&lt;p data-end=&quot;2151&quot; data-start=&quot;2061&quot; data-ke-size=&quot;size16&quot;&gt;관계형 데이터베이스가 표 기반 구조를 사용하는 이유, 정규화와 무결성이 왜 중요한지,&lt;br /&gt;제약 조건이 왜 필수인지까지 연결되면서 전체 흐름이 점점 명확해졌다.&lt;/p&gt;
&lt;p data-end=&quot;2241&quot; data-start=&quot;2153&quot; data-ke-size=&quot;size16&quot;&gt;앞으로 실제 프로젝트에서 사용자 정보, 주문 기록, 서비스 데이터 등을 다루게 될 텐데, 오늘 정리한 이 개념들이 큰 기반이 될 것 같다는 생각이 들었다.&lt;/p&gt;
&lt;p data-end=&quot;2267&quot; data-start=&quot;2243&quot; data-ke-size=&quot;size16&quot;&gt;한 문장으로 정리하면, 이렇게 남기고 싶다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2343&quot; data-start=&quot;2269&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;관계형 데이터베이스는 데이터를 단순히 저장하는 도구가 아니라, 정확하고 안전하게 &amp;lsquo;관리&amp;rsquo;하기 위한 구조적인 시스템이다.&lt;/b&gt;&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/3</guid>
      <comments>https://kgee0503.tistory.com/3#entry3comment</comments>
      <pubDate>Tue, 6 Jan 2026 17:38:24 +0900</pubDate>
    </item>
    <item>
      <title>Vue.js Props</title>
      <link>https://kgee0503.tistory.com/2</link>
      <description>&lt;p data-end=&quot;303&quot; data-start=&quot;154&quot; data-ke-size=&quot;size16&quot;&gt;Vue.js에서 컴포넌트를 사용하다 보면, 같은 컴포넌트를 상황에 따라 다르게 보여줘야 하는 경우가 많다. 예를 들어 글자 색만 다르게 보여주고 싶다거나, 같은 디자인의 카드인데 내용만 다르게 쓰고 싶을 때가 있다. 이럴 때 사용하는 것이 바로 &lt;b&gt;Props&lt;/b&gt;이다.&lt;/p&gt;
&lt;hr data-end=&quot;308&quot; data-start=&quot;305&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;325&quot; data-start=&quot;310&quot; data-ke-size=&quot;size26&quot;&gt;Props란 무엇인가?&lt;/h2&gt;
&lt;p data-end=&quot;396&quot; data-start=&quot;327&quot; data-ke-size=&quot;size16&quot;&gt;Props는 &lt;b&gt;부모 컴포넌트가 자식 컴포넌트로 값을 전달하는 방법&lt;/b&gt;이다.&lt;br /&gt;한 문장으로 정리하면 이렇게 생각하면 된다.&lt;/p&gt;
&lt;blockquote data-end=&quot;426&quot; data-start=&quot;398&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;426&quot; data-start=&quot;400&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;Props = 부모가 주고, 자식이 받는 값&amp;rdquo;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;531&quot; data-start=&quot;428&quot; data-ke-size=&quot;size16&quot;&gt;데이터 흐름은 항상 부모에서 자식 방향으로만 흐르는 &lt;b&gt;단방향 구조&lt;/b&gt;이며, 자식 컴포넌트는 받은 값을 읽어서 사용만 할 수 있다.&lt;br /&gt;그래서 Props는 &amp;ldquo;읽기 전용&amp;rdquo;이라고 표현한다.&lt;/p&gt;
&lt;hr data-end=&quot;536&quot; data-start=&quot;533&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;554&quot; data-start=&quot;538&quot; data-ke-size=&quot;size26&quot;&gt;Props가 필요한 이유&lt;/h2&gt;
&lt;p data-end=&quot;668&quot; data-start=&quot;556&quot; data-ke-size=&quot;size16&quot;&gt;컴포넌트를 사용하는 이유는 재사용성 때문이다.&lt;br /&gt;하지만 완전히 같은 UI만 계속 반복해서 쓰기에는 한계가 있다.&lt;br /&gt;같은 컴포넌트지만, 상황마다 다른 데이터를 보여주고 싶을 때 Props가 필요하다.&lt;/p&gt;
&lt;blockquote data-end=&quot;717&quot; data-start=&quot;670&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;717&quot; data-start=&quot;672&quot; data-ke-size=&quot;size16&quot;&gt;같은 컴포넌트 + 다른 데이터&lt;br /&gt;&amp;rarr; 재사용은 유지하면서 내용만 바꿀 수 있음&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;722&quot; data-start=&quot;719&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;741&quot; data-start=&quot;724&quot; data-ke-size=&quot;size26&quot;&gt;Props가 동작하는 흐름&lt;/h2&gt;
&lt;p data-end=&quot;771&quot; data-start=&quot;743&quot; data-ke-size=&quot;size16&quot;&gt;Props의 흐름을 간단하게 정리하면 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;861&quot; data-start=&quot;773&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;809&quot; data-start=&quot;773&quot;&gt;자식 컴포넌트는 &amp;ldquo;이런 값을 받을 수 있다&amp;rdquo;라고 선언한다&lt;/li&gt;
&lt;li data-end=&quot;834&quot; data-start=&quot;810&quot;&gt;부모 컴포넌트가 실제 값을 넘겨준다&lt;/li&gt;
&lt;li data-end=&quot;861&quot; data-start=&quot;835&quot;&gt;자식 컴포넌트는 그 값을 화면에서 사용한다&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;895&quot; data-start=&quot;863&quot; data-ke-size=&quot;size16&quot;&gt;이 흐름이 이해되면, Props 구조는 크게 어렵지 않다.&lt;/p&gt;
&lt;hr data-end=&quot;900&quot; data-start=&quot;897&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;928&quot; data-start=&quot;902&quot; data-ke-size=&quot;size26&quot;&gt;Props가 undefined가 되는 상황&lt;/h2&gt;
&lt;p data-end=&quot;964&quot; data-start=&quot;930&quot; data-ke-size=&quot;size16&quot;&gt;처음 Props를 쓰면 가장 많이 만나는 문제가 바로 이거다.&lt;/p&gt;
&lt;blockquote data-end=&quot;1001&quot; data-start=&quot;966&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1001&quot; data-start=&quot;968&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;분명 Props를 썼는데 값이 undefined로 나온다&amp;rdquo;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1019&quot; data-start=&quot;1003&quot; data-ke-size=&quot;size16&quot;&gt;대부분 이런 경우에 발생한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1100&quot; data-start=&quot;1021&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1041&quot; data-start=&quot;1021&quot;&gt;부모가 값을 보내지 않았을 때&lt;/li&gt;
&lt;li data-end=&quot;1071&quot; data-start=&quot;1042&quot;&gt;부모와 자식의 Props 이름이 서로 다를 때&lt;/li&gt;
&lt;li data-end=&quot;1100&quot; data-start=&quot;1072&quot;&gt;부모에서 전달하려는 값 자체가 비어 있을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1142&quot; data-start=&quot;1102&quot; data-ke-size=&quot;size16&quot;&gt;즉, 구조 자체가 잘못된 게 아니라 &amp;ldquo;&lt;b&gt;값이 실제로 들어오냐&lt;/b&gt;&amp;rdquo;가 중요하다.&lt;/p&gt;
&lt;hr data-end=&quot;1147&quot; data-start=&quot;1144&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1164&quot; data-start=&quot;1149&quot; data-ke-size=&quot;size26&quot;&gt;Props 기본값 개념&lt;/h2&gt;
&lt;p data-end=&quot;1263&quot; data-start=&quot;1166&quot; data-ke-size=&quot;size16&quot;&gt;Props는 언제든 안 들어올 수도 있기 때문에 &amp;ldquo;기본값&amp;rdquo; 개념이 필요하다.&lt;br /&gt;Vue에서는 기본값을 설정해 두면, 값이 전달되지 않아도 안정적으로 동작하도록 만들 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1317&quot; data-start=&quot;1265&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 기본값을 설정해두는 습관을 들이면 예상치 못한 undefined 문제를 줄일 수 있다.&lt;/p&gt;
&lt;hr data-end=&quot;1322&quot; data-start=&quot;1319&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1342&quot; data-start=&quot;1324&quot; data-ke-size=&quot;size26&quot;&gt;Props 요약&lt;/h2&gt;
&lt;p data-end=&quot;1363&quot; data-start=&quot;1344&quot; data-ke-size=&quot;size16&quot;&gt;Props는 이렇게 기억하면 된다.&lt;/p&gt;
&lt;blockquote data-end=&quot;1424&quot; data-start=&quot;1365&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1424&quot; data-start=&quot;1367&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;Props는 부모가 자식에게 값을 전달하는 통로이고, 자식은 그 값을 읽어서 사용하는 역할을 한다.&amp;rdquo;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1498&quot; data-start=&quot;1426&quot; data-ke-size=&quot;size16&quot;&gt;컴포넌트를 제대로 활용하려면 꼭 이해해야 하는 개념이고, 실제 프로젝트를 하게 되면 거의 필수처럼 계속 사용하게 될 개념이다.&lt;/p&gt;
&lt;p data-end=&quot;1498&quot; data-start=&quot;1426&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;29&quot; data-start=&quot;26&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;44&quot; data-start=&quot;31&quot; data-ke-size=&quot;size26&quot;&gt;정리하면서 느낀 점&lt;/h2&gt;
&lt;p data-end=&quot;258&quot; data-start=&quot;98&quot; data-ke-size=&quot;size16&quot;&gt;Props를 정리하면서 가장 크게 느낀 건, 단순히 &amp;ldquo;부모가 자식에게 값을 넘겨준다&amp;rdquo;라는 문장 하나로 끝나는 개념이 아니라는 점이었다.&lt;br /&gt;처음에는 그냥 기능 중 하나라고만 생각했는데, 공부하다 보니 컴포넌트를 &amp;ldquo;진짜 재사용 가능한 단위&amp;rdquo;로 만들어 주는 핵심이라는 걸 확실히 알게 됐다.&lt;/p&gt;
&lt;p data-end=&quot;451&quot; data-start=&quot;260&quot; data-ke-size=&quot;size16&quot;&gt;특히 undefined가 뜨는 상황이나 기본값 개념을 같이 보면서, 단순히 문법만 아는 것과 구조를 이해하는 건 확실히 다르다는 것도 느꼈다. 앞으로 Vue로 작업할 때, 그냥 props를 &amp;ldquo;넘긴다&amp;rdquo; 수준이 아니라, &lt;b&gt;언제 값이 없을 수 있는지, 어떤 흐름으로 데이터가 내려가는지까지 같이 생각해야 한다&lt;/b&gt;는 걸 기억해 두면 좋을 것 같다.&lt;/p&gt;
&lt;p data-end=&quot;1498&quot; data-start=&quot;1426&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1498&quot; data-start=&quot;1426&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/2</guid>
      <comments>https://kgee0503.tistory.com/2#entry2comment</comments>
      <pubDate>Tue, 30 Dec 2025 18:18:57 +0900</pubDate>
    </item>
    <item>
      <title>비동기(Asynchronous)</title>
      <link>https://kgee0503.tistory.com/1</link>
      <description>&lt;p data-end=&quot;294&quot; data-start=&quot;111&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 자바스크립트에서 정말 많이 쓰이고, 또 헷갈리기 쉬운 개념인 &lt;b&gt;비동기 처리&lt;/b&gt;에 대해 정리해보려고 한다. 수업 들으면서도 그렇고, 직접 정리하면서 느낀 거지만, 이 개념이 정확히 잡히지 않으면 이후에 나오는 &lt;b&gt;API 호출이나 서버 통신&lt;/b&gt; 같은 부분에서 계속 막히게 될 것 같아서 한 번 정리해 두면 좋을 것 같았다.&lt;/p&gt;
&lt;hr data-end=&quot;299&quot; data-start=&quot;296&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;314&quot; data-start=&quot;301&quot; data-ke-size=&quot;size26&quot;&gt;비동기란 무엇일까?&lt;/h2&gt;
&lt;p data-end=&quot;483&quot; data-start=&quot;316&quot; data-ke-size=&quot;size16&quot;&gt;비동기 처리는 한 줄로 정리하면 &lt;b&gt;기다리지 않고 다른 일을 먼저 하면서, 끝나면 다시 처리하는 방식&lt;/b&gt;이다.&lt;br /&gt;작업 중에 시간이 오래 걸리는 일이 있으면 그 자리에서 멈춰서 계속 기다리는 것이 아니라, &lt;b&gt;그동안 다른 코드부터 실행하고 있다가&lt;/b&gt;, 나중에 결과가 준비되면 그때 다시 처리한다.&lt;/p&gt;
&lt;p data-end=&quot;613&quot; data-start=&quot;485&quot; data-ke-size=&quot;size16&quot;&gt;웹에서는 &lt;b&gt;서버 요청, 데이터 불러오기, API 통신&lt;/b&gt; 같은 작업들이 시간이 걸리기 때문에 비동기 처리가 정말 중요하다. 만약 이런 것들이 전부 동기로 동작한다면, 화면이 멈춘 것처럼 보이고 사용자 경험이 크게 나빠질 것이다.&lt;/p&gt;
&lt;hr data-end=&quot;618&quot; data-start=&quot;615&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;634&quot; data-start=&quot;620&quot; data-ke-size=&quot;size26&quot;&gt;동기와 비동기의 차이&lt;/h2&gt;
&lt;p data-end=&quot;679&quot; data-start=&quot;636&quot; data-ke-size=&quot;size16&quot;&gt;비동기를 이해할 때 가장 도움이 된 건 &lt;b&gt;동기 방식과 비교&lt;/b&gt;하는 것이었다.&lt;/p&gt;
&lt;p data-end=&quot;785&quot; data-start=&quot;681&quot; data-ke-size=&quot;size16&quot;&gt;동기 방식은 &lt;b&gt;모든 작업이 순서대로 진행&lt;/b&gt;된다.&lt;br /&gt;앞에 있는 작업이 끝나야 &lt;b&gt;다음 작업이 실행&lt;/b&gt;된다.&lt;br /&gt;그래서 앞의 작업이 오래 걸리면 뒤에 있는 작업들도 전부 기다려야 한다.&lt;/p&gt;
&lt;p data-end=&quot;969&quot; data-start=&quot;787&quot; data-ke-size=&quot;size16&quot;&gt;반면 비동기 방식은 &lt;b&gt;오래 걸리는 작업을 따로 맡겨두고&lt;/b&gt;, 그 사이에 실행 가능한 다른 작업을 먼저 처리한다. 그리고 기다리던 작업이 끝나면, 그 결과를 나중에 처리한다.&lt;br /&gt;그래서&lt;b&gt; 실행 순서와 결과 순서가 다를 수 있다는 점&lt;/b&gt;이 특징이다. 처음엔 이 부분이 헷갈리지만, 구조를 이해하면 충분히 납득되는 부분이다.&lt;/p&gt;
&lt;hr data-end=&quot;974&quot; data-start=&quot;971&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;999&quot; data-start=&quot;976&quot; data-ke-size=&quot;size26&quot;&gt;자바스크립트가 비동기를 처리하는 방식&lt;/h2&gt;
&lt;p data-end=&quot;1077&quot; data-start=&quot;1001&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트는 기본적으로 &lt;b&gt;한 번에 하나의 작업만 처리하는 언어&lt;/b&gt;인데, 그럼에도 불구하고 비동기가 가능한 이유는 내부 구조 때문이다.&lt;/p&gt;
&lt;p data-end=&quot;1288&quot; data-start=&quot;1079&quot; data-ke-size=&quot;size16&quot;&gt;현재 실행 중인 코드를 처리하는 영역이 따로 있고, &lt;b&gt;시간이 오래 걸리는 작업은 별도로 맡겨 두었다가&lt;/b&gt;, 작업이 끝나면 다시 실행 가능한 상태로 옮겨 처리한다.&lt;br /&gt;이 덕분에 코드가 위에서 아래로 실행되는데도, &lt;b&gt;실제 결과는 다른 순서로 나오는 상황&lt;/b&gt;이 만들어진다.&lt;br /&gt;이 구조를 이해하고 나니 &amp;ldquo;왜 분명 위에 쓴 코드가 나중에 실행되지?&amp;rdquo;라는 의문이 조금씩 풀렸다.&lt;/p&gt;
&lt;hr data-end=&quot;1293&quot; data-start=&quot;1290&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1307&quot; data-start=&quot;1295&quot; data-ke-size=&quot;size26&quot;&gt;콜백과 콜백 지옥&lt;/h2&gt;
&lt;p data-end=&quot;1405&quot; data-start=&quot;1309&quot; data-ke-size=&quot;size16&quot;&gt;처음 비동기를 처리할 때 많이 사용하는 방식이 &lt;b&gt;콜백 함수&lt;/b&gt;이다.&lt;br /&gt;작업이 끝난 뒤에 실행할 코드를 미리 함수로 넘겨주고, 완료되었을 때 그 함수를 실행하는 방식이다.&lt;/p&gt;
&lt;p data-end=&quot;1546&quot; data-start=&quot;1407&quot; data-ke-size=&quot;size16&quot;&gt;문제는 비동기 작업이 많아질 때 생긴다.&lt;br /&gt;콜백 안에 콜백, 그 안에 또 콜백&amp;hellip; 이런 구조가 반복되면서 코드가 점점 안쪽으로 파고들고, 이 상황을 &lt;b&gt;콜백 지옥&lt;/b&gt;이라고 부른다.&lt;br /&gt;이렇게 되면 &lt;b&gt;가독성도 떨어지고, 유지보수도 어려워진다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-end=&quot;1551&quot; data-start=&quot;1548&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1578&quot; data-start=&quot;1553&quot; data-ke-size=&quot;size26&quot;&gt;Promise와 async / await&lt;/h2&gt;
&lt;p data-end=&quot;1728&quot; data-start=&quot;1580&quot; data-ke-size=&quot;size16&quot;&gt;콜백 지옥 문제를 해결하기 위해 등장한 것이 &lt;b&gt;Promise&lt;/b&gt;이다.&lt;br /&gt;Promise는 &lt;b&gt;&amp;ldquo;작업이 성공하면 이렇게, 실패하면 이렇게 처리하겠다&amp;rdquo;&lt;/b&gt; 라는 흐름을 깔끔하게 표현해 주는 방식이다.&lt;br /&gt;이 덕분에 비동기 코드 구조가 훨씬 정리되고 이해하기 쉬워졌다.&lt;/p&gt;
&lt;p data-end=&quot;1891&quot; data-start=&quot;1730&quot; data-ke-size=&quot;size16&quot;&gt;여기서 한 단계 더 발전한 방식이 &lt;b&gt;async / await&lt;/b&gt;이다.&lt;br /&gt;이 문법을 사용하면 &lt;b&gt;비동기 코드를 마치 일반 코드처럼 자연스럽게 읽히도록 작성&lt;/b&gt;할 수 있다.&lt;br /&gt;실제로도 많이 쓰이고, 가독성도 좋아서 앞으로 비동기 처리를 할 때 가장 많이 사용할 것 같다는 생각이 들었다.&lt;/p&gt;
&lt;hr data-end=&quot;1896&quot; data-start=&quot;1893&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1911&quot; data-start=&quot;1898&quot; data-ke-size=&quot;size26&quot;&gt;정리하면서 느낀 점&lt;/h2&gt;
&lt;p data-end=&quot;2033&quot; data-start=&quot;1913&quot; data-ke-size=&quot;size16&quot;&gt;비동기는 처음엔 단순히 &lt;b&gt;&amp;ldquo;순서가 이상한 코드&amp;rdquo;&lt;/b&gt; 정도로만 느껴졌는데,&lt;br /&gt;오늘 정리하면서 &lt;b&gt;왜 이런 방식이 필요한지&lt;/b&gt;, 그리고 &lt;b&gt;웹에서 비동기가 얼마나 중요한 개념인지&lt;/b&gt; 제대로 이해하게 된 것 같다.&lt;/p&gt;
&lt;p data-end=&quot;2135&quot; data-start=&quot;2035&quot; data-ke-size=&quot;size16&quot;&gt;지금은 개념적으로 이해한 단계지만, 나중에 실제 프로젝트에서 &lt;b&gt;API 연결, 데이터 통신, 서버 연동&lt;/b&gt; 같은 걸 하게 되면&lt;br /&gt;오늘 정리한 내용이 많이 도움이 될 것 같다.&lt;/p&gt;
&lt;p data-end=&quot;2203&quot; data-start=&quot;2137&quot; data-ke-size=&quot;size16&quot;&gt;특히 기억하고 싶은 문장은 이거 하나다.&lt;br /&gt;&lt;b&gt;&amp;ldquo;비동기는 멈추지 않고, 기다리지 않으며, 나중에 다시 처리한다.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;</description>
      <author>Gani053</author>
      <guid isPermaLink="true">https://kgee0503.tistory.com/1</guid>
      <comments>https://kgee0503.tistory.com/1#entry1comment</comments>
      <pubDate>Fri, 26 Dec 2025 20:46:54 +0900</pubDate>
    </item>
  </channel>
</rss>