1004 - 1010


# 1004 - 1010

# 1005 - ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ, ๋ธ”๋Ÿญ๊ณผ ๋„Œ๋ธ”๋Ÿญ

๋™๊ธฐ(Synchronous)์™€ ๋น„๋™๊ธฐ(Asynchronous), ๊ทธ๋ฆฌ๊ณ  ๋ธ”๋Ÿญ(Blocking)๊ณผ ๋„Œ๋ธ”๋Ÿญ(Non-blocking)

# Blocking / Non-blocking

ํ–‰์œ„์ž๊ฐ€ ์ทจํ•œ ํ–‰์œ„ ์ž์ฒด๊ฐ€, ๋˜๋Š” ๊ทธ ํ–‰์œ„๋กœ ์ธํ•ด ๋‹ค๋ฅธ ๋ฌด์—‡์ด ๋ง‰ํ˜€๋ฒ„๋ฆฐ, ์ œํ•œ๋œ, ๋Œ€๊ธฐํ•˜๋Š” ์ƒํƒœ. ๋Œ€๊ฐœ์˜ ๊ฒฝ์šฐ์—๋Š” ๋‚˜ ์ด์™ธ์˜ ๋Œ€์ƒ์œผ๋กœ ํ•˜์—ฌ๊ธˆ ๋‚ด๊ฐ€ Block ๋‹นํ•˜๊ฒ ์ง€๋งŒ(Blocked), ์–ด์ฐŒ ๋˜์—ˆ๋“  ๋ฌธ์ž ์ž์ฒด๋กœ๋Š” ๋‚˜๋ผ๋Š” ***๋‹จ์ผ ๊ฐœ์ฒด ์Šค์Šค๋กœ์˜ ์ƒํƒœ***๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

  • ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๊ฐ€ ์ž์‹ ์ด ํ•  ์ผ์„ ๋ชจ๋‘ ๋งˆ์น  ๋•Œ๊นŒ์ง€ ์ œ์–ด๊ถŒ์„ ๊ณ„์† ๊ฐ€์ง€๊ณ ์„œ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜์—๊ฒŒ ๋ฐ”๋กœ ๋Œ๋ ค์ฃผ์ง€ ์•Š์œผ๋ฉด Block
  • ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๊ฐ€ ์ž์‹ ์ด ํ•  ์ผ์„ ์ฑ„ ๋งˆ์น˜์ง€ ์•Š์•˜๋”๋ผ๋„ ๋ฐ”๋กœ ์ œ์–ด๊ถŒ์„ ๊ฑด๋„ค์ฃผ์–ด(return) ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ์ผ์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋ฉด Non-block

# Synchronous / Asynchronous

***๋™์‹œ์— ๋ฐœ์ƒํ•˜๋Š”***๊ฒƒ๋“ค. ๋™์‹œ๋ผ๋Š” ๊ฒƒ์€ ์ฆ‰, ์‹œ(time)๋ผ๋Š” ๋‹จ์ผ๊ณ„(system)์—์„œ ๊ฐ™์ด, ํ•จ๊ป˜ ๋ฌด์–ธ๊ฐ€๊ฐ€ ์ด๋ฃจ์–ด์ง€๋Š” ๋‘ ๊ฐœ ์ด์ƒ์˜ ๊ฐœ์ฒด ํ˜น์€ ์ด๋ฒคํŠธ๋ฅผ ์˜๋ฏธํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜์˜ ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ ๋ฐ ์ข…๋ฃŒ๋ฅผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜๊ฐ€(ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๋ฟ ์•„๋‹ˆ๋ผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜๋„ ํ•จ๊ป˜) ์‹ ๊ฒฝ ์“ฐ๋ฉด Synchronous
  • ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜์˜ ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ ๋ฐ ์ข…๋ฅ˜๋ฅผ ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜ ํ˜ผ์ž ์ง์ ‘ ์‹ ๊ฒฝ ์“ฐ๊ณ  ์ฒ˜๋ฆฌํ•œ๋‹ค๋ฉด(as a callback function) Asynchronus

# ์˜ˆ์ œ

# Blocking & Synchronous

