๋ฐฐ์ด๊ฒ
Git
- Cherry-Pick
๐ก cherry-pick์ ์๊ฒ๋ ๋ฐฐ๊ฒฝ
- ์ค๋ ์์ ์ ํ๋ค๊ฐ jira์ ํฐ์ผ ๋จ์๋ก ๋ธ๋์น๋ฅผ ์์ฑํด ๊ฐ๋ฐ์ ํ๋ ค๋ค ๋ณด๋ feat-99 ์์ ๊ฐ๋ฐํ ์ฝ๋๊ฐ feat-103์ ํ์ํ๊ฒ ๋ ๊ฒฝ์ฐ๊ฐ ์์๋ค. ํ์ง๋ง feat-99๋ฅผ Pull Request๋ฅผ ํ๊ณ ๋๋ ํ์๋ค์ด pr์ ๋ฐ์์ฃผ๊ณ ๋ด๊ฐ upstream ์์ ๊ฐ์ ธ์ฌ ๋ ๊น์ง ํด๋น ์ฝ๋๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๊ณ ์์๋ค! ํ์์ด ํด๋น ์ฝ๋๋ฅผ ๋ฐ๋ก ์์ฑํ๋ผ ํ์์ผ๋ cherry-pick ์ ๋ํด์ ์๊ฒ ๋์ด ์ฌ์ฉํ๊ฒ ๋์๋ค.
- feat-99 ์์ ๊ฐ๋ฐํ ์ปค๋ฐ ๊ธฐ๋ก์ feat-103 ๋ธ๋์น๋ก ๊ฐ์ ธ์ฌ ์ ์์๋ค.
- ์ด๋ฌํ ๊ณผ์ ๋์ ๊ฐ๋ฐ์ ์์ํ ํ ์ ์์๋ค.
- ๋ฌผ๋ก ๋ฆฌ๋ทฐ ๊ณผ์ ์์ ํด๋น ๋ก์ง์ด ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ๋ฌธ์ ๊ฐ ์๊ธด๋ค..!
- ๋ด๊ฐ ์ํ๋ ์ปค๋ฐ๋ค๋ง ๊ฐ์ ธ์์ ์ธ ์ ์๋๊ฒ์ผ๋ก๋ ์๊ณ ์๋ค.
- ๋ด๊ฐ pr ์ฌ๋ฆฐ ์ฝ๋๊ฐ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด cherry-pick๊ณผ rebase๋ฅผ ํตํด ๊น๋ํ๊ฒ ์งํํ ์ ์์๋ค.


- ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
Docker
- SpringBoot ์ด๋ฏธ์งํ ํ๊ธฐ
- SpringBoot๋ฅผ dockerfile ์ ํตํด ์ด๋ฏธ์งํ ํ์๋ค.
- springBoot ํ๋ก์ ํธ๋ฅผ
./gradlew clean build
๋ฅผ ํตํด jar ํ์ผ๋ก ๋ง๋ค์ด ์ค๋ค. - ์ดํ dockerfile์ ์์ฑํ๋ค.
FROM amazoncorretto:17
CMD ["./mvnw", "clean", "package"]
ARG JAR_FILE=target/*.jar
COPY ./.env ./.env
COPY ./build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
- ์ด๋ .env ํ์ผ์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ณต์ฌํด ์ต์์ ๋๋ ํ ๋ฆฌ์ ๋์ ์ ์๊ฒ ์ค์ ํ๋ค.
- ์ดํ
docker build -f Dockerfile -t diarist:0.0.1 .
๋ฅผ ํตํด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ค. docker run -p 8080:8080 diarist:0.0.1
๋ก ์ ์ ์๋ํ๋์ง ํ์ธํ๋ค.
Swagger
SpringDocs๋ฅผ ํตํด API๋ฌธ์ํ๋ฅผ ๋ฐ๋ก ํ์ง ์์๋ ํ ์ ์๋ค!
Swagger์ ๋ฒ์ ์ 3.x.x๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค. 3.0.0 ๋ฒ์ ๋ถํฐ API Test๋ฅผ ์ํด ์ ์ํด์ผ ํ๋ url ์ด ๋ฐ๋์๋ค๊ณ ํ๋ค.
Swagger
SpringBoot ์์ swagger ์ฐ๊ธฐ
- ์์กด์ฑ ์ถ๊ฐ
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
SwaggerConfig
ํด๋์ค ์์ฑ@Configuration public class SwaggerConfig { @Bean public OpenAPI openAPI() { String jwt = "JWT"; SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt); Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme() .name(jwt) .type(SecurityScheme.Type.HTTP) .scheme("bearer") .bearerFormat("JWT") ); return new OpenAPI() .components(new Components()) .info(apiInfo()) .addSecurityItem(securityRequirement) .components(components); } private Info apiInfo() { return new Info() .title("API Test") // API์ ์ ๋ชฉ .description("Let's practice Swagger UI") // API์ ๋ํ ์ค๋ช .version("1.0.0"); // API์ ๋ฒ์ } }
@Configuration public class SwaggerConfig { @Bean public OpenAPI openAPI() { return new OpenAPI() .components(new Components()) .info(apiInfo()); } private Info apiInfo() { return new Info() .title("API Test") // API์ ์ ๋ชฉ .description("Let's practice Swagger UI") // API์ ๋ํ ์ค๋ช .version("1.0.0"); // API์ ๋ฒ์ } }
application.yml ํ์ผ ์ค์
springdoc:
swagger-ui:
path: /api-test # swagger-ui ์ ๊ทผ ๊ฒฝ๋ก์ ๋ํ ๋ณ์นญ, ํด๋น ์ฃผ์๋ก ์ ์ํด๋ http://localhost:8080/swagger-ui/index.html๋ก ๋ฆฌ๋ค์ด๋ ์
๋จ.
groups-order: DESC # path, query, body, response ์์ผ๋ก ์ถ๋ ฅ
tags-sorter: alpha # ํ๊ทธ๋ฅผ ์ํ๋ฒณ ์์ผ๋ก ์ ๋ ฌ
operations-sorter: method # delete - get - patch - post - put ์์ผ๋ก ์ ๋ ฌ, alpha๋ฅผ ์ฌ์ฉํ๋ฉด ์ํ๋ฒณ ์์ผ๋ก ์ ๋ ฌ ๊ฐ๋ฅ
paths-to-match:
- /api/** # swagger-ui์ ํ์ํ api์ ์๋ํฌ์ธํธ ํจํด
- @anotation ์ค์ ํ๊ธฐ
@Operation(summary = "์
์ฒด ํ์๊ฐ์
", description = "์
์ฒด ์ธก์์ ํ์๊ฐ์
ํ ๋ ์ฌ์ฉํ๋ API")
public BaseResponse<CompanySignupRes> signUp(@RequestBody CompanySignupReq request) {
// @Operation์ผ๋ก api์ ๋ํ ์ค๋ช
๊ณผ ์์ฝ์ ์์ฑํ ์ ์๋ค.
@ApiResponses(value = {
@ApiResponse(responseCode = "1000", description = "์์ฒญ์ ์ฑ๊ณตํ์์ต๋๋ค.", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "2002", description = "์ด๋ฏธ ๊ฐ์
๋ ๊ณ์ ์
๋๋ค.", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "4000", description = "๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์คํจํ์์ต๋๋ค.", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "4011", description = "๋น๋ฐ๋ฒํธ ์ํธํ์ ์คํจํ์์ต๋๋ค.", content = @Content(mediaType = "application/json"))
})
//@ApiResponses ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ, ์๋ต ์ฝ๋์ ๋ํ ์ ๋ณด๋ฅผ ๋ํ๋ผ ์๋ ์๋ค.
@Parameters({
@Parameter(name = "email", description = "์ด๋ฉ์ผ", example = "chrome123@naver.com"),
@Parameter(name = "password", description = "6์~12์ ์ด๋ด", example = "abcd1234"),
@Parameter(name = "companyName", description = "์
์ฒด๋ช
", example = "์ฝ๋ฆฌ์ ์์คํ
"),
@Parameter(name = "companyNumber", description = "์
์ฒด ๋ฒํธ", example = "112233"),
@Parameter(name = "companyAddress", description = "์
์ฒด ์ฃผ์", example = "์ธ์ฒ์ ๋ฏธ์ถํ๊ตฌ ์ฉํ๋")
})
//@Parameters ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ, ํ๋ผ๋ฏธํฐ์ ๋ํ ์ ๋ณด๋ฅผ ๋ํ๋ผ ์ ์๋ค.
CORS ์ค์ ํ๊ธฐ
- corsConfig ๋ฅผ ํด์ฃผ์ด์ผ ํ๋ค.
- Spring์ webMvcConfigurer ๋ฅผ ํตํด cors ์ค์ ์ ํด์ค ์ ์๋ค.
package com.hanium.diarist.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173", // ๋ฆฌ์กํธ ์น ์ ํ๋ฆฌ์ผ์ด์
"http://10.0.2.2:8081", // ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ (์๋๋ก์ด๋)
"http://localhost:8081", // ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ (iOS)
// "http://<YOUR_DEVICE_IP>:8081", // ์ค์ ๋๋ฐ์ด์ค์ IP ์ฃผ์์ ํฌํธ
"http://localhost:8000", // ์ฅ๊ณ ์๋ฒ
"http://localhost:8080/swagger-ui/index.html"
// "http://<YOUR_DJANGO_SERVER_IP>:8000" // ์ฅ๊ณ ์๋ฒ IP ์ฃผ์
)
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}
CreatedAt, updatedAt - JPA๋ก ์ฐ๊ธฐ
- createdAt ํ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ BaseEntity ์ updatedAt ์ ๊ฐ์ง๊ณ ์๋ BaseEntity๋ฅผ ์์๋ฐ์ BaseEntityWithUpdate ํด๋์ค๋ฅผ ์์ฑํ์๋ค.
- ์ดํ ์คํ๋ง๋ถํธ๊ฐ ์คํ๋ ๋ JPA๋ฅผ ํตํด ํด๋น ํ๋๋ฅผ ์์๋ฐ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ฑฐ๋ ํ ๋ ํด๋น ๋ก์ง์ด ์คํ์ด ๋์ด์ผ ํ๋ค
@EnableJpaAuditing
์ฝ๋๊ฐ application ํ์ผ์ ํ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ ํด๋์ค๋
package com.hanium.diarist.common.entity;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
}
EntityListners
๋ฅผ ํตํด CreatedDate๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
'๐ฅํ๋ก์ ํธ๐ฅ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Trouble Shooting - ๊ตฌ๊ธ ๋ก๊ทธ์ธ, Swagger ๐ซ (1) | 2024.08.05 |
---|---|
~ 7/29 ํ์ด์ ํ๋ก์ ํธ ๊ณต๋ชจ์ sprint 2๐ฅ (1) | 2024.08.05 |
~ 6/17 ํ์ด์ ํ๋ก์ ํธ ๊ณต๋ชจ์ sprint 1๐ฅ (0) | 2024.06.17 |
๋ฐฐ์ด๊ฒ
Git
- Cherry-Pick
๐ก cherry-pick์ ์๊ฒ๋ ๋ฐฐ๊ฒฝ
- ์ค๋ ์์ ์ ํ๋ค๊ฐ jira์ ํฐ์ผ ๋จ์๋ก ๋ธ๋์น๋ฅผ ์์ฑํด ๊ฐ๋ฐ์ ํ๋ ค๋ค ๋ณด๋ feat-99 ์์ ๊ฐ๋ฐํ ์ฝ๋๊ฐ feat-103์ ํ์ํ๊ฒ ๋ ๊ฒฝ์ฐ๊ฐ ์์๋ค. ํ์ง๋ง feat-99๋ฅผ Pull Request๋ฅผ ํ๊ณ ๋๋ ํ์๋ค์ด pr์ ๋ฐ์์ฃผ๊ณ ๋ด๊ฐ upstream ์์ ๊ฐ์ ธ์ฌ ๋ ๊น์ง ํด๋น ์ฝ๋๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๊ณ ์์๋ค! ํ์์ด ํด๋น ์ฝ๋๋ฅผ ๋ฐ๋ก ์์ฑํ๋ผ ํ์์ผ๋ cherry-pick ์ ๋ํด์ ์๊ฒ ๋์ด ์ฌ์ฉํ๊ฒ ๋์๋ค.
- feat-99 ์์ ๊ฐ๋ฐํ ์ปค๋ฐ ๊ธฐ๋ก์ feat-103 ๋ธ๋์น๋ก ๊ฐ์ ธ์ฌ ์ ์์๋ค.
- ์ด๋ฌํ ๊ณผ์ ๋์ ๊ฐ๋ฐ์ ์์ํ ํ ์ ์์๋ค.
- ๋ฌผ๋ก ๋ฆฌ๋ทฐ ๊ณผ์ ์์ ํด๋น ๋ก์ง์ด ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ๋ฌธ์ ๊ฐ ์๊ธด๋ค..!
- ๋ด๊ฐ ์ํ๋ ์ปค๋ฐ๋ค๋ง ๊ฐ์ ธ์์ ์ธ ์ ์๋๊ฒ์ผ๋ก๋ ์๊ณ ์๋ค.
- ๋ด๊ฐ pr ์ฌ๋ฆฐ ์ฝ๋๊ฐ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด cherry-pick๊ณผ rebase๋ฅผ ํตํด ๊น๋ํ๊ฒ ์งํํ ์ ์์๋ค.


- ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
Docker
- SpringBoot ์ด๋ฏธ์งํ ํ๊ธฐ
- SpringBoot๋ฅผ dockerfile ์ ํตํด ์ด๋ฏธ์งํ ํ์๋ค.
- springBoot ํ๋ก์ ํธ๋ฅผ
./gradlew clean build
๋ฅผ ํตํด jar ํ์ผ๋ก ๋ง๋ค์ด ์ค๋ค. - ์ดํ dockerfile์ ์์ฑํ๋ค.
FROM amazoncorretto:17
CMD ["./mvnw", "clean", "package"]
ARG JAR_FILE=target/*.jar
COPY ./.env ./.env
COPY ./build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
- ์ด๋ .env ํ์ผ์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ณต์ฌํด ์ต์์ ๋๋ ํ ๋ฆฌ์ ๋์ ์ ์๊ฒ ์ค์ ํ๋ค.
- ์ดํ
docker build -f Dockerfile -t diarist:0.0.1 .
๋ฅผ ํตํด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ค. docker run -p 8080:8080 diarist:0.0.1
๋ก ์ ์ ์๋ํ๋์ง ํ์ธํ๋ค.
Swagger
SpringDocs๋ฅผ ํตํด API๋ฌธ์ํ๋ฅผ ๋ฐ๋ก ํ์ง ์์๋ ํ ์ ์๋ค!
Swagger์ ๋ฒ์ ์ 3.x.x๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค. 3.0.0 ๋ฒ์ ๋ถํฐ API Test๋ฅผ ์ํด ์ ์ํด์ผ ํ๋ url ์ด ๋ฐ๋์๋ค๊ณ ํ๋ค.
Swagger
SpringBoot ์์ swagger ์ฐ๊ธฐ
- ์์กด์ฑ ์ถ๊ฐ
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
SwaggerConfig
ํด๋์ค ์์ฑ@Configuration public class SwaggerConfig { @Bean public OpenAPI openAPI() { String jwt = "JWT"; SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt); Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme() .name(jwt) .type(SecurityScheme.Type.HTTP) .scheme("bearer") .bearerFormat("JWT") ); return new OpenAPI() .components(new Components()) .info(apiInfo()) .addSecurityItem(securityRequirement) .components(components); } private Info apiInfo() { return new Info() .title("API Test") // API์ ์ ๋ชฉ .description("Let's practice Swagger UI") // API์ ๋ํ ์ค๋ช .version("1.0.0"); // API์ ๋ฒ์ } }
@Configuration public class SwaggerConfig { @Bean public OpenAPI openAPI() { return new OpenAPI() .components(new Components()) .info(apiInfo()); } private Info apiInfo() { return new Info() .title("API Test") // API์ ์ ๋ชฉ .description("Let's practice Swagger UI") // API์ ๋ํ ์ค๋ช .version("1.0.0"); // API์ ๋ฒ์ } }
application.yml ํ์ผ ์ค์
springdoc:
swagger-ui:
path: /api-test # swagger-ui ์ ๊ทผ ๊ฒฝ๋ก์ ๋ํ ๋ณ์นญ, ํด๋น ์ฃผ์๋ก ์ ์ํด๋ http://localhost:8080/swagger-ui/index.html๋ก ๋ฆฌ๋ค์ด๋ ์
๋จ.
groups-order: DESC # path, query, body, response ์์ผ๋ก ์ถ๋ ฅ
tags-sorter: alpha # ํ๊ทธ๋ฅผ ์ํ๋ฒณ ์์ผ๋ก ์ ๋ ฌ
operations-sorter: method # delete - get - patch - post - put ์์ผ๋ก ์ ๋ ฌ, alpha๋ฅผ ์ฌ์ฉํ๋ฉด ์ํ๋ฒณ ์์ผ๋ก ์ ๋ ฌ ๊ฐ๋ฅ
paths-to-match:
- /api/** # swagger-ui์ ํ์ํ api์ ์๋ํฌ์ธํธ ํจํด
- @anotation ์ค์ ํ๊ธฐ
@Operation(summary = "์
์ฒด ํ์๊ฐ์
", description = "์
์ฒด ์ธก์์ ํ์๊ฐ์
ํ ๋ ์ฌ์ฉํ๋ API")
public BaseResponse<CompanySignupRes> signUp(@RequestBody CompanySignupReq request) {
// @Operation์ผ๋ก api์ ๋ํ ์ค๋ช
๊ณผ ์์ฝ์ ์์ฑํ ์ ์๋ค.
@ApiResponses(value = {
@ApiResponse(responseCode = "1000", description = "์์ฒญ์ ์ฑ๊ณตํ์์ต๋๋ค.", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "2002", description = "์ด๋ฏธ ๊ฐ์
๋ ๊ณ์ ์
๋๋ค.", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "4000", description = "๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์คํจํ์์ต๋๋ค.", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "4011", description = "๋น๋ฐ๋ฒํธ ์ํธํ์ ์คํจํ์์ต๋๋ค.", content = @Content(mediaType = "application/json"))
})
//@ApiResponses ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ, ์๋ต ์ฝ๋์ ๋ํ ์ ๋ณด๋ฅผ ๋ํ๋ผ ์๋ ์๋ค.
@Parameters({
@Parameter(name = "email", description = "์ด๋ฉ์ผ", example = "chrome123@naver.com"),
@Parameter(name = "password", description = "6์~12์ ์ด๋ด", example = "abcd1234"),
@Parameter(name = "companyName", description = "์
์ฒด๋ช
", example = "์ฝ๋ฆฌ์ ์์คํ
"),
@Parameter(name = "companyNumber", description = "์
์ฒด ๋ฒํธ", example = "112233"),
@Parameter(name = "companyAddress", description = "์
์ฒด ์ฃผ์", example = "์ธ์ฒ์ ๋ฏธ์ถํ๊ตฌ ์ฉํ๋")
})
//@Parameters ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ, ํ๋ผ๋ฏธํฐ์ ๋ํ ์ ๋ณด๋ฅผ ๋ํ๋ผ ์ ์๋ค.
CORS ์ค์ ํ๊ธฐ
- corsConfig ๋ฅผ ํด์ฃผ์ด์ผ ํ๋ค.
- Spring์ webMvcConfigurer ๋ฅผ ํตํด cors ์ค์ ์ ํด์ค ์ ์๋ค.
package com.hanium.diarist.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173", // ๋ฆฌ์กํธ ์น ์ ํ๋ฆฌ์ผ์ด์
"http://10.0.2.2:8081", // ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ (์๋๋ก์ด๋)
"http://localhost:8081", // ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ (iOS)
// "http://<YOUR_DEVICE_IP>:8081", // ์ค์ ๋๋ฐ์ด์ค์ IP ์ฃผ์์ ํฌํธ
"http://localhost:8000", // ์ฅ๊ณ ์๋ฒ
"http://localhost:8080/swagger-ui/index.html"
// "http://<YOUR_DJANGO_SERVER_IP>:8000" // ์ฅ๊ณ ์๋ฒ IP ์ฃผ์
)
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}
CreatedAt, updatedAt - JPA๋ก ์ฐ๊ธฐ
- createdAt ํ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ BaseEntity ์ updatedAt ์ ๊ฐ์ง๊ณ ์๋ BaseEntity๋ฅผ ์์๋ฐ์ BaseEntityWithUpdate ํด๋์ค๋ฅผ ์์ฑํ์๋ค.
- ์ดํ ์คํ๋ง๋ถํธ๊ฐ ์คํ๋ ๋ JPA๋ฅผ ํตํด ํด๋น ํ๋๋ฅผ ์์๋ฐ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ฑฐ๋ ํ ๋ ํด๋น ๋ก์ง์ด ์คํ์ด ๋์ด์ผ ํ๋ค
@EnableJpaAuditing
์ฝ๋๊ฐ application ํ์ผ์ ํ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ ํด๋์ค๋
package com.hanium.diarist.common.entity;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
}
EntityListners
๋ฅผ ํตํด CreatedDate๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
'๐ฅํ๋ก์ ํธ๐ฅ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Trouble Shooting - ๊ตฌ๊ธ ๋ก๊ทธ์ธ, Swagger ๐ซ (1) | 2024.08.05 |
---|---|
~ 7/29 ํ์ด์ ํ๋ก์ ํธ ๊ณต๋ชจ์ sprint 2๐ฅ (1) | 2024.08.05 |
~ 6/17 ํ์ด์ ํ๋ก์ ํธ ๊ณต๋ชจ์ sprint 1๐ฅ (0) | 2024.06.17 |