<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>기발자</title>
    <link>https://joelinseoul.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 08:26:05 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>kibal.countinue</managingEditor>
    <item>
      <title>스웨거(OpenAPI) 로 API 명세서 자동화 하기</title>
      <link>https://joelinseoul.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트 개발자, 기획자 등과 커뮤니케이션 할 때, 기능을 추상화 하여 커뮤니케이션 할 수도 있지만, request 와 response 를 통해 커뮤니케이션 하는 것이 혼선을 줄일 수 있는 좋은 방법이라고 생각한다.&amp;nbsp;&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;&amp;nbsp;Swagger (OpenAPI 와 통합) 를 통해 프론트엔드 연동, QA 등에서 정상동작 여부 및 오류 확인 등의 기준이 되는 API 를 확인해보자.&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;Springboot 2.7.15&lt;/b&gt; 버전이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;1. build.gradle 내 Dependency 추가하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1701335367678&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation &quot;io.springfox:springfox-boot-starter:3.0.0&quot;
implementation &quot;io.springfox:springfox-swagger-ui:3.0.0&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;'springfox-boot-starter'&lt;/b&gt; : SpringBoot 에 Swagger 를 통합하기 위한 스타터 패키지. 모든 컨트롤러와 모델 클래스를 스캔하여 API 문서를 자동으로 생성함.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;'springfox-swagger-ui'&lt;/b&gt; : SwaggerUI를 제공함. 로컬 접속 시 http://localhost:8080/swagger-ui/index.html#/ 경로를 통해 접근할 수 있음.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;2. application.yml 설정하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1701339798916&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  mvc:
    pathmatch:
      matching-strategy: ant-path-matcher&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;내 프로젝트의 환경인 Springboot 2.7.15 버전에서는 URL 매칭 전략을 추가로 설정해야 했다.&amp;nbsp;&lt;br /&gt;설정하지 않으면 documentationPluginsBootstrapper 빈에서 ApplicationContextException 에러가 발생하는 것을 경험했다. (스프링부트 버전과 스프링폭스 3.0 버전의 경로패턴 호환성이 맞지 않는것 같다.)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;2. SwaggerConfig 클래스 생성하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1701335614880&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.iamcaster.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SwaggerConfig {

    @Bean
    public Docket api() {  // Docket:API 문서화 구성
        return new Docket(DocumentationType.OAS_30)//OpenAPI Spec 3.0 사용
        		.groupName(&quot;general&quot;) // 문서의 그룹 지정 가능. 
                .useDefaultResponseMessages(false) // 기본 HttpCode 사용여부 설정
                .select() // 스캔할 API 범위 지정
                .apis(RequestHandlerSelectors.basePackage(&quot;com.iamcaster&quot;))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo());
    }
    
    private ApiInfo apiInfo() { // API 문서의 메타데이터 정의
        return new ApiInfoBuilder()
                .title(&quot;iamcaster api docs&quot;)
                .description(&quot;iamcaster api list&quot;)
                .version(&quot;1.0&quot;)
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Docket 클래스의 주요 메소드&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;table style=&quot;height: 383px;&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 366px;&quot;&gt;메소드&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 488px;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;apiInfo(ApiInfo apiInfo)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;API의 메타데이터를 설정. (제목, 설명, 버전 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;groupName(String groupName)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;API 문서의 그룹 이름을 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;height: 40px; width: 366px;&quot;&gt;select()&lt;/td&gt;
&lt;td style=&quot;height: 40px; width: 488px;&quot;&gt;&lt;code&gt;ApiSelectorBuilder&lt;/code&gt;를 반환하여, API를 선택하고 세부 사항을 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;enable(boolean enabled)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;Swagger를 활성화하거나 비활성화.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;protocols(Set&amp;lt;String&amp;gt; protocols)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;지원하는 프로토콜을 설정. (예: &quot;http&quot;, &quot;https&quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;host(String host)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;API 문서에 사용할 호스트 이름을 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px; width: 366px;&quot;&gt;directModelSubstitute(Class&amp;lt;?&amp;gt; originalClass, Class&amp;lt;?&amp;gt; substituteClass)&lt;/td&gt;
&lt;td style=&quot;height: 34px; width: 488px;&quot;&gt;특정 클래스를 다른 클래스로 대체. (모델 대체)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;alternateTypeRules(AlternateTypeRules alternateTypeRules)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;주어진 타입 규칙에 따라 모델을 변경.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px; width: 366px;&quot;&gt;useDefaultResponseMessages(boolean useDefaultResponseMessages)&lt;/td&gt;
&lt;td style=&quot;height: 34px; width: 488px;&quot;&gt;기본 응답 메시지 사용 여부를 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;height: 40px; width: 366px;&quot;&gt;globalResponseMessage(RequestMethod method, List&amp;lt;ResponseMessage&amp;gt; responseMessages)&lt;/td&gt;
&lt;td style=&quot;height: 40px; width: 488px;&quot;&gt;특정 HTTP 메소드에 대한 전역 응답 메시지를 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px; width: 366px;&quot;&gt;securitySchemes(List&amp;lt;? extends SecurityScheme&amp;gt; securitySchemes)&lt;/td&gt;
&lt;td style=&quot;height: 34px; width: 488px;&quot;&gt;보안 스키마를 설정. (예: API 키, OAuth2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;securityContexts(List&amp;lt;SecurityContext&amp;gt; securityContext)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;보안 컨텍스트를 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;tags(Tag tags)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;API 문서에 사용할 태그를 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 366px;&quot;&gt;pathMapping(String path)&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 488px;&quot;&gt;기본 경로 매핑을 설정.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;3. Controller 에 매핑하기&lt;/p&gt;
&lt;pre id=&quot;code_1701337006714&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Api(tags = {&quot;회원정보 등록, 수정, 삭제&quot;}) // Swagger 문서화 메타데이터.
@RequestMapping(&quot;/rest&quot;)
@RestController
public class UserInfoRestController {
	@ApiOperation(value=&quot;선택약관 동의여부&quot;) // endpoint 별 설명
	@ApiResponses(value = { // response 별 설명
	@ApiResponse(code = 200, message = &quot;성공적으로 처리됨&quot;, response = ResultResponse.class),
	@ApiResponse(code = 400, message = &quot;잘못된 요청&quot;),
	@ApiResponse(code = 500, message = &quot;서버 오류&quot;)
	})
	@GetMapping(&quot;/terms/optionalAgreed&quot;)
	public ResultResponse optionaltermsUpdate(@RequestParam(&quot;UID&quot;) int UID, 
			@ApiParam(&quot;ifAgreed&quot;) // API 파라미터 별 설명
            @RequestParam(&quot;ifAgreed&quot;) boolean ifAgreed){
		ResultResponse result = new ResultResponse();
		int isAgreed = userInfoService.optionalTermsSubmit(UID, ifAgreed);
		if(isAgreed == 1) {
			result.setResult(&quot;success&quot;);
		} else {
			result.setResult(&quot;fail&quot;);
		};
		return result;
	};
 }&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;컨트롤러에 설정된 어노테이션 별 정의 :&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;@Api: 클래스에 Swagger 문서화 메타데이터.&lt;br /&gt;&amp;nbsp;- tags: 이 API를 어떤 태그로 분류할지 지정.&lt;br /&gt;&amp;nbsp;- value: API에 대한 짧은 설명.&lt;br /&gt;&amp;nbsp;- description: API에 대한 보다 자세한 설명.&lt;br /&gt;&lt;br /&gt;@ApiOperation: 특정 API 연산에 대한 정보.&lt;br /&gt;&amp;nbsp;- value: API 연산에 대한 짧은 설명. &lt;br /&gt;&amp;nbsp;- notes: API 연산에 대한 보다 자세한 정보. &lt;br /&gt;&lt;br /&gt;@ApiParam: API 연산에서 파라미터에 대한 메타데이터.&lt;br /&gt;&amp;nbsp;- value: 파라미터에 대한 설명. &lt;br /&gt;&amp;nbsp;- required: 파라미터가 필수인지 여부를 나타냄. &lt;br /&gt;&amp;nbsp;- example: 파라미터의 예시 값. &lt;br /&gt;&lt;br /&gt;@ApiResponse: API 응답에 대한 정보를 정의.&lt;br /&gt;&amp;nbsp;- code: HTTP 응답 코드를 지정. &lt;br /&gt;&amp;nbsp;- message: 응답 코드에 따른 설명. &lt;br /&gt;&amp;nbsp;- response: 응답 본문의 타입.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;4. 객체에 매핑하기&lt;/p&gt;
&lt;pre id=&quot;code_1701337954524&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.iamcaster.user.domain;

import io.swagger.annotations.ApiModelProperty;

public class UserInfo {

	@ApiModelProperty(value = &quot;사용자Key&quot;, example = &quot;1&quot;)
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int UID;

	@ApiModelProperty(value = &quot;사용자ID&quot;, example = &quot;abc@iam.cater&quot;)
	private String email;
	
	@ApiModelProperty(value = &quot;사용자비밀번호&quot;, example = &quot;abc123abc&quot;)
	private String password;

	private String salt;
	
	@ApiModelProperty(value = &quot;닉네임Key&quot;, example = &quot;1&quot;)
	@Column(name=&quot;NickID&quot;)
	private int NickID;

	@ApiModelProperty(value = &quot;사용자지역Key&quot;, example = &quot;1&quot;)
	private int RGID;
	
	@ApiModelProperty(value = &quot;선택약관 동의 철회 일시&quot;, example = &quot;2022-04-18T09:00:00+09:00[Asia/Seoul]&quot;)
	@Column(name=&quot;optionalTerms&quot;)
	private ZonedDateTime optionalTerms;
	
	@Column(name=&quot;createdAt&quot;, updatable=false)
	@UpdateTimestamp
	private ZonedDateTime createdAt;
	
	@Column(name=&quot;updatedAt&quot;)
	@UpdateTimestamp
	private ZonedDateTime updatedAt;
	
	@ApiModelProperty(value = &quot;카카오 연동 여부&quot;, example = &quot;true&quot;)
	@Column(name=&quot;ifKakao&quot;)
	private boolean ifKakao;
	
	@Transient
	private boolean ifOptionalTermsAgreed;
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;객체에 설정된 어노테이션&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;@ApiModel: 도메인 객체에 대한 추가 정보.&lt;br /&gt;&amp;nbsp;- value: 필드명.&lt;br /&gt;&amp;nbsp;- description: 필드 정보.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Swagger UI 에서 확인하기&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;&amp;nbsp;http://localhost:8080/swagger-ui/index.html#/ 경로에서 Swagger UI 를 확인할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3638&quot; data-origin-height=&quot;1516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFLayZ/btsBaYNiHHF/lmi9zvYOIjyxFz6DUlgtS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFLayZ/btsBaYNiHHF/lmi9zvYOIjyxFz6DUlgtS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFLayZ/btsBaYNiHHF/lmi9zvYOIjyxFz6DUlgtS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFLayZ%2FbtsBaYNiHHF%2Flmi9zvYOIjyxFz6DUlgtS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3638&quot; height=&quot;1516&quot; data-origin-width=&quot;3638&quot; data-origin-height=&quot;1516&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3525&quot; data-origin-height=&quot;1451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c79mPa/btsBeVhwaWU/04f04V2wPVnVrh5LdjkD7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c79mPa/btsBeVhwaWU/04f04V2wPVnVrh5LdjkD7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c79mPa/btsBeVhwaWU/04f04V2wPVnVrh5LdjkD7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc79mPa%2FbtsBeVhwaWU%2F04f04V2wPVnVrh5LdjkD7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3525&quot; height=&quot;1451&quot; data-origin-width=&quot;3525&quot; data-origin-height=&quot;1451&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3460&quot; data-origin-height=&quot;1671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXaTH5/btsA9jxpmwk/bwyTz7xkFkGa4BztGaWQSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXaTH5/btsA9jxpmwk/bwyTz7xkFkGa4BztGaWQSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXaTH5/btsA9jxpmwk/bwyTz7xkFkGa4BztGaWQSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXaTH5%2FbtsA9jxpmwk%2FbwyTz7xkFkGa4BztGaWQSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3460&quot; height=&quot;1671&quot; data-origin-width=&quot;3460&quot; data-origin-height=&quot;1671&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실제로 서버에 적용되어 있는 API 를 Swagger UI를 통해 확인할 수 있다.&amp;nbsp;&lt;/p&gt;</description>
      <category>SpringBoot</category>
      <category>OpenAPI</category>
      <category>Swagger</category>
      <category>스웨거</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/25</guid>
      <comments>https://joelinseoul.tistory.com/25#entry25comment</comments>
      <pubDate>Thu, 30 Nov 2023 18:58:49 +0900</pubDate>
    </item>
    <item>
      <title>GitHub Actions 로 Docker 빌드 및 자동 배포하기</title>
      <link>https://joelinseoul.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃허브 액션을 사용하면 소스코드의 변경 후 git push 시, 자동으로 어플리케이션 빌드, 도커 이미지 생성 및 배포를 할 수 있다.&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;* 도커 적용과 도커파일 관련 내용은 아래 게시글에서 확인할 수 있다.&lt;/p&gt;
&lt;figure id=&quot;og_1700491226740&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Docker 로 SpringBoot 프로젝트 배포하기 - 이미지 빌드 해서 Docker Hub에 푸시&quot; data-og-description=&quot;기존 내 프로젝트는 war 파일을 톰캣 매니저 페이지를 통해 배포하는 방법을 채택했었다. 다만 프로젝트를 변경해 나가는 과정에서, ec2 인스턴스를 새로 설정하게 되는 경우가 발생하는데, 이때&quot; data-og-host=&quot;joelinseoul.tistory.com&quot; data-og-source-url=&quot;https://joelinseoul.tistory.com/12&quot; data-og-url=&quot;https://joelinseoul.tistory.com/12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fVvcK/hyUyxo3ImZ/LKk3iIMD00O6NQ4HoRS5uk/img.png?width=800&amp;amp;height=401&amp;amp;face=0_0_800_401,https://scrap.kakaocdn.net/dn/S3AxA/hyUCfmLdid/gp4bew6vQv8RmCXaklCKe1/img.png?width=800&amp;amp;height=401&amp;amp;face=0_0_800_401,https://scrap.kakaocdn.net/dn/bqp4Ji/hyUyt1f3ug/HHxidaHPqUblkc1aCM9Et1/img.png?width=1889&amp;amp;height=959&amp;amp;face=0_0_1889_959&quot;&gt;&lt;a href=&quot;https://joelinseoul.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://joelinseoul.tistory.com/12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fVvcK/hyUyxo3ImZ/LKk3iIMD00O6NQ4HoRS5uk/img.png?width=800&amp;amp;height=401&amp;amp;face=0_0_800_401,https://scrap.kakaocdn.net/dn/S3AxA/hyUCfmLdid/gp4bew6vQv8RmCXaklCKe1/img.png?width=800&amp;amp;height=401&amp;amp;face=0_0_800_401,https://scrap.kakaocdn.net/dn/bqp4Ji/hyUyt1f3ug/HHxidaHPqUblkc1aCM9Et1/img.png?width=1889&amp;amp;height=959&amp;amp;face=0_0_1889_959');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Docker 로 SpringBoot 프로젝트 배포하기 - 이미지 빌드 해서 Docker Hub에 푸시&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;기존 내 프로젝트는 war 파일을 톰캣 매니저 페이지를 통해 배포하는 방법을 채택했었다. 다만 프로젝트를 변경해 나가는 과정에서, ec2 인스턴스를 새로 설정하게 되는 경우가 발생하는데, 이때&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;joelinseoul.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;프로젝트 환경&lt;br /&gt;&amp;nbsp;&lt;/b&gt;- java 스프링부트&lt;br /&gt;&amp;nbsp;- gradle&lt;br /&gt;&amp;nbsp;- 도커&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;개념&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Git Hub 레파지토리에 변경사항이 발생되면, 사용자가 정의한 순서대로 jobs 를 실행해 나간다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 흐름을 정의 하는 스크립트 파일은 &lt;b&gt;.github/workflows/ci-cd.yaml&lt;/b&gt; 의 형태에 맞는 경로로 저장해 주며, 파일명은 무관하다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;내 프로젝트의 환경에 맞춘 (gradle빌드 및 ec2 내 도커 배포) workflows의 yaml 의 흐름은 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 95.0003%; height: 424px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignCenter&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;레파지토리 체크아웃&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 17px;&quot;&gt;▼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;gradle wrapper 파일 실행권한 추가&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 17px;&quot;&gt;▼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;./gradlew build 실행&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot;&gt;▼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;Docker Hub 에 로그인&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot;&gt;▼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;도커 이미지 빌드 및 Docker Hub에 푸시&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 17px;&quot;&gt;&lt;b&gt; ▼&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 17px;&quot;&gt;&lt;b&gt;ec2 접속 및 도커 기존 컨테이너 삭제, &lt;/b&gt;&lt;br /&gt;&lt;b&gt;신규 컨테이너 run&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;i&gt;( GitHub Actions 스크립트의 큰 흐름)&lt;/i&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;.github/workflows/ci-cd.yaml 파일 설정&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;pre id=&quot;code_1700487506069&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: CI/CD Pipeline
# ▽ aws 라는 이름의 브랜치에 push 발생 시 해당 스크립트 실행.
on:
  # ▽ 수동으로 동작시킬 수 있도록 이벤트 트리거 추가
  workflow_dispatch:
  push:
    branches:
      - aws
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout Repository
      uses: actions/checkout@v2
      
 # ▽ 프로젝트의 JDK 버전 명시
    - name: Set up JDK 17
      uses: actions/setup-java@v2
      with:
        java-version: '17'
        distribution: 'adopt'      
# ▽ GitHub Actions에서 gradlew 스크립트를 실행시키기 위해, 실행 권한을 부여 함.
    - name: Set up Executable Permission for Gradlew
      run: chmod +x ./gradlew
# ▽ 애플리케이션 빌드
    -  name: Build and Test
       run: ./gradlew build
# ▽ 도커 허브 로그인 (깃허브의 secrets 내 변수로 username, password 치환)
    - name: Login to Docker Hub
      uses: docker/login-action@v1
      with:
        username: ${{ secrets.DOCKER_HUB_USERNAME }}
        password: ${{ secrets.DOCKER_HUB_PW }}
# ▽ 도커 이미지 빌드 및 푸시        
    - name: Build and Push Docker Image
      run: |
        docker build -t joelgyunampark/iamcaster:${{ github.sha }} .
        docker push joelgyunampark/iamcaster:${{ github.sha }}
# ▽ EC2 접속
    - name: Deploy to AWS EC2
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ${{ secrets.EC2_USERNAME }}
        key: ${{ secrets.EC2_SSH_KEY }}
# ▽ EC2에서 docker 이미지 pull, 기존 컨테이너 중지 삭제 및 새 이미지 run
        script: |
          docker pull joelgyunampark/iamcaster:${{ github.sha }}
          docker stop myapp || true
          docker rm myapp || true
          docker run -d --name myapp -p 80:8080 joelgyunampark/iamcaster:${{ github.sha }}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;GitHub secrets 변수 설정&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;위의 workflows yaml 스크립트 내 ${{ secrets.xxxx }} 에 치환 될 값을 설정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;github repository &amp;gt; Settings &amp;gt; Secrets and variables &amp;gt; Actions &amp;gt; New repository secret&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Name : 변수명&amp;nbsp; Secret : 값&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2622&quot; data-origin-height=&quot;1689&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnEXov/btsAyVX4ZZD/xdAanbdfjVn6dHCQnS0FG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnEXov/btsAyVX4ZZD/xdAanbdfjVn6dHCQnS0FG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnEXov/btsAyVX4ZZD/xdAanbdfjVn6dHCQnS0FG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnEXov%2FbtsAyVX4ZZD%2FxdAanbdfjVn6dHCQnS0FG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2622&quot; height=&quot;1689&quot; data-origin-width=&quot;2622&quot; data-origin-height=&quot;1689&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;동작 확인 해보기&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;workflow_dispatch event trigger 를 추가하였으므로, 아래 스크린샷과 같이 수동으로 Run workflow를 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 환경의 브런치를 선택 후 Run workflow 를 하면 동작이 시작된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3754&quot; data-origin-height=&quot;1699&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gtt5P/btsACkXb2Vn/kRTiHlNQdZSbBAwlLo8sl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gtt5P/btsACkXb2Vn/kRTiHlNQdZSbBAwlLo8sl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gtt5P/btsACkXb2Vn/kRTiHlNQdZSbBAwlLo8sl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGtt5P%2FbtsACkXb2Vn%2FkRTiHlNQdZSbBAwlLo8sl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3754&quot; height=&quot;1699&quot; data-origin-width=&quot;3754&quot; data-origin-height=&quot;1699&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&amp;nbsp;- 실행 시, workflow 의 스크립트 순서대로 실행되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3772&quot; data-origin-height=&quot;1756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B0IfE/btsAGXGnL54/GSSLXDd8VCVk2Eb0yqITx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B0IfE/btsAGXGnL54/GSSLXDd8VCVk2Eb0yqITx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B0IfE/btsAGXGnL54/GSSLXDd8VCVk2Eb0yqITx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB0IfE%2FbtsAGXGnL54%2FGSSLXDd8VCVk2Eb0yqITx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3772&quot; height=&quot;1756&quot; data-origin-width=&quot;3772&quot; data-origin-height=&quot;1756&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;- 성공의 예 :&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;아래와 같이 successed now 메세지를 받으면 도커 컨테이너 실행까지 완료된 것.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3762&quot; data-origin-height=&quot;1801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceChTZ/btsAGPVSRF1/T4XKyW4qdk7np5nSpnBtRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceChTZ/btsAGPVSRF1/T4XKyW4qdk7np5nSpnBtRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceChTZ/btsAGPVSRF1/T4XKyW4qdk7np5nSpnBtRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceChTZ%2FbtsAGPVSRF1%2FT4XKyW4qdk7np5nSpnBtRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3762&quot; height=&quot;1801&quot; data-origin-width=&quot;3762&quot; data-origin-height=&quot;1801&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;- 실패의 예 :&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;실패하면 에러코드를 확인해 본다. 그래들 래퍼의 권한을 부여하지 않아 실패된 케이스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;이 실패케이스를 통해 위의 예시 yaml 파일에 run: chmod +x ./gradlew 를 추가할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3754&quot; data-origin-height=&quot;1565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqcSY3/btsAFuycNxT/k4I3fmw9Wyu2xkZDsPPGk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqcSY3/btsAFuycNxT/k4I3fmw9Wyu2xkZDsPPGk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqcSY3/btsAFuycNxT/k4I3fmw9Wyu2xkZDsPPGk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqcSY3%2FbtsAFuycNxT%2Fk4I3fmw9Wyu2xkZDsPPGk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3754&quot; height=&quot;1565&quot; data-origin-width=&quot;3754&quot; data-origin-height=&quot;1565&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 배포 환경 브랜치를 push 하면 자동으로 배포되게 되었다.&lt;/p&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>CI CD</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/24</guid>
      <comments>https://joelinseoul.tistory.com/24#entry24comment</comments>
      <pubDate>Mon, 20 Nov 2023 23:36:46 +0900</pubDate>
    </item>
    <item>
      <title>디자인패턴 - 팩토리 패턴</title>
      <link>https://joelinseoul.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&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;팩토리 패턴 (Factory Pattern)은 객체를 사용하는 코드에서, &lt;b&gt;객체 생성 부분을 떼어내 추상화&lt;/b&gt; 한 패턴.&lt;/li&gt;
&lt;li&gt;상속 관계에 있는 두 클래스에서 &lt;b&gt;상위클래스는 중요 뼈대&lt;/b&gt;를 결정하고, &lt;b&gt;하위 클래스에서 객체 생성&lt;/b&gt;에 관한 구체적인 내용을 결정하는 패턴.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&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;/li&gt;
&lt;li&gt;상위클래스에서는 인스턴스의 생성 방식에 대해서 알 필요가 없기 때문에 유연성을 가짐.&lt;/li&gt;
&lt;li&gt;유지보수성의 증가 : 객체 생성 로직이 따로 떼어져 있기 때문에, 코드를 리팩토링하더라도 한 곳만 고칠 수 있게 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Java 에서의 팩토리 패턴 적용 예시&lt;/p&gt;
&lt;pre id=&quot;code_1699371946980&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package csstudy.tistory;

public class FactoryPatternExample {
	// 상위 클래스(추상화 클래스) : 문구류 정보의 뼈대 제공.
    // 모든 문구류는 이 클래스를 상속 받아야 함.
	abstract static class Stationary{
    	//추상 메소드 : 가격을 반환.
		public abstract int getPrice();
        //추상 메소드 : 이름을 반환.
		public abstract String getName();
		
		@Override
		public String toString() {
			return this.getName()+&quot;의 가격 : &quot; + this.getPrice()+&quot;원&quot;;
		}
	}
    // 하위클래스 : 문구류 정보 안내 클래스에 상속
	static class DefaultPen extends Stationary{
		private int price;
		private String name;
		
		public DefaultPen(int price) {
			this.price = price;
			this.name = &quot;기본펜&quot;;
		}
		@Override
		public int getPrice() {
			return this.price;
		}
		@Override
		public String getName() {
			return this.name;
		}
	}
	static class Ballpen extends Stationary{
		private int price;
		private String name;
		
		public Ballpen(int price) {
			this.price = price;
			this.name = &quot;볼펜&quot;
;		}
		@Override
		public int getPrice() {
			return this.price;
		}
		@Override
		public String getName() {
			return this.name;
		}
	}
	static class Pencil extends Stationary{
		private int price;
		private String name;
		public Pencil(int price) {
			this.price = price;
			this.name = &quot;연필&quot;;
		}
		@Override
		public int getPrice() {
			return this.price;
		}
		@Override
		public String getName() {
			return this.name;
		}
	}
	// 팩토리 클래스 : 문자열 타입에 따라 문구류 객체를 생성하고 반환함.
	static class StationaryFactory{
		public static Stationary getStationary(String type, int price) {
			if(&quot;Ballpen&quot;.equalsIgnoreCase(type)) {
				return new Ballpen(price);
			} else if(&quot;Pencil&quot;.equalsIgnoreCase(type)) {
				return new Pencil(price);
			} else {
				return new DefaultPen(price);
			}
		}
	}
    // 300원짜리 연필 구하기
    public static void main(String[] args) {
		Stationary pencil = StationaryFactory.getStationary(&quot;Pencil&quot;,300);
		System.out.println(pencil);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWEBy/btszYHdj9Z1/8PYvwFZO3LmxWpU3cFEqU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWEBy/btszYHdj9Z1/8PYvwFZO3LmxWpU3cFEqU1/img.png&quot; data-alt=&quot;코드 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWEBy/btszYHdj9Z1/8PYvwFZO3LmxWpU3cFEqU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWEBy%2FbtszYHdj9Z1%2F8PYvwFZO3LmxWpU3cFEqU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;261&quot; height=&quot;78&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;137&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- Stationary 추상 클래스는 문구류 객체의 뼈대를 제공&lt;br /&gt;- StationaryFactory 클래스는 문구류 객체를 생성하는 과정을 캡슐화.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Javascript 에서의 팩토리 패턴 적용 예시&lt;/p&gt;
&lt;pre id=&quot;code_1699372751744&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;

    class Ballpen {
        constructor(){
            this.name=&quot;ballpen&quot;;
        }
    }
    class Pencil{
        constructor(){
            this.name=&quot;pencil&quot;;
        }
    }
    class BallpenMaker{
        static makeStationary(){
            return new Ballpen();
        }
    }
    class PencilMaker{
        static makeStationary(){
            return new Pencil();
        }
    }
    const makerList = {BallpenMaker, PencilMaker};
    class StationaryFactory{
        static createStationary(type){
            const maker = makerList[type];
            return maker.makeStationary()
        }
    }
    const main = (type) =&amp;gt; {
        const stationary = StationaryFactory.createStationary(type);
        console.log(stationary.name);
    }

    main(&quot;BallpenMaker&quot;)
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;38&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uQa35/btszSKwbUEP/D8SZB6JND9JwD52d4Wgrsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uQa35/btszSKwbUEP/D8SZB6JND9JwD52d4Wgrsk/img.png&quot; data-alt=&quot;코드 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uQa35/btszSKwbUEP/D8SZB6JND9JwD52d4Wgrsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuQa35%2FbtszSKwbUEP%2FD8SZB6JND9JwD52d4Wgrsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;181&quot; height=&quot;38&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;38&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- StationaryFactory :상위 클래스로, 문구류의 큰 뼈대 구조를 잡읍.&lt;br /&gt;- BallpenMaker : 하위클래스로, 객체의 구체적인 내용을 결정함. &lt;br /&gt;- 의존성 주입 : BallpenMaker 에서 생성한 인스턴스를 StationaryFactory에 주입.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>CS Study</category>
      <category>팩토리패턴 개념</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/22</guid>
      <comments>https://joelinseoul.tistory.com/22#entry22comment</comments>
      <pubDate>Wed, 8 Nov 2023 01:02:03 +0900</pubDate>
    </item>
    <item>
      <title>디자인패턴 - 싱글톤 패턴</title>
      <link>https://joelinseoul.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;싱글톤 (Singleton) 패턴 핵심&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;b&gt;나의 인스턴스&lt;/b&gt;만 가지는 디자인 패턴.&lt;/li&gt;
&lt;li&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;b&gt;인스턴스를 생성할 때 드는 비용이 줄어듬&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단점&lt;/b&gt; : &lt;b&gt;의존성이 높아짐&lt;/b&gt; -&amp;gt; 각 테스트 마다 독립적인 인스턴스를 생성해야 하는 TTD(Test Driven Development) 적용이 어려움.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&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;&amp;rarr; 이 때 의존성 주입을 통해 해결 가능.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;중간에 의존성 주입자(depenency injector) 가 하위 모듈에게 의존성을 주고, 의존성 주입자와 메인모듈만 서로 연결하는 개념.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의존성 주입 원칙&lt;/b&gt; :&amp;nbsp; 상위 모듈은 하위 모듈에서 어떤 것도 가져오지 않아야 함. 또한 둘 다 추상화에 의존해야 하며, 이때 추상화는 세부사항에 의존하지 말아야 함.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wN6Ar/btszQEQvfXI/Ps9VEjZDIF348hCW4dIWLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wN6Ar/btszQEQvfXI/Ps9VEjZDIF348hCW4dIWLK/img.png&quot; data-alt=&quot;의존성 주입 개념도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wN6Ar/btszQEQvfXI/Ps9VEjZDIF348hCW4dIWLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwN6Ar%2FbtszQEQvfXI%2FPs9VEjZDIF348hCW4dIWLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;185&quot; height=&quot;271&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;의존성 주입 개념도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Java 에서의 싱글톤 패턴 적용 예시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699370765210&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package csstudy.tistory;

public class SingletonExample {

	public static void main(String[] args) {
		Singleton instance1 = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		boolean isSame = (instance1 == instance2);
		System.out.println(instance1.hashCode());
		System.out.println(instance2.hashCode());
		System.out.println(isSame);
	}
}

class Singleton{
	private static class singleInstanceHolder{
		private static final Singleton INSTANCE = new Singleton();
	}
	public static Singleton getInstance() {
		return singleInstanceHolder.INSTANCE;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF3kU8/btszXLgdzQ6/C0591KDfBkRjWjQARZ6IX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF3kU8/btszXLgdzQ6/C0591KDfBkRjWjQARZ6IX0/img.png&quot; data-alt=&quot;코드 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF3kU8/btszXLgdzQ6/C0591KDfBkRjWjQARZ6IX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF3kU8%2FbtszXLgdzQ6%2FC0591KDfBkRjWjQARZ6IX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;299&quot; height=&quot;95&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- singleInstanceHolder 클래스의 Singleton 인스턴스가 static final 로 선언되어 있으므로, 클래스가 로딩되는 시점에 1개만 생성되며, 이후 추가 선언 시 해당 인스턴스를 가르키게 된다.&lt;br /&gt;- 코드 실행 결과를 보면, instance1과 instance2 가 같은 해시코드 값을 가지고 있는 것을 확인할 수 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Javascript 에서의 싱글톤 패턴 적용 예시&lt;/p&gt;
&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1699371356447&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
     class Singleton{
        constructor(){
            if(!Singleton.instance){
                Singleton.instance = this
            }
            return Singleton.instance
        }
    }
    const obj3 = new Singleton()
    const obj4 = new Singleton()
    console.log(obj3 === obj4)
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;106&quot; data-origin-height=&quot;22&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RLGvP/btszQBzw1NH/dKSKXYS1krXd9kv161Jb1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RLGvP/btszQBzw1NH/dKSKXYS1krXd9kv161Jb1k/img.png&quot; data-alt=&quot;코드 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RLGvP/btszQBzw1NH/dKSKXYS1krXd9kv161Jb1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRLGvP%2FbtszQBzw1NH%2FdKSKXYS1krXd9kv161Jb1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;106&quot; height=&quot;22&quot; data-origin-width=&quot;106&quot; data-origin-height=&quot;22&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- 자바스크립트 에서의 싱글톤 적용은, Singleton 클래스의 생성자 호출 시 생성자 존재 여부를 확인 후,&lt;br /&gt;있으면 새 인스턴스를 생성하는 대신 기존 인스턴스를 반환하게 된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS Study</category>
      <category>싱글톤 개념</category>
      <category>싱글톤 패턴</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/21</guid>
      <comments>https://joelinseoul.tistory.com/21#entry21comment</comments>
      <pubDate>Wed, 8 Nov 2023 00:40:24 +0900</pubDate>
    </item>
    <item>
      <title>ThymeLeaf  템플릿으로 JavaMailSender 활용, 자바 메일보내기</title>
      <link>https://joelinseoul.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring 의 JavaMailSender 와 Thymeleaf의 템플릿 엔진을 사용하여 이메일을 생성하고 발송하는 기능을 구현해 본다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 인증번호 전송 등의 기본 메일이라면, 아래의 모듈화 정도가 적당할 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PkWc5/btszAmolc7H/GVqvkJzEqNGUCHgBfUlwr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PkWc5/btszAmolc7H/GVqvkJzEqNGUCHgBfUlwr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PkWc5/btszAmolc7H/GVqvkJzEqNGUCHgBfUlwr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPkWc5%2FbtszAmolc7H%2FGVqvkJzEqNGUCHgBfUlwr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1866&quot; height=&quot;544&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;build.gradle 의존성 추가&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;JavaMailSender를 사용하기 위해 spring-boot-starter-mail 을 의존성 추가하고,&lt;br /&gt;템플릿엔진을 사용하기 위해 spring-boot-starter-thymeleaf 를 의존성 추가한다.&lt;br /&gt;
&lt;pre id=&quot;code_1698843259914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	//메일발송
	implementation 'org.springframework.boot:spring-boot-starter-mail'
	//thymemeleaf
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'​&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;application.yml 설정&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;JavaMailSender 를 사용하여 이메일을 보내기 위해, SMTP서버의 정보를 application.yml 에서 설정해 준다.&lt;/b&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1698843429368&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  mail:
    host: smtp.naver.com
    port: 587
    username: 아이디
    password: 비밀번호
    properties:
      mail:
        smtp:
          auth: true
          timeout: 5000
          starttls:
            enable: true
            required: true​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;spring.mail.host : SMTP 서버의 호스트 명&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp; spring.mail.port : SMTP 서버의 포트번호&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;spring.mail.usename : SMTP 서버 접속을 위한 사용자이름&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;password : SMTP 서버 접속을 위한 비밀번호&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;spring.mail.properties.mail.smtp.auth: SMTP 서버에 로그인할 때 인증을 사용할지 여부를 설정 &lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;spring.mail.properties.mail.smtp.timeout: SMTP 서버에 연결할 때의 타임아웃 시간을 설정&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;spring.mail.properties.mail.smtp.starttls.enable: STARTTLS를 사용하여 SMTP 서버에 연결할지 여부를 설정&amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;spring.mail.properties.mail.smtp.starttls.required: STARTTLS를 사용하여 SMTP 서버에 연결하는 것이 필수인지 여부를 설정&lt;br /&gt;&lt;br /&gt;메일서비스 제공사마다 설정값들이 다르기 때문에, &lt;b&gt;네이버의 경우 상기 코드&lt;/b&gt;와 같이 작성하면 된다.&lt;br /&gt;다른 메일서비스 제공사를 이용하고 싶다면 메일함에 들어가 설정 &amp;gt; POP/IMAP 설정 등과 같은 곳에 들어가 자신의 로그인ID, SMTP서버명, 포트번호 등을 확인해보자.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;b&gt;이어서, SpringBoot에서 Thymeleaf 템플릿 엔진을 사용하기 위한 설정 또한 해준다.&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;
&lt;pre id=&quot;code_1698843974753&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  thymeleaf:
    prefix: classpath:/templates/thymeleafTemplates/
    suffix: .html
    mode: HTML
    cache: false
    thymeleaf.view-names&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;nbsp; -&amp;nbsp; &amp;nbsp;thymeleaf.prefix: 템플릿 파일의 경로의 접두사로 사용됨. classpath:/templates/thymeleafTemplates/로 설정되어 있어, src/main/resources/templates/thymeleafTemplates/ 경로에 있는 템플릿 파일들을 찾게 된다.&lt;br /&gt;&amp;nbsp; -&amp;nbsp; thymeleaf.suffix:&amp;nbsp;템플릿&amp;nbsp;파일의&amp;nbsp;확장자를&amp;nbsp;설정&lt;br /&gt;&amp;nbsp; -&amp;nbsp; thymeleaf.mode: 템플릿 엔진의 모드를 설정. HTML문법으로 작성된 파일을 처리함.&lt;br /&gt;&amp;nbsp; &amp;nbsp;- thymeleaf.cache: 템플릿 파일의 캐싱 여부를 설정. 개발 환경이므로 false 하여 캐싱을 끔.&lt;br /&gt;&amp;nbsp; &amp;nbsp;- thymeleaf.view-names: 템플릿 파일의 이름 패턴을 설정. JSP 등과 함께 사용하는 경우 충돌이 발생될 수 있는데, 이 설정 시 해당 텍스트로 시작하는 템플릿 파일만 찾음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;DTO&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;메일 수신자, 발신자, 제목, 본문 을 구성하기 위한 DTO 이다.&lt;br /&gt;
&lt;pre id=&quot;code_1698840572016&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.spingblog.cases.mailSender;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@ToString
@Builder(toBuilder = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MailSenderDTO {

	private String receiver;
	private String sender;
	private String subject;
	private String context;
}​&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Controller : 응답 수신&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;컨트롤러는 서비스 마다 구현방법이 가지각색일것이다.&amp;nbsp;&lt;br /&gt;여기서는 최초 로직 시작이 되는 개념으로만 이해를 하면 된다.&lt;br /&gt;who 변수에 수신이메일, what 변수에 메일본문을 입력하면 된다.&lt;br /&gt;
&lt;pre id=&quot;code_1698839507154&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.spingblog.cases.mailSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MailSenderRestController {
	@Autowired
	private MailSenderService mailSenderService;
	@GetMapping(&quot;/send&quot;)
	public void sendRequest(@RequestParam(&quot;who&quot;) String who, @RequestParam(&quot;what&quot;) String what) {
		mailSenderService.send(who, what);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Service : send&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li data-ke-style=&quot;style3&quot;&gt;이메일을 받을 사람(who)과 이메일의 내용(what)을 인자로 받는다.&lt;/li&gt;
&lt;li data-ke-style=&quot;style3&quot;&gt;setContext 메서드를 호출하여 이메일 내용을 생성한다.&lt;/li&gt;
&lt;li data-ke-style=&quot;style3&quot;&gt;MailSenderDTO 객체를 생성하여 이메일의 수신자, 발신자, 제목, 내용 등을 설정한다.&lt;/li&gt;
&lt;li data-ke-style=&quot;style3&quot;&gt;sendEmail 메서드를 호출하여 이메일을 발송한다.&lt;br /&gt;
&lt;pre id=&quot;code_1698840782643&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.spingblog.cases.mailSender;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

@Service
public class MailSenderService {

	@Autowired
	private JavaMailSender javaMailSender;
	@Autowired
	private SpringTemplateEngine templateEngine;

	// 메일 작성
	public void send(String who, String what) {
		
		String writeTL = setContext(what);
		MailSenderDTO mailDTO = MailSenderDTO.builder()
				.receiver(who)
				.sender(&quot;joeldev@naver.com&quot;)
				.subject(&quot;기발자로부터 메일이 도착했어요!&quot;)
				.context(writeTL)
				.build();
		sendEmail(mailDTO);
	}

	// 타임리프 본문 구성
	public String setContext(String what) {
		//중략
	}
	// 메일 발송
	public void sendEmail(MailSenderDTO mailDTO) {
		//중략
	}
}​&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;service : setContext&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;&amp;nbsp; &amp;nbsp;- Context 객체를 생성하여 what을 변수로 설정한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;*&amp;nbsp; setVariable 에서 정의한 변수와 값은 타임리프 템플릿에서&amp;nbsp; &lt;span style=&quot;background-color: #2f2f2f;&quot;&gt;&lt;span style=&quot;background-color: #2f2f2f; color: #aaaaaa;&quot;&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;th:text&lt;/span&gt;=&lt;span style=&quot;color: #808080;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;${what}&lt;/span&gt;&lt;span style=&quot;color: #808080;&quot;&gt;&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp; 와 같이 구성하여 템플릿에서 치환된다.&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;&amp;nbsp; &amp;nbsp;- 타임리프 templateEngine을 사용하여 템플릿(tlTemplate)을 기반으로 이메일 내용을 생성한다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;* process(&amp;lt;html파일명&amp;gt;, &amp;lt;변수객체&amp;gt;) 와 같이 구성하여 해당 html파일을 변수객체로 치환하고, 치환된 html을 String으로 return 받는다.&lt;/p&gt;
&lt;pre id=&quot;code_1698841628106&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.spingblog.cases.mailSender;
//중략
@Service
public class MailSenderService {

	@Autowired
	private JavaMailSender javaMailSender;
	@Autowired
	private SpringTemplateEngine templateEngine;

	// 메일 작성
	public void send(String who, String what) {
    		// 중략
	}

	// 타임리프 본문 구성
	public String setContext(String what) {
		Context context = new Context();
		context.setVariable(&quot;what&quot;, what);
		return templateEngine.process(&quot;tlTemplate&quot;, context);
	}

	// 메일 발송
	public void sendEmail(MailSenderDTO mailDTO) {
    		// 중략
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;service : sendEmail&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;MimeMessage과&lt;/span&gt;&amp;nbsp;MimeMessageHelper를 사용하여 이메일의 수신자, 발신자, 제목, 내용 등을 설정한다.&lt;/li&gt;
&lt;li&gt;setText 의 두번째 파라미터 -&amp;gt;&amp;nbsp; true : MultiPartFiles 포함 / false : 미포함&lt;/li&gt;
&lt;li&gt;javaMailSender를 사용하여 이메일을 발송한다.&lt;/li&gt;
&lt;li&gt;try-catch블록 : 메일 발송 정보가 부족한 경우, SMTP서버에 연결할수 없는 경우 등, JavaMailSender에서 MessagingException이 발송할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1698842295687&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.spingblog.cases.mailSender;
//중략
@Service
public class MailSenderService {
//중략
	// 메일 작성
	public void send(String who, String what) {
			//중략
	}
	// 타임리프 본문 구성
	public String setContext(String what) {
			//중략
	}

	// 메일 발송
	public void sendEmail(MailSenderDTO mailDTO) {
		MimeMessage mimeMessage = javaMailSender.createMimeMessage();
		try {
			MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, &quot;UTF-8&quot;);
			mimeMessageHelper.setTo(mailDTO.getReceiver());
			mimeMessageHelper.setFrom(mailDTO.getSender());
			mimeMessageHelper.setSubject(mailDTO.getSubject());
			mimeMessageHelper.setText(mailDTO.getContext(), true);
			javaMailSender.send(mimeMessage);
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;템플릿 html 파일&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&amp;nbsp;- 파일경로 : application.yml 파일에서 정의한 위치에 저장한다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; * src/main/resources/templates 하위에 위치하는 것이 일반적이며, 필요에 따라 설정하면 된다.&lt;br /&gt;&amp;nbsp;- 이메일 클라이언트는 css파일을 지원하지 않으므로, css를 인라인 스타일로 작성한다.&lt;br /&gt;&amp;nbsp;- context 변수가 치환되는 위치는 th:text=&quot;${변수명}&quot; 이 위치해 있는 태그 안이다.&lt;br /&gt;
&lt;pre id=&quot;code_1698842853543&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional //EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&amp;gt;
&amp;lt;html xmlns=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head&amp;gt;
	&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&amp;gt;
	&amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, user-scalable=no&quot;&amp;gt;
	&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;div id=&quot;wrap&quot; style=&quot;width:auto; height:auto; margin:auto; font-family: SUITE Variable; background: #ffffff; font-size: 24px; overflow:auto;&quot;&amp;gt;
        &amp;lt;div class=&quot;my-5&quot; style=&quot;text-align:center;&quot;&amp;gt;
			&amp;lt;div class=&quot;f-content&quot; style=&quot;font-size: 16px; letter-spacing: 6px;&quot;&amp;gt;새로운 메일이 왔어요.&amp;lt;/div&amp;gt;
			&amp;lt;div class=&quot;f-title font-weight-bold&quot; style=&quot;font-size: 22px; letter-spacing: 3px;&quot;&amp;gt;기발자&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;
        &amp;lt;hr&amp;gt;
        &amp;lt;div class=&quot;f-content ml-3&quot; style=&quot;font-size: 15px; letter-spacing: 3px; margin: 10px; padding-top: 10px; text-align: center;&quot;&amp;gt;
            &amp;lt;br&amp;gt;
            &amp;lt;div style=&quot;text-align: center;&quot;&amp;gt;아래의 메세지를 확인해 주세요&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;m-3&quot; &amp;gt;
            &amp;lt;div class=&quot;text-center m-3&quot; style=&quot;padding-top: 10px; display: flex; justify-content: center; align-items: center;&quot;&amp;gt;새로운 메세지&amp;lt;/div&amp;gt;
            &amp;lt;div style=&quot;padding-top: 10px; display: flex; justify-content: center; align-items: center;&quot;&amp;gt;
                &amp;lt;div class=&quot;bg-secondary text-center p-3 f-title&quot; style=&quot;font-size: 30px; letter-spacing: 6px; width: 300px; height: 80px; display: flex; justify-content: center; align-items: center; background-color: #666666; border-radius: 10px;&quot;&amp;gt;
                   &amp;lt;div th:text=&quot;${what}&quot; style=&quot; color:rgb(255, 255, 255); font-weight: bolder; text-align:center; align-items: center;&quot;&amp;gt;&amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;f-content ml-3&quot; style=&quot;font-size: 15px; letter-spacing: 3px; margin: 10px; padding-top: 10px;&quot;&amp;gt;감사합니다.&amp;lt;/div&amp;gt;
	
        &amp;lt;div class=&quot;f-small&quot; style=&quot;font-size: 12px;&quot;&amp;gt;
            &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;
            &amp;lt;hr&amp;gt;
            &amp;lt;div&amp;gt;※ 본 메일은 발송전용 메일로, 회신하실 수 없습니다.&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;footer class=&quot;mt-3 pb-2&quot; style=&quot;color: #666666;&quot;&amp;gt;
            &amp;lt;hr&amp;gt;
            &amp;lt;div style=&quot;font-size: 12px; text-align: center;&quot; class=&quot;f-small text-center&quot;&amp;gt;ⓒ IAMCASTER 2023. All Rights Reserved.&amp;lt;/div&amp;gt;
        &amp;lt;/footer&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;​&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;발송 예시&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;위의 예시코드를 작동 시키고, 아래 대로 Get을 호출해 보자.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;localhost:8080/send?who=abc@abc.com&amp;amp;what=Hello 안녕하세요&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VHrvu/btszAnANgYs/LROx55HJ9Ql8qhpMXtf0Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VHrvu/btszAnANgYs/LROx55HJ9Ql8qhpMXtf0Zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VHrvu/btszAnANgYs/LROx55HJ9Ql8qhpMXtf0Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVHrvu%2FbtszAnANgYs%2FLROx55HJ9Ql8qhpMXtf0Zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1450&quot; height=&quot;721&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&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;/p&gt;</description>
      <category>SpringBoot</category>
      <category>자바 메일보내기</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/20</guid>
      <comments>https://joelinseoul.tistory.com/20#entry20comment</comments>
      <pubDate>Wed, 1 Nov 2023 22:18:32 +0900</pubDate>
    </item>
    <item>
      <title>AWS RDS 환경설정 하기</title>
      <link>https://joelinseoul.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 EC2 인스턴스에 MySQL을 함께 올려 사용했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 서비스를 운영하다 보니, 성능저하가 빈번하게 발생했고, 자바 애플리케이션과 mysql 중 어느 부분이 성능저하를 만들어 내고 있는가 에 대한 직관적인 확인이 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서,&amp;nbsp;EC2 와 RDS 를 분리하여 각각 인스턴스에 대한 관리를 용이하게 하고 싶었고, RDS를 추가하게 되었다.&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;RDS 생성 및 EC2 연결 방법은 아래와 같다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;RDS 인스턴스 생성하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;AWS RDS 에서 &quot;데이터베이스 생성&quot; 을 클릭, 아래의 화면으로 들어가며 시작된다.&lt;br /&gt;&lt;br /&gt;데이터베이스 생성 방식 선택 은 &lt;b&gt;표준 생성&lt;/b&gt;으로 둔다.&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkCtvC/btszA0qA79a/jb8dSq2EExWKSMZBKMmKz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkCtvC/btszA0qA79a/jb8dSq2EExWKSMZBKMmKz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkCtvC/btszA0qA79a/jb8dSq2EExWKSMZBKMmKz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkCtvC%2FbtszA0qA79a%2Fjb8dSq2EExWKSMZBKMmKz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;228&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;엔진 유형과 엔진 버전은 프로젝트에 적용되어 있는 DB를 선택하면 된다. &lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;나의 경우, &lt;b&gt;MySQL 8.0&lt;/b&gt;이 적용되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;775&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blfakO/btszvHfjPwg/PjYaOKvi0ML5H5fvUJm7Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blfakO/btszvHfjPwg/PjYaOKvi0ML5H5fvUJm7Qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blfakO/btszvHfjPwg/PjYaOKvi0ML5H5fvUJm7Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblfakO%2FbtszvHfjPwg%2FPjYaOKvi0ML5H5fvUJm7Qk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;583&quot; height=&quot;775&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;775&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;템플릿은 필요에 따라 선택하게 되는데, 무료 사용을 위해 프리 티어를 선택했다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q5diL/btszzGlRf8X/Z2ORCkprsTGm0vgpxv7fu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q5diL/btszzGlRf8X/Z2ORCkprsTGm0vgpxv7fu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q5diL/btszzGlRf8X/Z2ORCkprsTGm0vgpxv7fu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq5diL%2FbtszzGlRf8X%2FZ2ORCkprsTGm0vgpxv7fu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;582&quot; height=&quot;443&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;DB 인스턴스 식별자는 이 인스턴스를 내가 구분할 수 있는 텍스트로 잘 지어주자.&lt;br /&gt;&lt;b&gt;마스터 사용자 이름과 마스터 암호&lt;/b&gt;는 db 로그인 시 사용되는 이름으로, 프로젝트설정값을 변경하고 싶지 않다면 맞추어 변경하면 된다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m8uDc/btszzEO6wS8/Wl3EkBkv4gyIz2I6b5KTn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m8uDc/btszzEO6wS8/Wl3EkBkv4gyIz2I6b5KTn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m8uDc/btszzEO6wS8/Wl3EkBkv4gyIz2I6b5KTn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm8uDc%2FbtszzEO6wS8%2FWl3EkBkv4gyIz2I6b5KTn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;580&quot; height=&quot;603&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;인스턴스 구성과 스토리지는 필요 조건에 따라 설정하면 되는데, 난 기본값에서 변경하지 않았다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;581&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIX97A/btszyGmCjNY/UH8oKc2haUjRHgCzi8C1M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIX97A/btszyGmCjNY/UH8oKc2haUjRHgCzi8C1M0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIX97A/btszyGmCjNY/UH8oKc2haUjRHgCzi8C1M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIX97A%2FbtszyGmCjNY%2FUH8oKc2haUjRHgCzi8C1M0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;581&quot; height=&quot;662&quot; data-origin-width=&quot;581&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;연결 은 잘 알아두는 것이 좋다.&lt;br /&gt;기존에 EC2인스턴스를 생성해 놓은 경우, &lt;b&gt;EC2 컴퓨팅 리소스에 연결&lt;/b&gt; 을 선택하면 VPC 환경을 해당 EC2 인스턴스로 잡아준다. 다만 이 경우, 로컬에서의 접속은 불가능하나, EC2 인스턴스에서 db client 로 접속할 수 있다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;EC2 인스턴스&lt;/b&gt;는 적용할 EC2 인스턴스를 선택해 주면 된다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZVRqM/btszyIxGy4I/QbOPOFK93aCM876otios2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZVRqM/btszyIxGy4I/QbOPOFK93aCM876otios2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZVRqM/btszyIxGy4I/QbOPOFK93aCM876otios2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZVRqM%2FbtszyIxGy4I%2FQbOPOFK93aCM876otios2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;670&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;VPC 보안 그룹&lt;/b&gt;을 &lt;u&gt;기존 항목 선택&lt;/u&gt; 하여, EC2 생성 시 만들어놓은 보안그룹과 같은 적용을 받도록 할 수 있다.&lt;br /&gt;&lt;b&gt;추가VPC 보안 그룹&lt;/b&gt; 에서 EC2와 같은 보안그룹을 선택하면 된다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;691&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5YLGj/btszwcGlW6r/GtV93B50dsP877SLS2skbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5YLGj/btszwcGlW6r/GtV93B50dsP877SLS2skbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5YLGj/btszwcGlW6r/GtV93B50dsP877SLS2skbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5YLGj%2FbtszwcGlW6r%2FGtV93B50dsP877SLS2skbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;691&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;691&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;추가구성&amp;nbsp;&lt;/b&gt;을 클릭하면 포트번호를 선택할 수 있다. MySQL 기본 포트번호인 3306을 그대로 사용했다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUueQh/btszyK3l38N/f7lhBYVqD3mPWk5H0O4361/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUueQh/btszyK3l38N/f7lhBYVqD3mPWk5H0O4361/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUueQh/btszyK3l38N/f7lhBYVqD3mPWk5H0O4361/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUueQh%2FbtszyK3l38N%2Ff7lhBYVqD3mPWk5H0O4361%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;328&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;328&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;데이터베이스 인증은 기본 암호인증을 사용할 것이다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ySjIO/btszvBGqQvQ/psrXq4MM3EyphkLHGkgoMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ySjIO/btszvBGqQvQ/psrXq4MM3EyphkLHGkgoMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ySjIO/btszvBGqQvQ/psrXq4MM3EyphkLHGkgoMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FySjIO%2FbtszvBGqQvQ%2FpsrXq4MM3EyphkLHGkgoMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;589&quot; height=&quot;659&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;659&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이제 데이터베이스 생성을 누르면 RDS 인스턴스가 생성된다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm8jtS/btszxshDshb/4ZhhTy9UrCAlwEUOn4UuHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm8jtS/btszxshDshb/4ZhhTy9UrCAlwEUOn4UuHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm8jtS/btszxshDshb/4ZhhTy9UrCAlwEUOn4UuHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm8jtS%2FbtszxshDshb%2F4ZhhTy9UrCAlwEUOn4UuHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;583&quot; height=&quot;353&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;VPC 보안그룹 확인하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;DB 인스턴스로 들어가서&lt;b&gt; 보안그룹이 잘 묶여있는지&lt;/b&gt; 확인해 보자.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DB인스턴스를 생성할 때, EC2 리소스에 연결했으므로,&lt;br /&gt;아래 화면과 같이 rds-ec2-1 라는 보안그룹이 생성된 것을 확인할 수 있다.&amp;nbsp;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1851&quot; data-origin-height=&quot;939&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xLL2W/btszCqJPejC/ElwJDKyDaADHB6MqQLLet0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xLL2W/btszCqJPejC/ElwJDKyDaADHB6MqQLLet0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xLL2W/btszCqJPejC/ElwJDKyDaADHB6MqQLLet0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxLL2W%2FbtszCqJPejC%2FElwJDKyDaADHB6MqQLLet0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1851&quot; height=&quot;939&quot; data-origin-width=&quot;1851&quot; data-origin-height=&quot;939&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;rds-ec2-1 &lt;b&gt;보안그룹&lt;/b&gt;에 들어가서, 규칙이 어떻게 설정되어있는지 확인해 보자.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1549&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dI1cBw/btszCoeaIcQ/I2qfeMiYuVqhsTVUvIpN8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dI1cBw/btszCoeaIcQ/I2qfeMiYuVqhsTVUvIpN8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dI1cBw/btszCoeaIcQ/I2qfeMiYuVqhsTVUvIpN8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdI1cBw%2FbtszCoeaIcQ%2FI2qfeMiYuVqhsTVUvIpN8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1549&quot; height=&quot;371&quot; data-origin-width=&quot;1549&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;인바운드 규칙을 확인해 보니, sg-0f60~~ 라는 소스에 대해서 3306 포트에 인바운드 허용한 것을 확인할 수 있다.&lt;br /&gt;저 &lt;b&gt;보안그룹ID에서 발생된 트래픽만 접속&lt;/b&gt;이 허용되므로, 설정된 소스가 ec2의 보안그룹에 해당할 것이다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Muh4M/btszCKH1306/Rx0A71yxlfWdLKGKgSAjnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Muh4M/btszCKH1306/Rx0A71yxlfWdLKGKgSAjnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Muh4M/btszCKH1306/Rx0A71yxlfWdLKGKgSAjnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMuh4M%2FbtszCKH1306%2FRx0A71yxlfWdLKGKgSAjnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1622&quot; height=&quot;738&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;그렇다면&lt;b&gt; EC2 인스턴스의 보안그룹&lt;/b&gt;을 확인해 보자.&lt;br /&gt;보안그룹 을 보니 RDS 인스턴스에 접속이 허용된 보안그룹 ID가 EC2 인스턴스에도 적용되어 있는 것을 확인할 수 있다.&amp;nbsp;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFzuqO/btszyFB2cDK/kEMs7N2L3ItKk9niFVqbb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFzuqO/btszyFB2cDK/kEMs7N2L3ItKk9niFVqbb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFzuqO/btszyFB2cDK/kEMs7N2L3ItKk9niFVqbb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFzuqO%2FbtszyFB2cDK%2FkEMs7N2L3ItKk9niFVqbb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1684&quot; height=&quot;721&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;EC2 에서 RDS 접속해 보기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;AWS 대시보드에서 할 환경 설정은 끝났다.&lt;br /&gt;&lt;br /&gt;EC2 &amp;lt;&amp;gt; RDS 간 정상적인 통신이 가능한 지를 확인하기 위해, EC2에서 RDS 데이터베이스에 접속해 보자.&lt;br /&gt;(EC2 에 DB 클라이언트가 설치되어 있지 않다면, &lt;a href=&quot;https://joelinseoul.tistory.com/18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;EC2에 mysql client 설치하기&lt;/a&gt; 글을 확인하길 바란다.)&lt;br /&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1698824449279&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql -u &amp;lt;db사용자명&amp;gt; -p -h &amp;lt;호스트의 엔드포인트&amp;gt;​​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RDS 연결 및 보안에서&lt;b&gt; 엔드포인트를 확인&lt;/b&gt;할 수 있다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G4Myb/btszCK2vv54/B1g3fqYXyjI4FnhqLSYz50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G4Myb/btszCK2vv54/B1g3fqYXyjI4FnhqLSYz50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G4Myb/btszCK2vv54/B1g3fqYXyjI4FnhqLSYz50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG4Myb%2FbtszCK2vv54%2FB1g3fqYXyjI4FnhqLSYz50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3000&quot; height=&quot;1360&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;b&gt;이제 EC2 인스턴스에서 RDS에 원격으로 접속할 수 있다.&lt;/b&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2001&quot; data-origin-height=&quot;1726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8f5cK/btszA48xnwy/imD4yjZBK7GrC4JpKd2tt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8f5cK/btszA48xnwy/imD4yjZBK7GrC4JpKd2tt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8f5cK/btszA48xnwy/imD4yjZBK7GrC4JpKd2tt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8f5cK%2FbtszA48xnwy%2FimD4yjZBK7GrC4JpKd2tt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2001&quot; height=&quot;1726&quot; data-origin-width=&quot;2001&quot; data-origin-height=&quot;1726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>AWS/RDS</category>
      <category>RDS 설정</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/19</guid>
      <comments>https://joelinseoul.tistory.com/19#entry19comment</comments>
      <pubDate>Wed, 1 Nov 2023 16:45:28 +0900</pubDate>
    </item>
    <item>
      <title>EC2 (Amazon Linux 2023) 에 mysql 클라이언트 설치하기</title>
      <link>https://joelinseoul.tistory.com/18</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;RDS 의 데이터베이스 에 퀴리 실행, 테이블 확인 등을 하기 위해 EC2 에 mysql 을 설치해 볼 것이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;1. MySQL 8.0 설치 패키지를 내려받는다. (rpm)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;pre id=&quot;code_1698823385931&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo dnf install https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm​&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5G7jg/btszCFUq96G/668ZuSKAF6qUEA45AcoS9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5G7jg/btszCFUq96G/668ZuSKAF6qUEA45AcoS9K/img.png&quot; data-alt=&quot;아마존 리눅스 2023 에서sms el9-1 버전의 리포지토리를 지원한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5G7jg/btszCFUq96G/668ZuSKAF6qUEA45AcoS9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5G7jg%2FbtszCFUq96G%2F668ZuSKAF6qUEA45AcoS9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;964&quot; height=&quot;485&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아마존 리눅스 2023 에서sms el9-1 버전의 리포지토리를 지원한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;GPG key 등록하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;pre id=&quot;code_1698823645988&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023​​&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjFFip/btszy6eVlM2/KpOxKrE9pF2fLN3hPpwa5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjFFip/btszy6eVlM2/KpOxKrE9pF2fLN3hPpwa5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjFFip/btszy6eVlM2/KpOxKrE9pF2fLN3hPpwa5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjFFip%2Fbtszy6eVlM2%2FKpOxKrE9pF2fLN3hPpwa5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;971&quot; height=&quot;51&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;51&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;MySQL 클라이언트 설치&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;pre id=&quot;code_1698823901825&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo dnf install mysql​&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2446&quot; data-origin-height=&quot;1946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceAOdM/btszxugkym0/AZWSf6KKTG6rB9whhi2Ns0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceAOdM/btszxugkym0/AZWSf6KKTG6rB9whhi2Ns0/img.png&quot; data-alt=&quot;mysql client 설치 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceAOdM/btszxugkym0/AZWSf6KKTG6rB9whhi2Ns0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceAOdM%2Fbtszxugkym0%2FAZWSf6KKTG6rB9whhi2Ns0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2446&quot; height=&quot;1946&quot; data-origin-width=&quot;2446&quot; data-origin-height=&quot;1946&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mysql client 설치 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;DB 접속해보기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;pre id=&quot;code_1698824134149&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql -u &amp;lt;db사용자명&amp;gt; -p -h &amp;lt;호스트의 엔드포인트&amp;gt;​&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crL2i5/btszyJqIqY5/CGpxK17d0tf9mSWWh8byZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crL2i5/btszyJqIqY5/CGpxK17d0tf9mSWWh8byZ0/img.png&quot; data-alt=&quot;RDS 인스턴스에 접속했다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crL2i5/btszyJqIqY5/CGpxK17d0tf9mSWWh8byZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrL2i5%2FbtszyJqIqY5%2FCGpxK17d0tf9mSWWh8byZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;995&quot; height=&quot;331&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RDS 인스턴스에 접속했다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;</description>
      <category>AWS/EC2</category>
      <category>ec2 mysql</category>
      <category>mysql client</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/18</guid>
      <comments>https://joelinseoul.tistory.com/18#entry18comment</comments>
      <pubDate>Wed, 1 Nov 2023 16:36:40 +0900</pubDate>
    </item>
    <item>
      <title>SpringBoot 에서 JPA 사용하기 - 활용 하기</title>
      <link>https://joelinseoul.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://joelinseoul.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;이전 글: JPA 환경설정 하기&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698763707634&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;SpringBoot 에서 JPA 사용하기 - 환경설정 하기&quot; data-og-description=&quot;Lombok 설치하기 Lombok을 설치하면 별도의 getter/setter 을 만들지 않아도, 어노테이션으로 간단히 객체를 다룰 수 있다. JPA 는 DB 상의 데이터를 객체처럼 다룰 수 있는 핵심 장점이 있는데, Lombok은 그&quot; data-og-host=&quot;joelinseoul.tistory.com&quot; data-og-source-url=&quot;https://joelinseoul.tistory.com/16&quot; data-og-url=&quot;https://joelinseoul.tistory.com/16&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d3jGCc/hyUnIQLbCz/hoNS61muVOnNCzYa7AzKyk/img.png?width=800&amp;amp;height=393&amp;amp;face=0_0_800_393,https://scrap.kakaocdn.net/dn/DKM4g/hyUlttVK3S/O1wOuF3rvWK8hqrr2vgnf0/img.png?width=800&amp;amp;height=393&amp;amp;face=0_0_800_393,https://scrap.kakaocdn.net/dn/bXo6ZC/hyUnTSgZLp/S606brkeKi4NPGgcoE4T4k/img.png?width=1414&amp;amp;height=604&amp;amp;face=0_0_1414_604&quot;&gt;&lt;a href=&quot;https://joelinseoul.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://joelinseoul.tistory.com/16&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d3jGCc/hyUnIQLbCz/hoNS61muVOnNCzYa7AzKyk/img.png?width=800&amp;amp;height=393&amp;amp;face=0_0_800_393,https://scrap.kakaocdn.net/dn/DKM4g/hyUlttVK3S/O1wOuF3rvWK8hqrr2vgnf0/img.png?width=800&amp;amp;height=393&amp;amp;face=0_0_800_393,https://scrap.kakaocdn.net/dn/bXo6ZC/hyUnTSgZLp/S606brkeKi4NPGgcoE4T4k/img.png?width=1414&amp;amp;height=604&amp;amp;face=0_0_1414_604');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;SpringBoot 에서 JPA 사용하기 - 환경설정 하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Lombok 설치하기 Lombok을 설치하면 별도의 getter/setter 을 만들지 않아도, 어노테이션으로 간단히 객체를 다룰 수 있다. JPA 는 DB 상의 데이터를 객체처럼 다룰 수 있는 핵심 장점이 있는데, Lombok은 그&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;joelinseoul.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조회할 메소드를 JPQL 문법에 맞추어 메소드로 작성하면, 설정된 데이터베이스에 맞는 쿼리를 조회하여 결과를 리턴해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA 가 제공하는 메소드는 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;조회하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;JPA 가 제공하는 조회 메소드는 아래 표와 같다.&lt;br /&gt;&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 120px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15.8914%; height: 20px;&quot;&gt;메소드 명&lt;/td&gt;
&lt;td style=&quot;width: 27.5194%; height: 20px;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;width: 14.5736%; height: 20px;&quot;&gt;리턴&lt;/td&gt;
&lt;td style=&quot;width: 42.0155%; height: 20px;&quot;&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15.8914%; height: 20px;&quot;&gt;findAll()&lt;/td&gt;
&lt;td style=&quot;width: 27.5194%; height: 20px;&quot;&gt;모든 행 조회&lt;/td&gt;
&lt;td style=&quot;width: 14.5736%; height: 20px;&quot;&gt;List&amp;lt;객체&amp;gt;&lt;/td&gt;
&lt;td style=&quot;width: 42.0155%; height: 20px;&quot;&gt;findAll();&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15.8914%; height: 20px;&quot;&gt;findBy컬럼명()&lt;/td&gt;
&lt;td style=&quot;width: 27.5194%; height: 20px;&quot;&gt;컬럼값으로 조회&lt;/td&gt;
&lt;td style=&quot;width: 14.5736%; height: 20px;&quot;&gt;List&amp;lt;객체&amp;gt; 혹은 객체&lt;/td&gt;
&lt;td style=&quot;width: 42.0155%; height: 20px;&quot;&gt;findByName(&quot;홍길동&quot;);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15.8914%; height: 20px;&quot;&gt;countBy컬럼명()&lt;/td&gt;
&lt;td style=&quot;width: 27.5194%; height: 20px;&quot;&gt;컬럼값에 일치하는 개수 조회&lt;/td&gt;
&lt;td style=&quot;width: 14.5736%; height: 20px;&quot;&gt;long&lt;/td&gt;
&lt;td style=&quot;width: 42.0155%; height: 20px;&quot;&gt;countByUID(1);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15.8914%; height: 20px;&quot;&gt;orderBy컬럼명()&lt;/td&gt;
&lt;td style=&quot;width: 27.5194%; height: 20px;&quot;&gt;결과 정렬&lt;/td&gt;
&lt;td style=&quot;width: 14.5736%; height: 20px;&quot;&gt;List&amp;lt;객체&amp;gt;&lt;/td&gt;
&lt;td style=&quot;width: 42.0155%; height: 20px;&quot;&gt;OrderByNameDesc();&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15.8914%; height: 20px;&quot;&gt;existsBy컬럼명()&lt;/td&gt;
&lt;td style=&quot;width: 27.5194%; height: 20px;&quot;&gt;데이터 존재 여부&lt;/td&gt;
&lt;td style=&quot;width: 14.5736%; height: 20px;&quot;&gt;boolean&lt;/td&gt;
&lt;td style=&quot;width: 42.0155%; height: 20px;&quot;&gt;existsByUID(1);&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;위의 조회 메소드 표 상 메소드에 아래의 키워드를 추가할 수 있다.&lt;br /&gt;&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 260px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;keyword&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;And&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;여러&amp;nbsp;컬럼값과&amp;nbsp;일치하는&amp;nbsp;행&amp;nbsp;And&amp;nbsp;조회&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;findByNameAndEmail(name,&amp;nbsp;email)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;Or&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;여러 컬럼값과 일치하는 행 Or 조회&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #666666; text-align: left;&quot;&gt;findByNameOrEmail(name,&amp;nbsp;email)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 52px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 52px;&quot;&gt;Contains, Containing&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 52px;&quot;&gt;Like '%키워드%'&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 52px;&quot;&gt;findBySubjectContaining(&quot;키워드&quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;Like&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;&amp;nbsp;like&amp;nbsp;'키워드' &lt;br /&gt;키워드와 일치하는 것만 가져오므로 주의&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;findBySubjectLike(&quot;키워드&quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;StartingWith like&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;&amp;nbsp;'키워드%'&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;findByStartingWith(&quot;키워드&quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;Between&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;특정값 이상~이하 조회&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;&amp;nbsp;findByAgeBetween(20,&amp;nbsp;25) &lt;br /&gt;20&amp;nbsp;~&amp;nbsp;25&amp;nbsp;조회됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;In&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;&amp;nbsp;in문으로&amp;nbsp;일치하는&amp;nbsp;값&amp;nbsp;모두&amp;nbsp;조회 &lt;br /&gt;select * from 테이블 where name in ('길동', '춘향');&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;&amp;nbsp;findByNameIn(names) &lt;br /&gt;여기서&amp;nbsp;names는&amp;nbsp;List&amp;lt;String&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 26px;&quot;&gt;
&lt;td style=&quot;width: 21.4668%; height: 26px;&quot;&gt;Top&lt;/td&gt;
&lt;td style=&quot;width: 43.8401%; height: 26px;&quot;&gt;&amp;nbsp;Limit 제한 개수&lt;/td&gt;
&lt;td style=&quot;width: 34.693%; height: 26px;&quot;&gt;&amp;nbsp;한&amp;nbsp;개만&amp;nbsp;가져올&amp;nbsp;때:findTop() &lt;br /&gt;5개&amp;nbsp;가져올&amp;nbsp;때:findTop5ByOrderByNameDesc() &lt;br /&gt;※Top5&amp;nbsp;뒤에&amp;nbsp;By가&amp;nbsp;없으면&amp;nbsp;에러&amp;nbsp;발생&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;builder 패턴과 함께 사용하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;JPA 가 CRUD 하는 단위는 객체 이다.&lt;br /&gt;따라서 lombok의 builder를 활용하여 코드를 간소화 시킬 수 있다.&lt;br /&gt;
&lt;pre id=&quot;code_1698743424770&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestController
public class UserInfoController {
	@Autowired
	private UserInfoRepository userInfoRepository;
	@GetMapping(&quot;/&quot;)
	public String hello() {
		UserInfo newUser = userInfoRepository.save(UserInfo.builder()
				.name(&quot;홍길동&quot;)
				.email(&quot;hong@gil.dong&quot;)
				.build()
				);
		return newUser.toString();
	}
}​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1448&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIa6qS/btszsC6DkMP/coNy5k6zvMvz9AcDLPvlO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIa6qS/btszsC6DkMP/coNy5k6zvMvz9AcDLPvlO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIa6qS/btszsC6DkMP/coNy5k6zvMvz9AcDLPvlO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIa6qS%2FbtszsC6DkMP%2FcoNy5k6zvMvz9AcDLPvlO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1448&quot; height=&quot;780&quot; data-origin-width=&quot;1448&quot; data-origin-height=&quot;780&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;CRUD 예시&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;JPA 에서의 CRUD 를 경험하기 위해, 아래의 예시코드를 작성해 보았다.&lt;br /&gt;
&lt;pre id=&quot;code_1698746098094&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.spingblog.cases.userinfo;

import java.time.LocalDateTime;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.spingblog.cases.userinfo.domain.UserInfo;
import com.spingblog.cases.userinfo.repository.UserInfoRepository;

@RestController
public class UserInfoController {
	@Autowired
	private UserInfoRepository userInfoRepository;
	@GetMapping(&quot;/&quot;)
	public List&amp;lt;UserInfo&amp;gt; hello() {
		//생성 : 홍길동을 등록해라
		for(int i = 0; i &amp;lt; 2; i++) {
			userInfoRepository.save(UserInfo.builder()
					.name(&quot;홍길동&quot;)
					.email(&quot;hong@gil.dong&quot;)
					.build()
					);
		}
		
		//읽기 : 홍길동이 몇명인지 찾아라
		long countHong = userInfoRepository.countByNameLike(&quot;홍길동&quot;);
		//읽기 : 홍길동을 모두 조회하라
		List&amp;lt;UserInfo&amp;gt; findHongs = userInfoRepository.findByNameLike(&quot;홍길동&quot;);
		
        //업데이트 : 홍길동이 한명이 아니면, 기존 홍길동의 이름을 성춘향으로 수정하라
		if(countHong &amp;gt; 1) {
			UserInfo oldHong = findHongs.get(0);
			oldHong = oldHong.toBuilder()
					.name(&quot;성춘향&quot;)
					.email(&quot;sung@chun.hyang&quot;)
					.updatedAt(LocalDateTime.now())
					.build();
			userInfoRepository.save(oldHong);
		}
		
		//삭제 : 이름에 춘 이 들어가면 삭제하라
		List&amp;lt;UserInfo&amp;gt; findChun = userInfoRepository.findByNameContaining(&quot;춘&quot;);
		userInfoRepository.deleteAll(findChun);

		//읽기 : 남은 회원 중 가장 최큰에 가입한 2명을 출력하라
		List&amp;lt;UserInfo&amp;gt; findLatest2 = userInfoRepository.findTop2ByOrderByIdDesc();

		return findLatest2;
	}
}​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;위 코드 실행에 따라, 발생된 쿼리는 아래와 같다.&lt;br /&gt;
&lt;pre id=&quot;code_1698746063297&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hibernate: 
    insert 
    into
        userinfo
        (createdAt, email, name, updatedAt) 
    values
        (?, ?, ?, ?)
 [2m2023-10-31 18:47:51.922 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745671922 | took 5ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
insert into userinfo (createdAt, email, name, updatedAt) values (?, ?, ?, ?)
insert into userinfo (createdAt, email, name, updatedAt) values ('2023-10-31T18:47:51.895+0900', 'hong@gil.dong', '홍길동', '2023-10-31T18:47:51.895+0900');
 [2m2023-10-31 18:47:51.954 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745671954 | took 2ms | commit | connection 1| url jdbc:mysql://localhost:3306/springbootblog

;
Hibernate: 
    insert 
    into
        userinfo
        (createdAt, email, name, updatedAt) 
    values
        (?, ?, ?, ?)
 [2m2023-10-31 18:47:51.958 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745671958 | took 1ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
insert into userinfo (createdAt, email, name, updatedAt) values (?, ?, ?, ?)
insert into userinfo (createdAt, email, name, updatedAt) values ('2023-10-31T18:47:51.956+0900', 'hong@gil.dong', '홍길동', '2023-10-31T18:47:51.956+0900');
 [2m2023-10-31 18:47:51.962 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745671962 | took 1ms | commit | connection 1| url jdbc:mysql://localhost:3306/springbootblog

;
Hibernate: 
    select
        count(userinfo0_.id) as col_0_0_ 
    from
        userinfo userinfo0_ 
    where
        userinfo0_.name like ? escape ?
 [2m2023-10-31 18:47:52.069 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672069 | took 3ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
select count(userinfo0_.id) as col_0_0_ from userinfo userinfo0_ where userinfo0_.name like ? escape ?
select count(userinfo0_.id) as col_0_0_ from userinfo userinfo0_ where userinfo0_.name like '홍길동' escape '\';
Hibernate: 
    select
        userinfo0_.id as id1_0_,
        userinfo0_.createdAt as createda2_0_,
        userinfo0_.email as email3_0_,
        userinfo0_.name as name4_0_,
        userinfo0_.updatedAt as updateda5_0_ 
    from
        userinfo userinfo0_ 
    where
        userinfo0_.name like ? escape ?
 [2m2023-10-31 18:47:52.078 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672078 | took 1ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
select userinfo0_.id as id1_0_, userinfo0_.createdAt as createda2_0_, userinfo0_.email as email3_0_, userinfo0_.name as name4_0_, userinfo0_.updatedAt as updateda5_0_ from userinfo userinfo0_ where userinfo0_.name like ? escape ?
select userinfo0_.id as id1_0_, userinfo0_.createdAt as createda2_0_, userinfo0_.email as email3_0_, userinfo0_.name as name4_0_, userinfo0_.updatedAt as updateda5_0_ from userinfo userinfo0_ where userinfo0_.name like '홍길동' escape '\';
 [2m2023-10-31 18:47:52.090 [0;39m  [33m WARN [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mo.h.p.entity.AbstractEntityPersister     [0;39m  [2m: [0;39m HHH000502: The [createdAt] property of the [com.spingblog.cases.userinfo.domain.UserInfo] entity was modified, but it won't be updated because the property is immutable.
Hibernate: 
    update
        userinfo 
    set
        email=?,
        name=?,
        updatedAt=? 
    where
        id=?
 [2m2023-10-31 18:47:52.099 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672099 | took 1ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
update userinfo set email=?, name=?, updatedAt=? where id=?
update userinfo set email='sung@chun.hyang', name='성춘향', updatedAt='2023-10-31T18:47:52.090+0900' where id=12;
 [2m2023-10-31 18:47:52.113 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672113 | took 12ms | commit | connection 1| url jdbc:mysql://localhost:3306/springbootblog

;
Hibernate: 
    select
        userinfo0_.id as id1_0_,
        userinfo0_.createdAt as createda2_0_,
        userinfo0_.email as email3_0_,
        userinfo0_.name as name4_0_,
        userinfo0_.updatedAt as updateda5_0_ 
    from
        userinfo userinfo0_ 
    where
        userinfo0_.name like ? escape ?
 [2m2023-10-31 18:47:52.118 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672118 | took 1ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
select userinfo0_.id as id1_0_, userinfo0_.createdAt as createda2_0_, userinfo0_.email as email3_0_, userinfo0_.name as name4_0_, userinfo0_.updatedAt as updateda5_0_ from userinfo userinfo0_ where userinfo0_.name like ? escape ?
select userinfo0_.id as id1_0_, userinfo0_.createdAt as createda2_0_, userinfo0_.email as email3_0_, userinfo0_.name as name4_0_, userinfo0_.updatedAt as updateda5_0_ from userinfo userinfo0_ where userinfo0_.name like '%춘%' escape '\';
Hibernate: 
    delete 
    from
        userinfo 
    where
        id=?
 [2m2023-10-31 18:47:52.124 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672124 | took 1ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
delete from userinfo where id=?
delete from userinfo where id=12;
 [2m2023-10-31 18:47:52.127 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672127 | took 2ms | commit | connection 1| url jdbc:mysql://localhost:3306/springbootblog

;
Hibernate: 
    select
        userinfo0_.id as id1_0_,
        userinfo0_.createdAt as createda2_0_,
        userinfo0_.email as email3_0_,
        userinfo0_.name as name4_0_,
        userinfo0_.updatedAt as updateda5_0_ 
    from
        userinfo userinfo0_ 
    order by
        userinfo0_.id desc limit ?
 [2m2023-10-31 18:47:52.133 [0;39m  [32m INFO [0;39m  [35m12384 [0;39m  [2m--- [0;39m  [2m[nio-8080-exec-1] [0;39m  [36mp6spy                                    [0;39m  [2m: [0;39m #1698745672133 | took 0ms | statement | connection 1| url jdbc:mysql://localhost:3306/springbootblog
select userinfo0_.id as id1_0_, userinfo0_.createdAt as createda2_0_, userinfo0_.email as email3_0_, userinfo0_.name as name4_0_, userinfo0_.updatedAt as updateda5_0_ from userinfo userinfo0_ order by userinfo0_.id desc limit ?
select userinfo0_.id as id1_0_, userinfo0_.createdAt as createda2_0_, userinfo0_.email as email3_0_, userinfo0_.name as name4_0_, userinfo0_.updatedAt as updateda5_0_ from userinfo userinfo0_ order by userinfo0_.id desc limit 2;​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;565&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qMTYQ/btszzT6ah2Y/1WUkMym1dfUpumoms69olK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qMTYQ/btszzT6ah2Y/1WUkMym1dfUpumoms69olK/img.png&quot; data-alt=&quot;위 예시코드에 따라 실행 후 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qMTYQ/btszzT6ah2Y/1WUkMym1dfUpumoms69olK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqMTYQ%2FbtszzT6ah2Y%2F1WUkMym1dfUpumoms69olK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;664&quot; height=&quot;565&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;위 예시코드에 따라 실행 후 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;JPA 네이티브 쿼리&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;위와 같이 JPA는 일상적인 조회에서 코드를 간결하고 객체에 집중할 수 있도록 도와주는 강력한 메소드들을 가지고 있다.&lt;br /&gt;다만 데이터베이스의 특정 기능을 활용해야 하는 경우 등에서는 JPA 네이티브 쿼리를 활용할 수 있다.&lt;br /&gt;&lt;br /&gt;아래, mysql 의 regexp 기능을 활용하고자 할 때 JPA Native Query 를 활용한 예시이다.&lt;br /&gt;repository 에서 native query를 활용할 메서드를 작성 후, @Query 어노테이션을 추가하면 된다.&lt;br /&gt;@Query 의 파라미터는 아래와 같다.&lt;br /&gt;&amp;nbsp;- value : 쿼리 문자열을 지정하는 파라미터. SQL 문법에 맞추어 작성함.&lt;br /&gt;&amp;nbsp;- nativeQuery : 기본값은 false 이며, true 로 입력 시 value 에 작성한 텍스트를 쿼리로 사용.&lt;br /&gt;
&lt;pre id=&quot;code_1698762788150&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
public interface UserInfoRepository extends JpaRepository&amp;lt;UserInfo, Integer&amp;gt; {
	@Query(value=&quot;SELECT * FROM userinfo WHERE email REGEXP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}'&quot;, nativeQuery = true)
	public List&amp;lt;UserInfo&amp;gt; findValidEmail();
}​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vk5fX/btszvhOF9WN/8SI56p18NeMfM1KqkP3Oh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vk5fX/btszvhOF9WN/8SI56p18NeMfM1KqkP3Oh0/img.png&quot; data-alt=&quot;네이티브 쿼리를 적용한 메소드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vk5fX/btszvhOF9WN/8SI56p18NeMfM1KqkP3Oh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvk5fX%2FbtszvhOF9WN%2F8SI56p18NeMfM1KqkP3Oh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1350&quot; height=&quot;304&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이티브 쿼리를 적용한 메소드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;br /&gt;위의 메소드를 동작시키면 아래의 로그와 같이, value 값이 그대로 쿼리로 사용된 것을 알 수 있다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beLmcA/btszAlhrUOw/8HXPfpyXNKx6tt8i86bMTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beLmcA/btszAlhrUOw/8HXPfpyXNKx6tt8i86bMTK/img.png&quot; data-alt=&quot;네이티브 쿼리 동작 로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beLmcA/btszAlhrUOw/8HXPfpyXNKx6tt8i86bMTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeLmcA%2FbtszAlhrUOw%2F8HXPfpyXNKx6tt8i86bMTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1384&quot; height=&quot;71&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이티브 쿼리 동작 로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;b&gt;네이티브 쿼리&lt;/b&gt; 사용 시 한 가지 &lt;b&gt;주의&lt;/b&gt;해야 할 점이 있다.&lt;br /&gt;&lt;b&gt;JPQL&lt;/b&gt; 의 장점은 DB를 변경하더라도, &lt;b&gt;변경된 DB에 맞추어&lt;/b&gt; 객체와 그 필드를 기준으로 쿼리를 작성한다는 것이 큰 장점인데, &lt;b&gt;네이티브 쿼리&lt;/b&gt;의 경우 &lt;b&gt;DB에 종속적인 SQL 문법&lt;/b&gt;을 따르게 되며, DB변경 시 &lt;b&gt;변경 된 DB에 맞춘 문법으로 수정&lt;/b&gt;해야 한다.&lt;br /&gt;따라서 네이티브 쿼리 보다는 myBatis 를 함께 사용 하는 것이 나을 것이다.&lt;/blockquote&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>SpringBoot/JPA</category>
      <category>JPA 사용법</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/17</guid>
      <comments>https://joelinseoul.tistory.com/17#entry17comment</comments>
      <pubDate>Tue, 31 Oct 2023 23:50:33 +0900</pubDate>
    </item>
    <item>
      <title>SpringBoot 에서 JPA 사용하기 - 환경설정 하기</title>
      <link>https://joelinseoul.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Lombok 설치하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lombok을 설치하면 별도의 getter/setter 을 만들지 않아도, 어노테이션으로 간단히 객체를 다룰 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA 는 DB 상의 데이터를 객체처럼 다룰 수 있는 핵심 장점이 있는데, Lombok은 그 장점을 더욱 돋보이게 해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lombok 설치는 아래 글에서 확인할 수 있다.&lt;/p&gt;
&lt;figure id=&quot;og_1698734488935&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;이클립스에 Lombok 설치하기&quot; data-og-description=&quot;Lombok 은 객체지향 개발을 편리하게 해주는 라이브러리이다. Entity 클래스 에서 직접 Getter/Setter 를 만들 필요 없이, @Data 혹은 @Getter/@Setter 등의 어노테이션만 추가하면 객체를 편리하게 사용하게 &quot; data-og-host=&quot;joelinseoul.tistory.com&quot; data-og-source-url=&quot;https://joelinseoul.tistory.com/15&quot; data-og-url=&quot;https://joelinseoul.tistory.com/15&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cEwqUH/hyUnJhFWpH/O0YbtE7xZwu6kdyxzbIxzK/img.png?width=800&amp;amp;height=464&amp;amp;face=0_0_800_464,https://scrap.kakaocdn.net/dn/bzpOgq/hyUj7Ezq14/PBALwchLCgAcZvsn7Hz1S0/img.png?width=800&amp;amp;height=464&amp;amp;face=0_0_800_464,https://scrap.kakaocdn.net/dn/UL5lv/hyUluGe2jG/1ksjhZQc7si28qkop4KyK0/img.png?width=1268&amp;amp;height=744&amp;amp;face=0_0_1268_744&quot;&gt;&lt;a href=&quot;https://joelinseoul.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://joelinseoul.tistory.com/15&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cEwqUH/hyUnJhFWpH/O0YbtE7xZwu6kdyxzbIxzK/img.png?width=800&amp;amp;height=464&amp;amp;face=0_0_800_464,https://scrap.kakaocdn.net/dn/bzpOgq/hyUj7Ezq14/PBALwchLCgAcZvsn7Hz1S0/img.png?width=800&amp;amp;height=464&amp;amp;face=0_0_800_464,https://scrap.kakaocdn.net/dn/UL5lv/hyUluGe2jG/1ksjhZQc7si28qkop4KyK0/img.png?width=1268&amp;amp;height=744&amp;amp;face=0_0_1268_744');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;이클립스에 Lombok 설치하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Lombok 은 객체지향 개발을 편리하게 해주는 라이브러리이다. Entity 클래스 에서 직접 Getter/Setter 를 만들 필요 없이, @Data 혹은 @Getter/@Setter 등의 어노테이션만 추가하면 객체를 편리하게 사용하게&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;joelinseoul.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;spring-boot-starter-data-jpa 의존성 추가&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;우선 그래들에 의존성을 추가한다.&lt;br /&gt;build.gradle에서 스프링부트의 스타터 중 하나인 spring-boot-starter-data-jpa 의존성을 추가한다.&lt;br /&gt;&lt;br /&gt;* build.gradle을 수정했다면 잊지말고 refresh gradle project 를 하길 바란다.&amp;nbsp;&lt;br /&gt;
&lt;pre id=&quot;code_1698729976878&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1226&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfDwwO/btszvDDnILK/2YJaXXQIeeG3GIq6J14cE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfDwwO/btszvDDnILK/2YJaXXQIeeG3GIq6J14cE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfDwwO/btszvDDnILK/2YJaXXQIeeG3GIq6J14cE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfDwwO%2FbtszvDDnILK%2F2YJaXXQIeeG3GIq6J14cE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1226&quot; height=&quot;603&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1226&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;P6Spy 의존성 추가 (선택)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;P6Spy 는 JDBC 드라이버의 프록시로 작동하여 SQL 쿼리를 가로채서 로깅하는 라이브러리다.&lt;br /&gt;이 의존성을 추가하면 콘솔을 통해 쿼리 결과를 실시간으로 볼 수 있다.&lt;br /&gt;필요 여부에 따라 추가하면 된다. (성능에 영향을 주기 때문에)&lt;br /&gt;
&lt;pre id=&quot;code_1698735738365&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.7'​&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C1PUX/btszviM6MU1/lYaBHjtSEtw2fE5LfUSrj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C1PUX/btszviM6MU1/lYaBHjtSEtw2fE5LfUSrj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C1PUX/btszviM6MU1/lYaBHjtSEtw2fE5LfUSrj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC1PUX%2FbtszviM6MU1%2FlYaBHjtSEtw2fE5LfUSrj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1414&quot; height=&quot;604&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;이를 추가하면, 아래와 같이 콘솔에서 쿼리 처리 결과를 확인할 수 있다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1690&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbQTxw/btszvF86cvH/K4zEbW8CS5dtBfl932Rov1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbQTxw/btszvF86cvH/K4zEbW8CS5dtBfl932Rov1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbQTxw/btszvF86cvH/K4zEbW8CS5dtBfl932Rov1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbQTxw%2FbtszvF86cvH%2FK4zEbW8CS5dtBfl932Rov1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1690&quot; height=&quot;253&quot; data-origin-width=&quot;1690&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;application.yml 수정하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;최소 동작을 위한 필수 설정은 끝났다.&lt;br /&gt;이제 좀더 유연하고 편하게 JPA 를 즐길 수 있도록, application.yml 을 설정한다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;나의 default 설정값은 아래와 같다.&lt;br /&gt;
&lt;pre id=&quot;code_1698736020674&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
    hibernate:
      naming:
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
      ddl-auto: none​&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1471&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cj66vp/btszwcsfabM/bE3EWsP5JQi53JH7HJYT40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cj66vp/btszwcsfabM/bE3EWsP5JQi53JH7HJYT40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cj66vp/btszwcsfabM/bE3EWsP5JQi53JH7HJYT40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcj66vp%2FbtszwcsfabM%2FbE3EWsP5JQi53JH7HJYT40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1471&quot; height=&quot;305&quot; data-origin-width=&quot;1471&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&amp;nbsp;위 설정의 내용은 key에 따른 옵션 별 내용을 담은 아래 표를 참고하길 바란다.&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 27.7503%;&quot;&gt;&amp;nbsp;key&lt;/td&gt;
&lt;td style=&quot;width: 72.2497%;&quot;&gt;option&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 27.7503%;&quot;&gt;&amp;nbsp;spring.jpa.show-sql&lt;/td&gt;
&lt;td style=&quot;width: 72.2497%;&quot;&gt;true: JPA 쿼리문 확인 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 27.7503%;&quot;&gt;spring.jpa.hibernate.ddl-auto&lt;/td&gt;
&lt;td style=&quot;width: 72.2497%;&quot;&gt;create:기존&amp;nbsp;테이블을&amp;nbsp;삭제&amp;nbsp;후&amp;nbsp;새로&amp;nbsp;생성 &lt;br /&gt;create-drop:기존&amp;nbsp;테이블을&amp;nbsp;삭제&amp;nbsp;후&amp;nbsp;새로&amp;nbsp;생성&amp;nbsp;+&amp;nbsp;종료&amp;nbsp;후&amp;nbsp;다시&amp;nbsp;drop &lt;br /&gt;(drop&amp;nbsp;+&amp;nbsp;create&amp;nbsp;+&amp;nbsp;drop) &lt;br /&gt;update:테이블과&amp;nbsp;매핑&amp;nbsp;정보&amp;nbsp;비교&amp;nbsp;후&amp;nbsp;변경사항만&amp;nbsp;수정(만약&amp;nbsp;기존&amp;nbsp;테이블&amp;nbsp;없으면&amp;nbsp;create) &lt;br /&gt;validate:차이가&amp;nbsp;있으면&amp;nbsp;경고를&amp;nbsp;날린&amp;nbsp;후&amp;nbsp;수행하지&amp;nbsp;않음 &lt;br /&gt;none:테이블&amp;nbsp;자동&amp;nbsp;생성기능&amp;nbsp;사용&amp;nbsp;안함(있는&amp;nbsp;테이블로&amp;nbsp;사용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 27.7503%;&quot;&gt;spring.jpa.properties.hibernate.format_sql&lt;/td&gt;
&lt;td style=&quot;width: 72.2497%;&quot;&gt;true:&amp;nbsp;jpa&amp;nbsp;구현체인&amp;nbsp;하이버네이트&amp;nbsp;동적쿼리&amp;nbsp;로그를&amp;nbsp;예쁘게&amp;nbsp;출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 27.7503%;&quot;&gt;&lt;span&gt;spring.jpa.hibernate.naming.implicit-strategy&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 72.2497%;&quot;&gt;설정 시 객체 명과 테이블 명이 같을 경우 해당 객체명을 테이블명으로 사용.&lt;br /&gt;&lt;span&gt;org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 27.7503%;&quot;&gt;&lt;span&gt;spring.jpa.hibernate.naming.physical-strategy&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 72.2497%;&quot;&gt;설정 시 테이블 명이나 컬럼 명을 변환하지 않고 그대로 사용함.&lt;br /&gt;(카멜케이스인 컬럼명을 사용할 수 있음.)&lt;br /&gt;&lt;span&gt;org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;객체 설정 방법&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;JPA 는 객체 단위의 DB 처리를 하므로, 객체마다 JPA가 인식할 수 있도록 설정하는 것이 필요하다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;우선 간단한 예시를 들자면 아래와 같다.&lt;br /&gt;
&lt;pre id=&quot;code_1698738789492&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity						 // jpa가 인식할 수 있도록 선언
@ToString					 // 객체 변수 값을 문자열로 반호나해서 객체의 상태를 쉽게 확인.
@Builder(toBuilder = true)	 // 객체 생성/수정 등을 할 수 있도록 빌더 패턴 생성.
@NoArgsConstructor			 // 매개변수가 없는 기본 생성자를 생성.
@AllArgsConstructor			 // 전체 생성자 생성
@Table(name = &quot;userinfo&quot;)	 //테이블 명 매핑
@Data						 //Getter 및 Setter 자동 생성
public class UserInfo {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;
	private String name;
	private String email;
	@UpdateTimestamp
	@Column(name=&quot;createdAt&quot;, updatable=false)
	private LocalDateTime createdAt;
	@UpdateTimestamp
	@Column(name=&quot;updatedAt&quot;)
	private LocalDateTime updatedAt;
	
}​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDu7oB/btszyKu8PDX/NRtnkpIZQ4H04x49vskZUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDu7oB/btszyKu8PDX/NRtnkpIZQ4H04x49vskZUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDu7oB/btszyKu8PDX/NRtnkpIZQ4H04x49vskZUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDu7oB%2FbtszyKu8PDX%2FNRtnkpIZQ4H04x49vskZUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;778&quot; height=&quot;806&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;아래는 javax.persistence 라이브러리에 포함되는 어노테이션이다.&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;어노테이션&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;@Entity&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;해당 클래스를 JPA 엔티티로 선언.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;@Table&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;해당 객체와 매핑시킬 DB 상의 테이블 이름 설정. &lt;br /&gt;미작성 시 클래스 이름이 테이블 명으로 설정됨.&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;* 파라미터&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&amp;nbsp; - name : 매핑시킬 테이블명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;@Column&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;객체의 변수와 매핑될 DB상의 컬럼 이름 설정.&lt;br /&gt;미작성 시 변수 이름이 컬럼 명으로 설정됨.&lt;br /&gt;(변수 명이 카멜케이스로 작성 되었다면 Column 설정 필수)&lt;br /&gt;* 파라미터&lt;br /&gt;&amp;nbsp; - name : 매핑시킬 컬럼명&lt;br /&gt;&amp;nbsp; - updatable : 수정 가능 여부&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;@Id&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;객체의 Primary Key 선언.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;@GeneratedValue&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;Primary Key의 생성 방법 설정.&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;* 파라미터&lt;/span&gt; &lt;br /&gt;&amp;nbsp; - strategy=GenerationType.IDENTITY : auto increment 와 같음.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.3226%;&quot;&gt;@UpdateTimestamp&lt;/td&gt;
&lt;td style=&quot;width: 78.6774%;&quot;&gt;rdb query 상 DEFAULT CURRENT_TIMESTAMP 와 같음.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Repository 에서 JpaRepository extends 하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;MVC 패턴으로 작성된 애플리케이션이라면 객체에 따른 Repository 인터페이스가 있을 것이다.&lt;br /&gt;없다면 해당 객체를 다룰 수 있는 repository를 만들고, repository 에 JpaRepository 를 extends 해야 한다.&lt;br /&gt;&lt;br /&gt;아래는 위의 UserInfo 객체 예시에 해당하는 Repository 이다.&lt;br /&gt;이 인터페이스는 JpaRepository를 상속받으며, 객체의 타입과 ID 타입을 선언해야 한다.&lt;br /&gt;
&lt;pre id=&quot;code_1698739493606&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Repository
public interface UserInfoRepository extends JpaRepository&amp;lt;UserInfo, Integer&amp;gt; {

}​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3Byj5/btszvEQeBKR/id5E977ht1RK9ipjPQx90k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3Byj5/btszvEQeBKR/id5E977ht1RK9ipjPQx90k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3Byj5/btszvEQeBKR/id5E977ht1RK9ipjPQx90k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3Byj5%2FbtszvEQeBKR%2Fid5E977ht1RK9ipjPQx90k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;286&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;286&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;JPA 사용 준비 완료&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;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a href=&quot;https://joelinseoul.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;다음 글 : JPA 활용하기&lt;/b&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1698763902526&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;SpringBoot 에서 JPA 사용하기 - 활용 하기&quot; data-og-description=&quot;이전 글: JPA 환경설정 하기 SpringBoot 에서 JPA 사용하기 - 환경설정 하기 Lombok 설치하기 Lombok을 설치하면 별도의 getter/setter 을 만들지 않아도, 어노테이션으로 간단히 객체를 다룰 수 있다. JPA 는 DB&quot; data-og-host=&quot;joelinseoul.tistory.com&quot; data-og-source-url=&quot;https://joelinseoul.tistory.com/17&quot; data-og-url=&quot;https://joelinseoul.tistory.com/17&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/u0ZIY/hyUnTres54/JTuK1nVlqFmwqr8raZoAdk/img.png?width=800&amp;amp;height=430&amp;amp;face=0_0_800_430,https://scrap.kakaocdn.net/dn/bgUP7U/hyUnOKcqDF/I8xQis4K5XOKkmjWVjh5O1/img.png?width=800&amp;amp;height=430&amp;amp;face=0_0_800_430,https://scrap.kakaocdn.net/dn/b3pMlg/hyUnJ9Yerl/XBlgYu2UGOn0knnGyNfVlK/img.png?width=1448&amp;amp;height=780&amp;amp;face=0_0_1448_780&quot;&gt;&lt;a href=&quot;https://joelinseoul.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://joelinseoul.tistory.com/17&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/u0ZIY/hyUnTres54/JTuK1nVlqFmwqr8raZoAdk/img.png?width=800&amp;amp;height=430&amp;amp;face=0_0_800_430,https://scrap.kakaocdn.net/dn/bgUP7U/hyUnOKcqDF/I8xQis4K5XOKkmjWVjh5O1/img.png?width=800&amp;amp;height=430&amp;amp;face=0_0_800_430,https://scrap.kakaocdn.net/dn/b3pMlg/hyUnJ9Yerl/XBlgYu2UGOn0knnGyNfVlK/img.png?width=1448&amp;amp;height=780&amp;amp;face=0_0_1448_780');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;SpringBoot 에서 JPA 사용하기 - 활용 하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전 글: JPA 환경설정 하기 SpringBoot 에서 JPA 사용하기 - 환경설정 하기 Lombok 설치하기 Lombok을 설치하면 별도의 getter/setter 을 만들지 않아도, 어노테이션으로 간단히 객체를 다룰 수 있다. JPA 는 DB&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;joelinseoul.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>SpringBoot/JPA</category>
      <category>JPA 설정</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/16</guid>
      <comments>https://joelinseoul.tistory.com/16#entry16comment</comments>
      <pubDate>Tue, 31 Oct 2023 17:13:23 +0900</pubDate>
    </item>
    <item>
      <title>이클립스에 Lombok 설치하기</title>
      <link>https://joelinseoul.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;Lombok 라이브러리는 객체지향 개발을 편리하게 해준다.&amp;nbsp;&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;Entity 클래스 에서 직접 Getter/Setter 를 만들 필요 없이, @Data 혹은 @Getter/@Setter 등의 어노테이션만 추가하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 편리하게 사용하게 해준다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 이클립스 (STS)&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;&amp;nbsp;- gradle&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Lombok.jar 다운받기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;아래 URL에서 Lombok을 다운받는다.&lt;br /&gt;&lt;a href=&quot;https://projectlombok.org/downloads/lombok.jar&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://projectlombok.org/downloads/lombok.jar&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Lombok.jar 설치하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;위에서 다운받은 Lombok을 열면 아래의 설치화면이 나온다.&amp;nbsp;&lt;br /&gt;설치 프로그램에서 자동으로 IDE 리스트를 보여주는데, 여기서 각자 적용할 IDE 를 선택해 주면 된다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;※ 주의사항&lt;br /&gt;&lt;/b&gt;lombok.jar 의 위치가 한글 폴더로 되어있으면 안된다!&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oM4BS/btszviGdp3D/i6ugtWvWmf0Q9YYqLAHPj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oM4BS/btszviGdp3D/i6ugtWvWmf0Q9YYqLAHPj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oM4BS/btszviGdp3D/i6ugtWvWmf0Q9YYqLAHPj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoM4BS%2FbtszviGdp3D%2Fi6ugtWvWmf0Q9YYqLAHPj1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1244&quot; height=&quot;722&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;혹시 STS 와 같은 IDE를 설치하지 않고 사용하는 경우에는, Specify location을 클릭해, 아래 화면에서 선택할 수 있다. STS 실행파일이 있는 경로의 폴더를 선택해 주면 된다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbkLqj/btszuumOpXj/OrUha9EOon9SnXhkOsjUt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbkLqj/btszuumOpXj/OrUha9EOon9SnXhkOsjUt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbkLqj/btszuumOpXj/OrUha9EOon9SnXhkOsjUt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbkLqj%2FbtszuumOpXj%2FOrUha9EOon9SnXhkOsjUt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1268&quot; height=&quot;744&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;744&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Install Successful 화면이 나오면 IDE 경로로 들어가 Lombok 파일이 생성되었는지 확인해 보자.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgzSEM/btszvjZwAfe/MHsIDtzmLiBQ0Xw1w9O7K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgzSEM/btszvjZwAfe/MHsIDtzmLiBQ0Xw1w9O7K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgzSEM/btszvjZwAfe/MHsIDtzmLiBQ0Xw1w9O7K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgzSEM%2FbtszvjZwAfe%2FMHsIDtzmLiBQ0Xw1w9O7K0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1096&quot; height=&quot;770&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;build.gradle에 Lombok 의존성 추가하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;이제 IDE로 돌아와, build.gradle 에 아래 두개의 의존성을 추가한다.&lt;br /&gt;
&lt;pre id=&quot;code_1698733587493&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'​&lt;/code&gt;&lt;/pre&gt;
* build.gradle을 수정했다면 잊지말고 refresh gradle project 를 하길 바란다.&amp;nbsp;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HQyVR/btszvgVZ8az/sDHr8U91cdY0KAYhKgCTe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HQyVR/btszvgVZ8az/sDHr8U91cdY0KAYhKgCTe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HQyVR/btszvgVZ8az/sDHr8U91cdY0KAYhKgCTe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHQyVR%2FbtszvgVZ8az%2FsDHr8U91cdY0KAYhKgCTe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1252&quot; height=&quot;544&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold; border-bottom: 1px solid #3A3A3A; margin: 10px 0px 5px; border-left: 5px solid #3A3A3A; letter-spacing: -0.07em; line-height: 30px; padding: 0px 10px 1px;&quot; data-ke-size=&quot;size18&quot;&gt;Lombok 동작 확인&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;먼저 프로젝트를 Clean 한다.&lt;br /&gt;(상단 메뉴 바 &amp;gt; Project &amp;gt; Clean)&lt;br /&gt;&lt;br /&gt;이제 Entity 객체에 @Data, @Getter 등을 추가하고, getter가 동작하는지 확인하면 정상동작 까지 확인완료.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebEQ7Q/btszuKXmoad/5cXQRUmpDLz6jLG8koNSv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebEQ7Q/btszuKXmoad/5cXQRUmpDLz6jLG8koNSv1/img.png&quot; data-alt=&quot;UserInfo 객체에 @Data 어노테이션 작성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebEQ7Q/btszuKXmoad/5cXQRUmpDLz6jLG8koNSv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FebEQ7Q%2FbtszuKXmoad%2F5cXQRUmpDLz6jLG8koNSv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;319&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;UserInfo 객체에 @Data 어노테이션 작성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pk8V9/btszut2yKrP/Oouc32tdEYmKPeR8afVxKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pk8V9/btszut2yKrP/Oouc32tdEYmKPeR8afVxKK/img.png&quot; data-alt=&quot;이제 UserInfo 객체에서 getName으로 name을 받아올 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pk8V9/btszut2yKrP/Oouc32tdEYmKPeR8afVxKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpk8V9%2Fbtszut2yKrP%2FOouc32tdEYmKPeR8afVxKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;281&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;535&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이제 UserInfo 객체에서 getName으로 name을 받아올 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;__endic_crx__&quot;&gt;
&lt;div class=&quot;css-diqpy0&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>SpringBoot</category>
      <category>Lombok 설치</category>
      <author>kibal.countinue</author>
      <guid isPermaLink="true">https://joelinseoul.tistory.com/15</guid>
      <comments>https://joelinseoul.tistory.com/15#entry15comment</comments>
      <pubDate>Tue, 31 Oct 2023 15:39:04 +0900</pubDate>
    </item>
  </channel>
</rss>