๋‚˜ : ๋Œ€ํ‘œ๋‹˜, ๊ฐœ๋ฐœ์ž ์ข€ ๋” ๋ฝ‘์•„์ฃผ์„ธ์š”..
๋Œ€ํ‘œ๋‹˜ : ์˜ค์ผ€์ด, ์ž ๊น๋งŒ ๊ฑฐ๊ธฐ ๊ณ„์„ธ์š”!
๋‚˜ : โ€ฆ?!!
๋Œ€ํ‘œ๋‹˜ : (์ฑ„์šฉ ๊ณต๊ณ  ๋“ฑ๋ก.. ์ง€์›์ž ์—ฐ๋ฝ.. ๋ฉด์ ‘ ์ง„ํ–‰.. ์—ฐ๋ด‰ ํ˜‘์ƒ..)
๋‚˜ : (๊ณผ์ • ์ง€์ผœ๋ด„.. ๊ถ๊ธˆํ•จ.. ์–ด์ฐจํ”ผ ๋‚ด ์ผ ํ•˜๋Ÿฌ๋Š” ๋ชป ๊ฐ€๊ณ  ๊ณ„์† ์„œ ์žˆ์Œ)

# Blocking & Asynchronous

๋‚˜ : ๋Œ€ํ‘œ๋‹˜, ๊ฐœ๋ฐœ์ž ์ข€ ๋” ๋ฝ‘์•„์ฃผ์„ธ์š”..
๋Œ€ํ‘œ๋‹˜ : ์˜ค์ผ€์ด, ์ž ๊น๋งŒ ๊ฑฐ๊ธฐ ๊ณ„์„ธ์š”!
๋‚˜ : โ€ฆ?!!
๋Œ€ํ‘œ๋‹˜ : (์ฑ„์šฉ ๊ณต๊ณ  ๋“ฑ๋ก.. ์ง€์›์ž ์—ฐ๋ฝ.. ๋ฉด์ ‘ ์ง„ํ–‰.. ์—ฐ๋ด‰ ํ˜‘์ƒ..)
๋‚˜ : (์•ˆ ๊ถ๊ธˆํ•จ.. ์ง€๋‚˜๊ฐ€๋Š” ๋ง๋กœ ์—ฌ์ญˆ์—ˆ๋Š”๋ฐ ๋ถ™์žกํ˜€๋ฒ„๋ฆผ.. ๋”ด ์ƒ๊ฐ.. ๋ชป ๊ฐ€๊ณ  ๊ณ„์† ์„œ ์žˆ์Œ)

# Non-blocking & Synchronous

๋‚˜ : ๋Œ€ํ‘œ๋‹˜, ๊ฐœ๋ฐœ์ž ์ข€ ๋” ๋ฝ‘์•„์ฃผ์„ธ์š”..
๋Œ€ํ‘œ๋‹˜ : ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ€์„œ ๋ณผ ์ผ ๋ณด์„ธ์š”.
๋‚˜ : ๋„ต!
๋Œ€ํ‘œ๋‹˜ : (์ฑ„์šฉ ๊ณต๊ณ  ๋“ฑ๋ก.. ์ง€์›์ž ์—ฐ๋ฝ.. ๋ฉด์ ‘ ์ง„ํ–‰.. ์—ฐ๋ด‰ ํ˜‘์ƒ..)
๋‚˜ : ์ฑ„์šฉํ•˜์…จ๋‚˜์š”?
๋Œ€ํ‘œ๋‹˜ : ์•„์ง์š”.
๋‚˜ : ์ฑ„์šฉํ•˜์…จ๋‚˜์š”?
๋Œ€ํ‘œ๋‹˜ : ์•„์ง์š”.
๋‚˜ : ์ฑ„์šฉํ•˜์…จ๋‚˜์š”?
๋Œ€ํ‘œ๋‹˜ : ์•„์ง์š”~!!!!!!

# Non-blocking & Asynchronous

๋‚˜ : ๋Œ€ํ‘œ๋‹˜, ๊ฐœ๋ฐœ์ž ์ข€ ๋” ๋ฝ‘์•„์ฃผ์„ธ์š”..
๋Œ€ํ‘œ๋‹˜ : ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ€์„œ ๋ณผ ์ผ ๋ณด์„ธ์š”.
๋‚˜ : ๋„ต!
๋Œ€ํ‘œ๋‹˜ : (์ฑ„์šฉ ๊ณต๊ณ  ๋“ฑ๋ก.. ์ง€์›์ž ์—ฐ๋ฝ.. ๋ฉด์ ‘ ์ง„ํ–‰.. ์—ฐ๋ด‰ ํ˜‘์ƒ..)
๋‚˜ : (์—ด์ผ์ค‘..)
๋Œ€ํ‘œ๋‹˜ : ํ•œ ๋ถ„ ๋ชจ์‹œ๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค~!
๋‚˜ : ๐Ÿ˜

# 1006 - Spring5 WebClient

# WebClient๋ž€?

Spring WebClient๋ž€? ์›น์œผ๋กœ API๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” Non-Blocking ๋ฐฉ์‹์˜ Http Client ๋ชจ๋“ˆ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

Java์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” Http Clent๋Š” RestTemplate์ด๋‹ค. ์ฐจ์ด์ ์€ RestTemplate๋Š” Blocking๋ฐฉ์‹์ด๊ณ , WebClient๋Š” Non-Blocking๋ฐฉ์‹์ด๋‹ค.

# ๊ฐ„๋‹จํ•œ์˜ˆ์ œ

# Building with

  • maven
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
  • gradle
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-webflux'
}

# Instance ์ƒ์„ฑ

WebClient client1 = WebClient.create();
// or
WebClient client1 = WebClient.create("http://localhost:8080");
WebClient client3 = WebClient
                    .builder()
                    .baseUrl()
                    .defaultCookie()
                    .defaultHeader()
                .build();

# WebClient Java Config

@Configuration
@Slf4j
public class WebClientConfig {

    @Bean
    public WebClient webClient() {
        // ExchangeStrategies HTTP ๋ฉ”์„ธ์ง€ reader/writer ์ปค์Šคํ…€
        ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
                                                                  .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024*1024*50))
                                                                  .build();
        exchangeStrategies
            .messageWriters().stream()
            .filter(LoggingCodecSupport.class::isInstance)
            .forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));

        return WebClient.builder()
                .clientConnector(
                    new ReactorClientHttpConnector(
                        HttpClient
                            .create()
                            .secure(
                                ThrowingConsumer.unchecked(
                                    sslContextSpec -> sslContextSpec.sslContext(
                                        SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build()
                                    )
                                )
                            )
                            // timeout ์„ค์ •
                            .tcpConfiguration(
                                client -> client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 120_000)
                                                .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(180))
                                                                           .addHandlerLast(new WriteTimeoutHandler(180))
                                                )
                            )
                    )
                )
                .exchangeStrategies(exchangeStrategies)
                // request ๋กœ๊ทธ
                .filter(ExchangeFilterFunction.ofRequestProcessor(
                    clientRequest -> {
                        log.debug("Request: {} {}", clientRequest.method(), clientRequest.url());
                        clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value)));
                        return Mono.just(clientRequest);
                    }
                ))
                // response ๋กœ๊ทธ
                .filter(ExchangeFilterFunction.ofResponseProcessor(
                    clientResponse -> {
                        clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value)));
                        return Mono.just(clientResponse);
                    }
                ))
                .defaultHeader("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.3")
                .build();
    }
}
  • MaxInMemorySize
    ExchageStrategies.builder()๋ฅผ ํ†ตํ•ด in-memory buffer๊ฐ’์„ ๋ณ€๊ฒฝ (๊ธฐ๋ณธ256KB)

  • Logging
    ExchageStrateges์™€ logging level์„ค์ •

# ์‚ฌ์šฉ

  • @Bean์œผ๋กœ ๋“ฑ๋ก๋œ WebClient๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ
@Service
@RequiredArgsConstructor
@Slf4j
public class SomeService implements SomeInterface {

    private final WebClient webClient;
    public Mono<SomeData> getSomething() {
  
    return webClient.mutate()
                    .build()
                    .get()
                    .uri("/resource")
                    .retrieve()
                    .bodyToMono(SomeData.class);
    }
}

# retrieve(), exchange()

HTTP ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ retrieve()์™€ exchange()๊ฐ€ ์žˆ๋‹ค. Spring์—์„œ๋Š” exchange๋ฅผ ์ด์šฉํ•˜๊ฒŒ ๋˜๋ฉด Response ์ปจํ…์ธ ์— ๋Œ€ํ•œ ๋ชจ๋“  ์ฒ˜๋ฆฌ๋ฅผ ์ง์ ‘ ํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” memory leak ๊ฐ€๋Šฅ์„ฑ ๋–„๋ฌธ์— ๊ฐ€๊ธ‰์  retrieve๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ๊ณ ํ•œ๋‹ค.

Mono<Person> result = webClient.get()
                               .uri("/persons/{id}", id)
                               .accept(MediaType.APPLICATION_JSON) 
                               .retrieve() 
                               .bodyToMono(Person.class);

# 4xx and 5xx์ฒ˜๋ฆฌ

webClient.mutate()
         .baseUrl("https://some.com")
         .build()
         .get()
         .uri("/resource")
         .accept(MediaType.APPLICATION_JSON)
         .retrieve()
         .onStatus(status -> status.is4xxClientError() 
                          || status.is5xxServerError()
             , clientResponse ->
                           clientResponse.bodyToMono(String.class)
                           .map(body -> new RuntimeException(body)))
         .bodyToMono(SomeData.class)

# GET ์˜ˆ์ œ

public Mono<SomeData> getData(Integer id, String accessToken) {
    return
        webClient.mutate()
                 .baseUrl("https://some.com/api")
                 .build()
                 .get()
                 .uri("/resource?id={ID}", id)
                 .accept(MediaType.APPLICATION_JSON)
                 .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
                 .retrieve()
                 .bodyToMono(SomeData.class)
        ;
}

# POST ์˜ˆ์ œ

  • form ๋ฐ์ดํ„ฐ ์ „์†ก
webClient.mutate()
         .baseUrl("https://some.com/api")
         .build()
         .post()
         .uri("/login")
         .contentType(MediaType.APPLICATION_FORM_URLENCODED)
         .accept(MediaType.APPLICATION_JSON)
         .body(BodyInserters.fromFormData("id", idValue)
                            .with("pwd", pwdValue)
         )
         .retrieve()
         .bodyToMono(SomeData.class);
  • JSON body ๋ฐ์ดํ„ฐ ์ „์†ก
webClient.mutate()
         .baseUrl("https://some.com/api")
         .build()
         .post()
         .uri("/login")
         .contentType(MediaType.APPLICATION_JSON)
         .accept(MediaType.APPLICATION_JSON)
         .bodyValue(loginInfo)
         .retrieve()
         .bodyToMono(SomeData.class);

# DELETE

webClient.mutate()
         .baseUrl("https://some.com/api")
         .build()
         .delete()
         .uri("/resource/{ID}", id)
         .retrieve()
         // Void ๋ฐ˜ํ™˜
         .bodyToMono(Void.class);

# 1010 - Inner class์— Static์„ ๋ถ™์ด๋Š” ์ด์œ 

# Nested Class

- Nested classes
    - Inner classes
        - Inner classes
        - Method local Inner classes
        - Anonymous Inner classes (์ต๋ช…ํด๋ž˜์Šค)
    - Static Nested classes

์ž๋ฐ”๋Š” ์ผ๋ฐ˜์ ์ธ ํด๋ž˜์Šค๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ ํด๋ž˜์Šค์˜ ์ค‘์ฒฉ์„ ์ด๋ ‡๊ฒŒ ๋‚˜๋ˆˆ๋‹ค.

# Nested Class

  • ํŒจํ‚ค์ง€๊ฐ€ ๋˜๋Š” ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋‚˜๋จธ์ง€ ํด๋ž˜์Šค
  • ํ•˜๋‚˜์˜ ํŒจํ‚ค์ง€์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ์„œ๋กœ๊ฐ„ ๊ฒฐํ•ฉ๋งŒ์ด ์กด์žฌํ•˜๋Š” ํด๋ž˜์Šค์˜ ๊ฒฝ์šฐ ๊ฐ€๋…์„ฑ์ด ์ข‹๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ํŽธํ•˜๋‹ค.

ํด๋ž˜์Šค๊ฐ€ ๋‹ค๋ฅธ ํด๋ ˆ์Šค์—๋งŒ ์œ ์šฉ ํ•  ๊ฒฝ์šฐ ํ•ด๋‹น ํด๋ž˜์Šค์— ํด๋ž˜์Šค๋ฅผ ํฌํ•จ์‹œํ‚ค๊ณ  ๋‘ ํด๋ž˜์Šค๋ฅผ ํ•ข๊ป˜ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ๋…ผ๋ฆฌ์ ์ด๋‹ค. ์ด๋Ÿฌํ•œ "ํ—ฌํผ ํด๋ž˜์Šค"๋ฅผ ์ค‘์ฒฉํ•˜๋ฉด ํŒจํ‚ค์ง€๊ฐ€ ๋”์šฑ ๊ฐ„์†Œํ™”๋œ๋‹ค.

  • ์ค‘์ฒฉ ํด๋ž˜์Šค๋“ค์€ ํŒจํ‚ค์ง€ ํด๋ž˜์Šค ๋‚ด๋ถ€์— ์ˆจ๊ฒจ์ ธ์žˆ์œผ๋ฏ€๋กœ ์บก์Šํ™”์— ๋„์›€์ด ๋œ๋‹ค.

A์™€ B๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ์ตœ์ƒ์œ„ ํด๋ž˜์Šค๋ฅผ ๊ณ ๋ คํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ B๋Š” ์„ ์–ธ ๋  A์˜ ๋ฉค๋ฒ„์— ์•ก์„ธ์Šคํ•ด์•ผํ•œ๋‹ค. ํด๋ž˜์Šค A ๋‚ด์— ํด๋ž˜์Šค B๋ฅผ ์ˆจ๊ธฐ๋ฉด A์˜ ๊ตฌ์„ฑ์›์„ ๋น„๊ณต๊ฐœ๋กœ ์„ ์–ธํ•˜๊ณ  B๊ฐ€ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ B ์ž์ฒด๋Š” ์™ธ๋ถ€ ์„ธ๊ณ„์—์„œ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

# non-static nested class

  • Inner class๋ผ๊ณ  ํ•˜๋ฉฐ ์™ธ๋ถ€ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋œ๋‹ค.
  • ์™ธ๋ถ€ ์ธ์Šคํ„ด์Šค๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ new๋ฅผ ํ†ตํ•œ ์ธ์Šคํ„ด์Šค ํ• ๋‹น์œผ๋กœ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋Ÿฌ์ฒข ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์™ธ๋ถ€์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋˜๋ฏ€๋กœ ๋‚ด๋ถ€ ํด๋ž˜์Šค๋„ ์™ธ๋ถ€ ํด๋ž˜์Šค์˜ ์ž์›์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
public class Outer {
	class Inner {
    }
  }
  
Outer outer = new Outer();
Outer.Inner inner = new Outer.Inner(); 

# static nested class

  • static์ด ๋ถ™๋Š” ์ค‘์ฒฉ ํด๋ž˜์Šค
  • ๋™์ผํ•œ static ๋ฉค๋ฒ„๋“ค์„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • static์˜ ํŠน์ง•์— ๋”ฐ๋ผ ์™ธ๋ถ€ ์ธ์Šคํ„ด์Šค ๋ฉค๋ฒ„์˜ ์ง์ ‘์ฐธ์กฐ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ
public class Outer {
	static class staticNasted {
    }
  }
  
Outer.Inner staticNasted = new Outer.Inner();

# ์ฐจ์ด

  • ์™ธ๋ถ€ ์ฐธ์กฐ์˜ ์—ฌ๋ถ€
  • ์™ธ๋ถ€ ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋œ๋‹ค๋Š” ๊ฒƒ์€ ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋˜๊ณ  ์žˆ๋‹ค๋Š” ๋œป์œผ๋กœ GC๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšŒ์ˆ˜ํ•  ์ˆ˜์—†๋‹ค. ๋‹น์—ฐํžˆ ์ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ถ€๋ฅด๋Š” ์น˜๋ช…์ ์ธ ๋‹จ์ .
  • ํ•ญ์ƒ ์™ธ๋ถ€ ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ ์ƒ ๋น„ํšจ์œจ์ .
  • ๊ฒฐ๊ตญ ์™ธ๋ถ€ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋ฉด static nested class๊ฐ€ ๋‚ซ๋‹ค.
  • ์—ฌ๊ธฐ์„œ์˜ staitc์˜ ์˜๋ฏธ๋Š” ์™ธ๋ถ€ ์ธ์Šคํ„ด์Šค ์—†์ด ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅด์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ”๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์œผ๋กœ ์‚ฌ์šฉ ๋œ๋‹ค.

# Spring Boot์—์„œ DTO๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ static nested class

  • DTO ์˜ˆ์ œ
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

public class User {

    @Getter
    @AllArgsConstructor
    @Builder
    public static class Info {
        private int id;
        private String name;
        private int age;
    }

    @Getter
    @Setter
    public static class Request {
        private String name;
        private int age;
    }

    @Getter
    @AllArgsConstructor
    public static class Response {
        private Info info;
        private int returnCode;
        private String returnMessage;
    }
}
  • Controller
import com.parksh.demo.dto.DefaultResponse;
import com.parksh.demo.dto.user.User;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(โ€œuserโ€)
public class UserController {

    @GetMapping(โ€œ/{user_id}โ€)
    public User.Response getUser(@PathVariable(โ€œuser_idโ€) String userId) {

        return new User.Response(new User.Info(), 200, โ€œsuccessโ€);
    }

    @PostMapping
    public DefaultResponse addUser(@RequestBody User.Info info) {

        return new DefaultResponse();
    }
}
Last update: September 13, 2022 21:44
Contributors: ahnjs