블로그

대협

[인프런 워밍업 클럽 2기 - BE] 3주차 발자국

[인프런 워밍업 클럽 2기 - BE] 3주차 발자국이 블로그는 정보근님의 입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기 강의 기반으로 코드작성과 코드설명을 적었습니다1. controller test 코드 분석애너테이션 조사@AutoConfigureMockMvcMockMvc를 자동으로 설정해 주는 애너테이션. 이 애너테이션을 통해 HTTP 요청을 수행하고 응답을 확인할 수 있다.MockMvc 란 ?실제로 서버를 띄우지 않고 컨트롤러를 테스트할 수 있는 도구@DisplayName("Test")테스트 클래스를 시작할 때 테스트 클래스의 이름을 지정해서 테스트 리포트에 표시된다.위 코드를 실행시키면 리포트에 TEST 라는 이름으로 테스트 성공유무가 표시됨.@Configuration : Spring에서 Bean을 수동으로 등록하기 위해서 사용메서드 분석 @Test @DisplayName("Introductions 조회") fun testGetIntroductions() { val uri = "/api/v1/introductions" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() }api/vi/introduction을 uri 변수에 넣음.HTTP GET 요청을 보낸후, 응답을 문자열로 변환한 후에 JSONArray로 변환JSONArray의 길이가 0보다 큰지 검증, 응답 데이터가 비어 있지 않음을 확인 @Test @DisplayName("Link 조회") fun testGetLinks() { val uri = "/api/v1/links" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() } api/vi/links을 uri 변수에 넣음HTTP GET 요청을 보낸후, 응답을 JSONArray로 변환배열의 크기와, 그 데이터가 존재하는지 검증@Test @DisplayName("Resume 조회") fun testGetResume() { val uri = "/api/v1/resume" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonObject = JSONObject(contentAsString) assertThat(jsonObject.optJSONArray("experiences").length()).isPositive() assertThat(jsonObject.optJSONArray("achievements").length()).isPositive() assertThat(jsonObject.optJSONArray("skills").length()).isPositive() } /api/vi/resume를 uri변수에 넣음GET요청을 보낸후, 응답을 JSONObject로 변환experiences, achievements,skills를 JSONArray로 변환 후 그 값이 양수인지와 데이터가 존재하는지 검증@Test @DisplayName("Projects 조회") fun testProjects() { val uri = "/api/v1/projects" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() } /api/vi/projects를 uri 변수에 넣음GET요청을 보낸후 응답 본문을 JSONArray로 변환하고, 배열의 길이가 양수인지와 데이터가 존재하는지 검증private fun performGet(uri: String): MvcResult { return mockMvc .perform(MockMvcRequestBuilders.get(uri)) .andDo(MockMvcResultHandlers.print()) .andReturn() } perform(MockMvcRequestBuilders.get(uri)) : 특정 uri에 GET 요청을 보내는 코드. 서버를 띄우지 않고 API 엔드포인트의 동작을 확인할 수 있음andDo(MockMvcResultHandlers.print()) : 요청과 응답을 콘솔에 출력andReturn() : MvcResult를 반환2. 부분 코드 분석<html *lang*="ko" *xmlns:th*="<http://www.thymeleaf.org>" *th:replace*="~{presentation/layouts/layout-main :: layout(~{::#content})}">Thymeleaf 템플릿 엔진에서 레이아웃을 정의하고 해당 레이아웃을 재사용하는 방식, 템플릿 코드의 중복을 줄이고, HTML 파일 간에 공통 요소를 재사용할 수 있게 하는 것. th:replace="~{presentation/layouts/layout-main :: layout(~{::#content})}"th:replace : 다른 파일을 가져와 현재 위치에 삽입하는 기능 수행~{presentation/layouts/layout-main :: layout(~{::#content})} :~{presentation/layouts/layout-main} : layout-main.html 파일 참조:: layout : layout 이라는 이름의 fragment를 사용하겠다는 의미, 위 코드에서는 layout fragment를 가져오겠다는 뜻(~{::#content}) : id="content" 로 지정된 부분을 layout fragment의 특정 위치에 대체할 것이라는 의미3. interceptor 코드 분석@Component class PresentationInterceptor( private val httpInterfaceRepository: HttpInterfaceRepository ) : HandlerInterceptor { override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) { val httpInterface = HttpInterface(request) httpInterfaceRepository.save(httpInterface) } }private val httpInterfaceRepository: HttpInterfaceRepository의존성 주입을 통해서 Repository를 사용할 수 있다.override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) {afterCompletion : HTTP 요청 처리 후에 호출되는 메서드val httpInterface = HttpInterface(request)httpInterfaceRepository.save(httpInterface)request 정보를 담고 있는 httpInterface 객체를 생성 후, httpInterfaceRepository에 저장. @Configuration class PresentationInterceptorConfiguration( private val presentationInterceptor: PresentationInterceptor ) : WebMvcConfigurer { override fun addInterceptors(registry: InterceptorRegistry) { registry.addInterceptor(presentationInterceptor) .addPathPatterns("/**") .excludePathPatterns("/assets/**", "/css/**", "/js/**", "/admin/**", "h2**", "/favicon.ico", "/error") } }addInterceptors인터셉터를 등록하는 메서드registry.addInterceptor(presentationInterceptor)addInterceptor 메서드를 통해 presentationInterceptor를 등록addPathPatterns("/**")모든 요청 경로에 대해 인터셉터 적용excludePathPatterns(...) : 인터셉터가 동작하지 않도록 설정/assets/**: 정적 자원(예: 이미지, 폰트 등)./css/**: CSS 파일./js/**: JavaScript 파일./admin/**: 관리 페이지.h2**: H2 데이터베이스 콘솔./favicon.ico: 사이트 아이콘./error: 오류 처리 경로.[미션4] 조회 REST API 만들기-회고이번 미션을 하면서 @GetMapping 어노테이션에 대해서는 어느정도 이해를 할 수 있었다. 저번 발자국에서 @Id, @GeneratedValue 어노테이션에 대해서 적었지만 아직 부족하다는 걸 알 수 있었고, @ManyToOne 어노테이션에 대해 더 깊이 공부해야겠다는걸 깨달았다. 아직 Spring에 본질적인걸 이해를 못한걸수도 있는거 같다. 코드를 작성하면 할수록 더 깊게 공부를 해야했고, JAVA 문법도 다시 해야겠다는걸 뼈저리게 느끼면서 한것 같다...3주차 회고Spring은 하면 할수록 재밌는건 맞다. Test 코드를 작성할 때도 이래서 이코드가 작동이 되는것도 알 수 있고, 부분적인 걸 따로 모듈화? 해서 만드는것도 재밌다. 이번 워밍업 클럽도 곧 종료가 되는데 java의 중요성도 깨달아서 java공부도 열심히 하고, Spring에 대해서 더 깊게 공부할거다!참고로 중간점검 때 정보근님께서 내가 작성한 질문에 대해 답변을 해주신거 같다. 나의 질문은 이번 워밍업 클럽이 종료가 되면 java의 정석, spring공부를 할건데 추천해줄 강의가 있냐 라는 질문이었다. 답변은 역시 김영한님의 강의였고 다른 강의도 추천해주셨는데 이거는 확인해보고 글을 수정해야겠다...! 무튼, spring을 선택한건 잘한 일 같다...!

백엔드워밍업클럽javakotlinspringTest코드미션4회고록코드설명백엔드

miiro

[인프런 워밍업 스터디 클럽 1기] BE 2주차 회고록

두 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 두 번째 회고록입니다.학습 내용static이 아닌 코드를 사용하려면 인스턴스화를 해야합니다.하지만, 학습에서 진행했던 UserController는 jdbcTemplate를 의존하여 사용하고 있습니다.이를 가능케 하는 것은 @RestController 어노테이션으로 의해 의존이 가능해지고 해당 클래스를 스프링 빈으로 등록시킵니다. 스프링 빈서버가 시작되면, 스프링 서버 내부에 거대한 컨테이너를 만듭니다.해당 컨테이너 안에는 클래스가 들어가게 되고, 다양한 정보(이름, 타입) 도 함께 들어가고, 인스턴스화도 이루어집니다.서버가 시작되면 코드의 구현 순서에 대해 살펴보겠습니다.스프링 컨테이너(즉, 클래스 저장소)가 시작됩니다.기본적으로 생성되어있는 스프링 빈들이 등록됩니다.사용자가 설정한 스프링 빈이 등록됩니다.필요한 의존성이 자동으로 설정이 됩니다. 여기서 스프링 컨테이너를 사용하는 이유를 살펴보면 2가지의 스프링 프레임워크의 특성 때문입니다.첫 번째는 제어의 역전(IOC) 이다. 말 그대로 메서드나 객체의 호출 작업을 개발자가 결정하는 것이 아닌, 외부(스프링 컨테이너)에서 결정되는 것을 의미입니다. 객체의 의존성을 역전시켜 객체간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 해서 가독성 및 코드 중복, 유지 보수를 편하게 할 수 있도록 도와줍니다.두 번째는 의존성 주입(DI) 로 객체를 직접 생성하는 것이 아닌 외부에서 생성할 후 주입시키는 방식을 의미한다.이를 통해 모듈 간의 결합도가 낮아지고 유연성을 높일 수 있습니다.  스프링 빈으로 등록하는 방법여기서 중점적으로 사용하는 어노테이션에 대해 살펴보겠습니다. @Configuration클래스에 붙이는 어노테이션@Bean을 사용할 때 함께 사용외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때 사용한다.@Bean메서드에 붙이는 어노테이션메서드에서 반환되는 객체를 스프링 빈에 등록한다.외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때 사용한다.@Service, @Repository개발자가 직접 만든 클래스를 스프링 빈으로 등록할 때 사용한다.@Component주어진 클래스를 컴포넌트로 간주한다.해당 클래스들은 스프링 서버가 뜰 때 자동으로 감지된다. @Component 사용컨트롤러, 서비스, 레포지토리 X개발자가 직접 작성한 클래스를 스프링 빈으로 등록 시에 사용되기도 한다. 스프링 빈 주입 방법생성자를 활용하여 주입하는 방법setter와 @Autowired를 사용하는 방법필드에 직접 @Autowired를 사용하는 방법 JPA(Java Persistence API)데이터를 영구적으로 보관하기 위해 Java 진영에서 정해진 규칙영속성 : 서버가 재시작되어도 데이터는 영구적으로 저장되는 속성 ORM(Object-Relational Mapping)객체와 관계형 DB의 테이블을 짝짓는 방법HibernateJPA를 구현(implement)해서 코드로 작성한 구현체내부적으로 JDBC를 사용한다   JPA 어노테이션@Entity : 스프링이 객체와 테이블을 같은 것으로 바라본다.Entity 뜻 : 저장되고, 관리되어야 하는 데이터@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;@Id : 위 필드를 primary key로 간주@GeneratedValue : primary key는 자동 생성되는 값GenerationType.IDENTITY : MySQL의 auto_increment 전략과 매칭JPA를 사용하기 위해서는 기본생성자가 꼭 필요하다 @Column(nullable = false, length = 20, name = "name") private String name;@Column : 객체의 필드와 Table의 필드를 매칭한다.null 여부, 길이 제한, DB Column 이름 등을 사용@Column 어노테이션을 생략할 수도 있다.  트랜잭션(Transaction)쪼갤 수 없는 업무의 최소 단위 모든 SQL 한번에 성공 or 하나라도 실패하면 모두 실패 트랜잭션 명령어start transaction; : 트랜잭션 시작하기commit; : 트랜잭션 정상 종료(SQL 반영)rollback; : 트랜잭션 실패 처리(SQL 미반영)   트랜잭션 적용 방법@Transactional public void saveUser(UserCreateRequest request) { userRepository.save(new User(request.getName(), request.getAge())); }SELECT 쿼리만 사용한다면 readOnly 옵션 사용 가능@Transactional(readOnly = true) public List<UserResponse> getUsers() { return userRepository.findAll().stream() .map(UserResponse::new) .collect(Collectors.toList()); } ❗ 주의사항IOException 과 같은 Checked Exception은 롤백이 일어나지 않는다. 영속성 컨텍스트테이블과 매핑된 Entity 객체를 관리/보관하는 역할스프링에서는 트랜잭션을 사용하면 영속성 컨텍스트가 생겨나고, 트랜잭션이 종료되면 영속성 컨텍스트가 종료특징변경 감지(Dirty Check)영속성 컨텍스트 안에 불러와진 Entity는 명시적으로 save 하지 않더라도, 변경을 감지해 자동으로 저장된다.@Transactional public void updateUser(UserUpdateRequest request) { User user = userRepository.findById(request.getId()) .orElseThrow(IllegalArgumentException::new); user.updateName(user.getName()); }쓰기 지연DB의 insert/update/delete SQL문을 바로 날리는 것이 아닌, 트랜잭션이 commit될때 모아서 1번만 날린다.1차 캐싱ID를 기준으로 Entity를 기억한다.캐싱된 객체는 완전히 동일하다.(객체 주소도 같다) JPA 연관관계ex) 사람(person)과 실거주 주소(address)사람 1명은 1개의 실거주 주소만을 가지고 있다.@OneToOne연관관계의 주인을 설정한다.(mappedBy 사용한다.)연관관계의 주인 효과상대 테이블을 참조하고 있으면 연관관계의 주인이다.연관관계 주인이 아니면 mappedBy 사용연관관계의 주인의 setter가 사용되어야만 테이블이 연결@Transactional public void savePerson() { Person person = personRepotiory.save(new Person()); Address address = addressRepotiory.save(new Address()); person.setAddress(address); } 연관 관계의 주의점트랜잭션이 끝나지 않았기에, 한 쪽만 연결해두면 반대쪽의 값은 알 수 없다. @Transactional public void savePerson() { Person person = personRepotiory.save(new Person()); Address address = addressRepotiory.save(new Address ()); person.setAddress(address); System.out.println(address.getPerson); //null 반환 }이를 방지하기 위해 setter 한 번에 둘을 같이 이어준다.public void setAddress(Address address) { this.address = address; this.address.setPerson(this); } 다대일,일대다관계@ManyToOne을 단방향으로 사용할 수 있다.@JoinColumn연관관계의 주인이 활용할 수 있는 어노테이션필드의 이름이나, null 여부, 유일성 여부, 업데이트 여부 등을 지정할 수 있다.다대다관계(N : M 관계)@ManyToMany구조가 복잡하고, 테이블이 직관적으로 매핑되지 않기 때문에 사용하지 않는 것을 지양한다.cascade 옵션한 객체가 저장되거나 삭제될 때, 그 변경이 폭포처럼 흘러서 연결되어 있는 객체도 함께 저장되거나 삭제되는 기능orphanRemoval 옵션객체간의 관계가 끊어진 데이터를 자동으로 제거하는 옵션 @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<UserLoanHistory> userLoanHistories = new ArrayList<>();지연 로딩(Lazy Loading)연결되어 있는 객체를 꼭 필요한 순간에 데이터를 로딩한다. @OneToMany의 fetch() 옵션 연관관계의 장점각자의 역할에 집중하게 된다.새로운 개발자가 코드를 읽을 때 이해하기 쉬워진다.테스트 코드 작성이 쉬워진다.연관관계 사용 시 주의 사항지나치게 사용하면 성능 상의 문제가 발생할 수 있다.도메인 간의 복잡한 연결로 인해 시스템을 파악하기 어려워질 수 있다.요구 사항 등 여러 부분을 고민해서 연관 관계 사용을 선택해야한다. 과제 내용Day 4Day2에서 진행했던 GET API와 POST API를 구현했었는데, 그 당시에는 database를 사용하지 않은 방법으로 과제에서 주어진 조건에 맞게 답을 출력했었습니다. 이번 과제에서는 DB를 활용하여 정보를 저장하고, 수정할 수 있는 로직을 구현해야했습니다.Layer를 분리해서 진행을 할 수 있지만, 간단하게 문제의 답만 도출하기 위해서 Controller Class에 구현을 진행했었습니다.그렇기 때문에 Spring Data JPA가 아닌 JDBCTemplate를 활용하여 진행했습니다. JPA를 통한 DB 로직을 구현하는 것만 주구장창 했어서, 직접 쿼리문을 작성해서 진행하는 JDBCTemplate를 사용하는 방법에 대해 알 수 있었던 거 같습니다.📋 4일차 미션 : GET API와 POST API 구현 Day 5클린 코드는 코드를 아름답게 만드는 것이 아닌 코드의 질을 향상 시키는 데 중요하다는 것을 알았습니다.클린 코드를 구현하기 위해서 명확하고 간결하게 코드를 구현하여 버그를 줄이고, 그로 인한 개발 속도를 향상시킬 수 있습니다.또한, 잘 작성된 코드는 시간이 흘러도 이해하기 쉽기에, 유지 보수가 간편합니다. 이로 인해 개발자로서 팀 프로젝트를 진행할 시에팀 커뮤니케이션을 원활하게 진행할 수 있도록 도움을 줄 수 있다는 것을 알게 되었습니다.📋 5일차 미션 : 클린 코드 구현  회고스프링 프레임워크의 핵심 개념인 제어의 역전(IOC)과 의존성 주입(DI)을 통해 더 나은 코드 작성과 유지 보수의 용이섬에 대해 알게 되었습니다. 또한 어노테이션들을 활용하여 클래스를 스프링 빈으로 등록하고, 스프링 컨테이너가 이를 관리함으로써, 필요한 의존성을 자동으로 설정할 수 있다는 사실을 배웠습니다. JPA를 통한 데이터의 영속성 관리와 ORM을 통한 객체와 DB의 매핑에 대해 이론적으로 정립할 수 있는 계기되었던 거 같습니다.서비스를 구성하는 데 가장 중요한 @Transactional 어노테이션을 사용하여 데이터의 일관성을 유지하는 방법을 쉽게 공부하면서 더티 체크, 쓰기 지연 등 특성에 대해 알 수 있었던 거 같습니다.객체와 DB를 효과적으로 설계할 수 있도록 연관관계를 설계하는 방법을 배움으로써 사용할 때의 주의사항과 성능 문제를 방지하기 위한 전략에 대해 알게 되면서 이를 통해 효과적이고 용이한 애플리케이션 개발을 할 수 있는 토대를 마련할 수 있었던 거 같습니다.  

백엔드인프런워밍업스터디클럽2주차회고록

miiro

[인프런 워밍업 스터디 클럽 1기] BE 4주차 회고록

네 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 네 번째 회고록입니다.학습 내용build.gradle빌드 스크립트라고 불린다.gradle을 이용하여 프로젝트를 빌드하고 의존성을 관리하기 위해 작성되었다.현재는 groovy 언어를 사용해 작성되어있고, kotlin 언어를 사용할 수도 있다. 플러그인plugins { id 'java' id 'org.springframework.boot' version '3.1.11' id 'io.spring.dependency-management' version '1.1.4' } org.springframework.boot 플러그인스프링을 빌드했을 때 실행 가능한 jar 파일이 나오게 도와준다.스프링 애플리케이션의 실행을 도와준다.이 외의 플러그인들이 적용될 수 있도록 해준다.io.spring.dependency-management 플러그인외부 라이브러리, 프레임워크의 버전 관리의존성 처리하는 데 사용java 플러그인java 프로젝트 개발 시 필요한 기능 추가JVM 언어 Gradle 플러그인의 사용할 수 있는 기반 마련 그룹group = 'sample' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' }group프로젝트 그룹빌드 결과물에 프로젝트 그룹에 대한 정보가 들어있다.version프로젝트 버전sourceCompatibility프로젝트가 사용하고 있는 JDK 버전 레포지토리repositories { mavenCentral() }외부 라이브러리/ 프레임워크를 가져오는 장소 설정 의존성(dependencies)dependencies { // Spring boot implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' // test testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' // lombok compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' //mysql runtimeOnly 'com.mysql:mysql-connector-j' }사용하는 라이브러리/프레임워크 표시implementation : 해당 의존성을 항시 사용한다.runtimeOnly : 코드를 실행할때에만 의존성을 사용한다.testImplementation : 테스트코드를 컴파일하거나 실행할 때 항시 사용한다.Spring과 SpringBoot의 차이점간편한 설정스프링은 강력한 기능을 제공한다.ex) IoC/DI, AOP, PSA ..기능을 사용하기 위해 xml 설정을 해야했는데 양이 많았다. -> 어노테이션 기반의 설정으로 변경하고 기본적으로 필요한 것들은 모두 자동 설정간단한 의존성 관리Spring을 사용할 때는 개발에 필요한 라이브러리/프레임워크를 모두 기입해야했다.의존성 관리가 힘들기에 starter로 묶어서 관리강력한 확장성Springboot 내부에 tomcat이 있기에 따로 설정할 필요가 없다.MSA에 적합한 모니터링application.yml 파일YAML 문법Yet Another Markup Language(또 다른 마크업 언어)YMAL Ain't Markup Language(마크업 언어가 아니다)확장자 : .yaml 또는 .ymlkey : value 형식으로 데이터를 정의한다.각 계층은 들여쓰기를 통해 구분하게 되며, 이를 통해 중복을 제거할 수 있다.value에는 참/거짓, 숫자, 문자열이 들어갈 수 있다.value에는 배열도 들어갈 수 있다. - 를 활용한다.#을 이용하면 주석을 사용할 수 있다.application.propertiesdev profile 사용application-dev.properties 파일 생성Lombokgetter/setter, 생성자와 같은 반복되는 보일러 플레이트 코드(boiler plate code)를 제거할 수 있다.dependencies 추가compileOnly 'org.projectlombok:lombok'annotationProcessor 추가annotationProcessor 'org.projectlombok:lombok'Spring Boot 2.7.x -> 3.0.x 변경점java 최소 버전이 17로 업그레이드스프링 프로젝트, third-party library 버전 업그레이드AOT 기초 작업AOT(Ahead Of Time) : 빌드 시 스프링 애플리케이션을 분석하고 최적화하는 도구애플리케이션 시작 시간과 메모리 사용량을 줄일 수 있게 해준다.javax -> jakarta 패키지로 변경모니터링 기능 강화 과제 내용이번 프로젝트에서는 출퇴근 사내 시스템으로써, 회사 내 팀과 직원 관리, 출퇴근 관리, 그리고 연차 관리 기능을 설계하였습니다. 기본적인 기술 스택으로는 Java 17 / Springboot 3.x.x으로 구성하여 팀 관리에서는 팀 이름을 필수로 등록하고 팀 정보를 조회할 수 있는 기능을 구현했습니다. 직원 관리에서는 직원의 이름, 매니저 여부, 입사 날짜, 생일을 등록하고, 직원 정보를 조회할 수 있게 했습니다. 출퇴근 관리에서는 직원의 출근 및 퇴근 기능을 구현하였으며, 직원의 근무 시간을 날짜별로 조회할 수 있도록 하였습니다. 연차 관리에서는 직원이 연차를 신청하고, 남아있는 연차를 조회할 수 있는 기능을 제공했습니다. 특히, 연차 신청 시 팀마다 다른 등록 기간을 적용하여 유연성을 높였습니다. 📋 미니 프로젝트 Github : commuting-system회고이번 프로젝트를 통해 팀, 직원, 출퇴근, 연차 관리를 통합적으로 설계하는 경험을 쌓았습니다. 팀 관리에서는 팀의 필수 정보를 명확히 정의하고, 팀 조회 기능을 통해 팀 운영의 투명성을 높였습니다. 직원 관리에서는 직원의 기본 정보를 체계적으로 관리할 수 있게 되었고, 매니저 여부와 같은 역할 분류를 통해 조직의 구조를 명확히 파악할 수 있었습니다. 출퇴근 관리에서는 출퇴근 예외 처리와 날짜별 근무 시간 조회 기능을 통해 직원들의 근태를 정확히 관리할 수 있었습니다. 연차 관리에서는 연차 신청과 조회 기능을 통해 직원들이 연차를 효율적으로 사용할 수 있도록 했습니다. 팀마다 다른 연차 등록 기간을 적용함으로써 조직의 유연성을 높였습니다. 이 프로젝트를 통해 데이터의 일관성을 유지하면서도 다양한 요구 사항을 충족시키는 설계의 중요성을 깨달았습니다. 또한, 시스템 통합의 복잡성을 이해하고, 사용자 편의성을 고려한 기능 설계의 필요성을 다시 한 번 느꼈습니다.

백엔드인프런워밍업스터디클럽4주차회고록

miiro

[인프런 워밍업 스터디 클럽 1기] BE 3주차 회고록

세 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 세 번째 회고록입니다. 학습 내용배포란?최종 사용자에게 SW를 전달하는 과정이다. = 전용 컴퓨터에 우리의 서버를 옮겨 실행시키는 것서버용 컴퓨터는 보통 리눅스를 사용한다.profile과 H2 DBprofile : 똑같은 서버 코드를 실행시키지만, 실행될 때 설정을 다르게 하고 싶다.(ex. Database)[예시]local profile -> H2 DBdev profile -> MySQL DB  H2 DB경량 database로, 개발 단계에서 많이 사용하며 디스크가 아닌 메모리에 데이터를 저장할 수 있다.메모리에 데이터를 저장하면 휘발되는 특징으로 인해 개발 단계에서만 사용한다개발단계에서는 테이블이 계속 변경되는데, 데이터가 휘발되기에 ddl-auto 옵션을 create로 주면 테이블이 자동 생성/삭제가 되기에 주로 사용된다.git/githubgit코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램githubgit으로 관리되는 프로젝트의 코드가 저장되는 저장소사용하는 이유?코드는 어떠한 이유로든 소실이 될 가능성이 있다.배포를 할 때 활용할 수 있다.git 명령어git init해당 프로젝트를 git이 관리하겠다는 의미git 프로젝트의 github 저장소 설정git remote add origin [git 주소]코드를 git에 모든 파일을 넣는다git add .Git 커밋 명령어git commit -m '메시지'Git 푸시 명령어git push코드 github에 최초로 보내기git push --set-upstream origin masterGit 상태 확인git status.gitignore파일 안에 적힌 폴더 및 파일의 이름은 깃으로 관리하지 않는다. EC2에 접속해서 리눅스 명령어 다뤄보기 EC2 접속 방법다운로드 받은 키 페어(pem key)를 이용하는 방법접속하려는 EC2의 IP 주소다운로드 받은 키 페어 접속하기 위한 프로그램(git CLI or Mac Terminal) chmod 400 키페어이름.pemssh -i 경로/키페어이름.pem ec2-user@IPAWS 콘솔을 활용해서 접속하는 방법 기본적인 리눅스 명령어mkdir : 폴더를 만드는 명령어ex) mkdir folder1ls : 현재 위치에서 폴더나 파일을 확인하는 명령어ls -l : 조금 더 자세한 정보를 확인할 수 있다. drwxrwxr-x : folder1은 폴더이다.drwxrwxr-xr : 읽는 권한, w : 쓸 수 있는 권한, x : 실행 권한rwx/rwx/r-x폴더 소유자 권한 / 폴더 소유 그룹 권한/ 모든 접근의 권한2 : 폴더에 걸려 있는 바로가기 개수ec2-user : 폴더 소유주의 이름ec2-user : 폴더 소유 그룹의 이름6 : 폴더(파일의 크기) 단위 : byte cd(change directory) : 폴더 안으로 들어가는 명령어ex) cd folder2pwd(print working directory) : 현재 위치 확인하는 명령어/home/ec2-user/folder1cd .. : 상위 폴더로 올라가는 명령어rmdir : 특정 폴더(디렉토리) 제거하는 명령어 배포를 위한 프로그램 설치하기 코드를 가져오기 위한 Gitsudo yum install git : yum을 이용한 프로그램 다운로드 진행한다.서버를 구동할 Javasudo yum install java-11-amazon-corretto -yjava -version : 자바 버전 확인데이터베이스 MySQLsudo dnf install https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpmsudo dnf install mysql-community-serversudo systemctl status mysqldsudo systemctl restart mysqldsudo cat /var/log/mysqld.log | grep "A temporary password"mysql8의 임시 비밀번호를 확인하는 명령어alter user 'root'@'localhost' identified with mysql_native_password by 'Abdc1234!';비밀번호는 대/소문자, 특수문자 포함 8자 이상 리눅스에서 스프링 배포 프로그램 설치sudo yum updatesudo : 관리자 권한 실행yum : 리눅스 패키지 관리 프로그램(ex. gradle과 비슷한 역할)update : 현재 프로그램들을 최신화 설정한다. 빌드와 실행, 그리고 접속 git 코드 로딩 :git clone [github 저장소 주소]swap 설정기존에는 RAM을 사용해야하지만 RAM의 용량이 부족한 경우, 일부 Disk를 사용하게 해준다.#swap 메모리를 할당한다. (128M 16 = 2GB) sudo dd if=/dev/zero of=/swapfile bs=128M count=16 #스왑 파일에 대한 권한 업데이트 sudo chmod 600 /swapfile #swap 영역 설정 sudo mkswap /swapfile #swap 파일을 사용할 수 있도록 만든다. sudo swapon /swapfile #swap 성공 확인 sudo swapon -schmod +x ./gradlewgradlew를 사용하기 위해 실행할 수 있도록 설정한다../gradlew build -x testgradle을 이용해 프로젝트를 빌드한다. -> 테스트코드는 실행하지 않는다. java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev--spring.profiles.active=dev : 설정 파일등록 이후에 인스턴스 인바운드 규칙 설정을 해줘야한다.8080 포트 Open  jar 파일만 실행했는데 서버가 동작하는 이유?SpringBoot 에는 톰캣(Tomcat)이 내장되어 있기 때문이다.톰캣(Tomcat)웹 애플리케이션 서버(WAS)의 한 종류로써, 요청이 들어오면 그 요청을 약속된 형식에 맞추어 스프링에 전달해준다.실행 중인 서버 중단ctrl + c./gradlew clean현재 빌드되어 있는 결과물 제거 foreground vs background foreground우리가 보고 있는 프로그램ex) PDF 프로그램이 foreground 프로그램 background우리가 보고 있지 않은데 실행중인 프로그램ex) 컴퓨터에서의 백신 프로그램 리눅스에서 background로 동작하게 만드는 명령어nohup [명령어] &nohup java -jar build/libs/library-app-0.0.1-SNAPSHOT.jar &rm nohup.out  background 서버 다운작업관리자 명령어ps aux : 현재 실행중인 프로그램 목록을 확인할 수 있다.ps aux | grep java : java가 들어가는 프로그램을 확인한다.kill -9 프로그램번호 : 해당 프로그램을 종료시킨다.파일의 내용물을 확인하는 방법파일에 직접 들어가 내용물 확인vi : 리눅스 편집기인 vim을 사용하여 파일을 접속한다. (ex. vi nohup.out)파일에 들어가지 않고 현재 접속중인 터미널을 활용하는 방법cat : 파일에 있는 내용물을 모두 출력하는 명령어(ex. cat nohup.out)파일 내용물의 양이 많지 않고, 실시간 업데이트가 잘 되지 않는 파일을 확인할 때 사용한다.tail : 현재 파일의 끝 부분을 출력하는 명령어tail -f : 현재 파일의 끝부분을 실시간으로 출력해준다.  과제 내용Day 6Controller, Service, Repository의 3단 분리 구조를 채택하여 백엔드 설계를 진행했습니다.Repository 클래스에서는 jdbcTemplate를 활용해 SQL문을 직접 작성하고 데이터베이스와 직접적으로 연결하는 방식을 택했습니다. 이 과정에서 @Repository 어노테이션을 활용한 생성자를 통한 의존성 주입이 이루어지는 것을 확인할 수 있었습니다.특히, 다양한 저장소 구현체(FruitMySqlRepository, FruitMemoryRepository)를 만들면서, @Primary 어노테이션을 활용하여 서비스 로직이 실행될 때 어떤 레포지토리 레이어를 우선적으로 사용할지 결정하는 방식을 경험했습니다. 이러한 구조적 접근은 유연하고 확장 가능한 백엔드 시스템을 구축하는 데 큰 도움이 되었습니다.📋 6일차 미션: 레이어 3단 분리 Day 7JDBCTemplate을 사용해 시스템을 구축한 DB를 성능 개선과 유지보수의 편의성을 위해 JPA로 전환하였습니다.엔티티 클래스인 Fruit에서는 과일의 이름, 입고 날짜, 가격, 판매 여부를 관리했습니다. JPA의 강력함은 FruitRepository 인터페이스를 통해 드러났다. 여기서 단순 조회부터 복잡한 조건의 데이터 처리까지 어노테이션 몇 개로 해결할 수 있었습니다. FruitServiceV2에서는 과일의 저장, 판매 상태 업데이트, 통계 조회 등 핵심 비즈니스 로직을 구현하여, 코드의 간결함과 효율성을 극대화했습니다.특히, 과일의 개수를 세거나, 특정 가격 이상 또는 이하의 과일을 조회하는 기능을 추가하며, JPA의 유연성과 편리함에 다시 한번 감탄했습니다. 이 모든 과정을 통해, 나는 JPA의 놀라운 잠재력을 경험하며, 보다 나은 소프트웨어 개발자로 성장할 수 있는 계기를 마련한 것 같습니다.📋 7일차 미션: JPA 구현회고SW 배포는 최종 사용자에게 소프트웨어를 전달하는 과정으로, 리눅스 기반 서버 컴퓨터에서 주로 이루어집니다. 개발 단계에서는 경량화된 H2 DB를 활용하여 데이터의 휘발성을 감안한 개발 환경을 구축합니다. Git과 GitHub을 통한 버전 관리 및 코드 저장소 활용은 코드 소실 방지와 효율적인 배포 과정을 지원합니다. EC2와 리눅스 명령어를 통한 서버 접속 및 관리, 그리고 리눅스 환경에서의 스프링 배포는 필수적인 프로세스라는 것을 알게 되었습니다.또한, Controller, Service, Repository의 3단 분리 구조를 채택하여 백엔드 설계를 진행하고, JDBCTemplate에서 JPA로 전환하여 성능 개선과 유지보수의 편의성을 높였습니다. 이 모든 과정은 유연하고 확장 가능한 백엔드 시스템 구축과 개발자로서의 성장에 밑거름이 된 거 같습니다.

백엔드인프런워밍업스터디클럽3주차회고록

이삭토스트

[인프런 워밍업 클럽 스터디1기] BE 3주차 회고록

강의 수강10일차 - 객체지향과 JPA연관관계JPA를 사용하는 이유를 배우는 단계, 무려 연관관계와 지연로딩에 관한 내용이다.자바와 같이 JPA를 객체지향적으로 설계하기 위해 연관관계 매핑을 사용한다.처음에 N:1 과, 1:1, N:M,의 경우에 대해 배우게 된다. 더불어 참조 관계를 단방향, 양방향으로 보게되고 연관관계의 주인이라는 개념을 이해하기엔 복잡한 부분도 있었다.N:M은 문제가 N+1이라는 toString의 순환참조로 인해 재귀함수가 되는데 이 경우에는 N:M을 N:1, 1:1, 1:M으로 테이블 하나를 중간다리 처럼 생성하여 나누는 것이 좋은 것으로 알고 있다.그리고 트랜잭션을 사용하고 있을 때, 한 쪽만 연결 해두면 반대 쪽은 알 수 없기에 각각의 setter를 연결해주는 방법을 이용하여 서로 알 수 있게 해주는 방법에 대해서 알게 되었다.또한 Fetch 옵션이 최적화에 밀접한 영향이 있고, 항상 연관관계를 사용하는 것이 좋은 것만은 아니기에 장단점을 잘 따져보고 사용하는 것이 좋겠다!11일차 - 기본적인 배포를 위한 준비Github와 AWS를 이용하여 우리가 만든 라이브러리 앱을 직접 외부에서 사용해볼 수 있게 하는 단계이다.프로파일을 적용시켜둬서 우리가 개발단계와 배포단계에서 사용하는 설정들을 미리 해둘 수 있다.AWS은 우리가 흔하게 접하게될 사이트다 유료 사이트이지만, 프리티어 내에서는 1년동안 자유롭게 사용가능하고 특별하게 사고를 치지 않는 이상은 별도의 요금은 발생하지 않을 것이다.12일차 - AWS와 EC2 배포본격적으로 AWS와 EC2를 사용해보는 시간이다.EC2는 리눅스를 사용하는데 개발자 분들이 알아야하는 것 중 리눅스 명령어들을 직접 사용해보는 시간이었다. 근데 뭔가 사용하는 명령어들이 ls, cd, pwd, cd, rmdir... 맥에 있는 터미널과 비슷하다는 느낌을 받는다...? 이 부분은 나중에 리눅스 운영체제 사용해보면서 경험해봐야겠다.Github에 올려둔 코드들을 어떻게 EC2에 올리는지 궁금했었는데 git clone을 이용하여 저장소 주소에 있는 파일들을 받아오는 방법이었다. 리눅스 swap 하는 방법을 통해서 메모리가 부족할 때 디스크 자체에서 대신하는 방법들을 배웠다 우리에게는 메모리 스왑 방식이 좀 더 익숙하긴 한데 비슷한 방식인 것 같다.빌드를 하고 방화벽 설정을 하고 그리고 실행중인 서버를 중단하고, EC2 콘솔을 닫아도 백그라운드에서 작동하는 방법네이버나 구글처럼, 아이피를 치고 들어가는 것이 아닌 도메인을 이용하여 DNS을 적용하는 방법 13일차 - Spring Boot 설정, 버전업 이해하기우리가 사용하는 스프링과 스프링부트에 관하여 좀 더 알아보는 시간 스프링이 어떻게 현재까지 이어져왔고 스프링부트로 인해 스프링을 좀 더 쉽게 쓰게 되었다.추가로 Lombok의 사용법도 배우면서 보일로 플레이트 코드를 줄이고 좀 더 깔끔하게 쓰는 방법에 대해서 배우게 되었다.미션 - 미니프로젝트 1차 모든 것이 처음부터 시작하는 상황으로 돌아가는 상황이다.먼저 테이블과 객체 설계부터 들어갔다.롬복을 사용해서 좀 더 깔끔하게 코드를 만들 수 있었다. public class Team { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long teamId; private String teamName; @OneToMany(mappedBy = "team") private List<Member> members = new ArrayList<>();public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long memberId; private String memberName; private boolean isManager; private LocalDate hireDate; private LocalDate brithDay; @ManyToOne @JoinColumn(name = "team_id") private Team team; 팀 등록기능과 직원 등록기능은 꽤 간단한 편이지만팀 전체적으로 조회 기능과, 직원 전체 기능을 조회하는 것이 꽤 난이도가 있었다.서로 하나만 쓰는 것도 아니고 동시에 같이 쓰기에 이것을 어떻게 처리할 것인가가 관건이었고둘 다 Response를 리스트로 보내기 위해서 객체들을 가져와서 새로 객체들을 만들어 리스트로 묶어줬다.다행인건 과제에서도 비슷한 과제가 존재하였기에 그나마 만들 수 있었던 것 같았다.@Transactional public List<GetAllMembersResponse> getAllMembers() { List<Member> members = memberRepository.findAll(); return members.stream() .map(this::mapToGetAllMembersResponse) .collect(Collectors.toList()); } private GetAllMembersResponse mapToGetAllMembersResponse(Member member) { GetAllMembersResponse response = new GetAllMembersResponse(); response.setName(member.getMemberName()); response.setTeamName(member.getTeam().getTeamName()); response.setRole(member.isManager() ? "MANAGER" : "MEMBER"); response.setBirthDay(member.getBirthDay()); response.setWorkStartDate(member.getHireDate()); return response; }순식간에 많은 내용을 배우면서 이 내용을 어떻게 써야할지 갈피를 못 잡는 것 보다단계적으로 상위 과제를 주면서 미니프로젝트를 완성해가는 것이 뭔가 뿌듯하다.아직 4단계 까지 남아있으니까 2단계 3단계 점차 나아가면서 마지막 배포 단계까지 열심히 작성해봐야겠다!

백엔드백엔드워밍업스터디BE1기회고록

이삭토스트

[인프런 워밍업 클럽 스터디1기] BE 2주차 회고록

강의 수강6일차 - 스프링 컨테이너의 의미와 사용 방법우리가 설정해줘야 하는 부분들이 설정을 안 해줬는데도 작동하는 신기한 현상을 볼 수 있다.물론 정답은 스프링 부트에서 제공해주는 매우 편리한 기능(스프링 빈, 컨테이너)에 의한거지만 (개발자는 반복을 싫어한다.)또한 기기 자체에서 모듈방식을 채택하는 경우가 많은데 그것과 유사하게 스프링 내에서는Repository를 어떤 전략을 취할 것인지 선택하여 많은 변경이 없이 구조를 효과적으로 바꾸게 된다.스프링 컨테이너가 이 역할을 해주고 컨테이너가 서비스를 대신 인스턴스화하고, 그때마다 레포지토리를 결정해주는데 이 방식 자체를 IoC라고 한다.@Configuration과 @Component등 스프링에서 자주 쓰이는 어노테이션에 대해서 배우게 되는 시간이었던 것 같다.7일차 - Spring Data JPA를 사용한 데이터베이스 조작SQL에서 벗어나 드디어 JPA를 본격적으로 사용하게 되는 부분이다.JPA를 사용하기 위한 사전 설정과 Entity 클래스, 그리고 JPA를 사용할 때 가장 중요한 ddl_auto 이 부분이 실무에서는 매우 중요하다고 생각한다. (실무 데이터에서 validate빼고 사용한다면 데이터가, 변형 또는 날라가버리니까)가끔 일반적인 SQL 명령어에서 정밀하게 다루고자 할 때 JPA를 확장시켜둔 Repository에JPA 쿼리를 이용하여 다양한 쿼리를 작성해줄 수 있다. (조금 더 정밀하게 작동시키려면 JPQL이 답)8일차 - 트랜잭션과 영속성 컨텍스트트랜잭션의 개념에 대해 알아가는 구간, 영속성 컨텍스트 특징 (변경 감지, 쓰기 지연, 1차 캐싱, 지연로딩, 동일성 보장) 9일차 - 조금 더 복잡한 기능을 API로 구성하기User에서 벗어나 대출과 반납이라는 개념을 들어간다. 새로운 테이블을 만들고 두 테이블을 연결해서 사용하는 방법을 알게 되었다.그리고 마지막으로 JPA에서 연관관계 매핑에 관한 떡밥을 남기시며 다음 주 월요일을 기대하게 된다.미션6일차 과제 - 4일차 과제 API 분리, Controller - Service - Repository 계층에 익숙해지기 기존코드를 JPA를 이용하여리팩토링을 해나가는 과정이다.문제1 에서는 컨트롤러가 너무 많은 역할을 하고 있어 Controller(HTTP 관련 역할) - Service(분기 처리, 로직) - Repository(DB와 접근 담당)로 나누는 과정이며,문제2는 Repository를 인터페이스화 해서 메모리에 저장하는 부분과 MySql 저장하는 것을 선택하게끔 하는 것이었다.문제1은 기존 코드를 Controller에서 Service로 우선 나누고 그 다음에 Service에서 DB와 접근에 관련된 부분을 분리하여 Repository에 나누는등 3개로 분리하였다. 이 과정에서 JdbcTemplate를 Repository만 접근하므로 코드의 가독성을 늘리기 위해Repository를 제외하고는 JdbcTemplate 관련 설정을 지워줬다.문제2는 DIP에 관련된 내용으로 스프링에서 클래스에 의존하는 것이 아니라 인터페이스에 의존하게끔 만들어 의존성 역전 원칙을 만들게 하기 위함이다. (+ IoC)7일차 과제 - JPA 연습 문제1은 6일차 과제에서 만든 과제를 JdbcTemplate에서 Spring Data JPA를 사용하는 환경으로 바꿔주는 과정이다.JPA를 처음 접할 때 이걸 왜 사용하고 어떻게 사용해야하는지 몰랐다. 오히려 SQL 내용을 배우고나서 JPA로 천천히 넘어오니 사용방법과 필요성을 뼈저리게 느꼈다. 부트캠프에서는 처음 접하는 내용을 바로 활용하는 입장에 있어서 이해를 하지 못하고 급하게 넘어왔던 부분이었는데 지금 JPA를 다시 공부하면 깊게 배우면서 조금 더 내 실력을 늘릴 수 있을 것 같다. 자연스럽게 테이블에 대한 개념도 배우면서 어떤 곳에서 어떤 코드를 짜고 그 의문점에 대해서 해소 할 수 있는 과제 였다.문제2는 JPA를 적용해 놨다면 이제 새로운 기능을 JPA를 이용하여 만드는 것이다.조금 의아한거라면 JPA를 깊게 배워갈 수록 SQL의 필요성을 느끼게 되는 것 같다.문제3은 2가지 쿼리를 받아서 2가지 갈래로 분기를 만들어 값을 리턴하는 기능을 만드는 것이었다.처음에 dto 설계를 잘 못해서 객체를 객체로 감싸서 List 자체만이 나오는 것이 아니라 dto에서 설정한 이름이 한번 더 포장되어서 결과가 반환되었다. API에서 디버그를 사용하면 요청이 보내졌을 때 변해지는 과정을 알 수 있으면 좋겠다. 아니면 내가 알지 못하는 사용법이 있는 것 같다.8일차 과제 - 미니프로젝트 도입아직은 특별하게 작업물을 만들지는 않았다. 5월 23일까지 제출해야하는 것이므로 프로젝트 전체적으로 크게 보고나서 설계하고 만들어가는 것도 늦지 않다고 생각을 하고, 강의를 들어가면서 구축해나가야 할 것 같다.본격적인 내용은 3주차 회고에서 나오게 될 것 같다.기존 구조에서 새로운 것을 추가하고 JPA를 다양하게 사용해보고 이제 연관관계 매핑이나 백엔드를 살짝 벗어나는 내용도 나오게 될 것 같다. 특히 배포 부분에 관련된 내용 같은데 이 부분은 아는게 많이 없어서 접해보는 걸로 만족하는 계기가 되지 않을까?

백엔드워밍업스터디BE1기회고록

이삭토스트

[인프런 워밍업 클럽 스터디1기] BE 1주차 회고록

 강의 수강 1일차 - 서버 개발을 위한 기본 환경 설정 및 네트워크 기초 기본적인 내용을 배우는 시간, HTTP 네트워크 기초에 대해서 배우고 있는 내용이 있어서 기본에 배웠던 내용들을 복습하는 시간이 되었다.2일차 - 첫 HTTP API 개발 대표적으로 GET과 POST를 나타내며 데이터를 전달하는 방법이 쿼리와 Body(JSON)으로 나뉘며 자세하게 모르고 있었던 JSON을 받는 방법에 대해서 알게 되었다.예전에 배웠던 부트캠프에서 스프링을 배우다가 dto 개념을 제대로 모르는 상태에서 프로젝트에 투입이 되었는데, request 와 response 을 활용하지 못하여 주어진 소스코드를 이해하지 못해서 구조를 어떻게 활용을 해야하나 고민했었다.그리고 다양한 파라미터와 JSON을 받아서 어떻게 컨트롤러 단에서 처리를 해야하는지 전혀 감이 잡히지 않았는데 최태현 코치님이 보여주신 구체적인 예를 통해서 막연한 안개가 걷힌 느낌이 들었다.  3일차 - 기본적인 데이터베이스 사용법 MySQL에 대해서 이론적인 부분은 배운 상태이지만 우리가 실무적인 면에서 주로 사용하는 명령어들을 통해서 MySQL을 어떻게 사용해야 할지 감을 잡게 되었다.JPA를 이론적으로는 알고 있는 상황이지만 실질적인 프로젝트에 적용해본 상태는 아니다. JPA를 JdbcTemplate대신에 사용한다는 것을 알지만, 어떤 범위에 사용하는지를 몰랐고 그 기본적인 사용법을 알고나서 이후에 있는 JPA를 어떻게 적용할지 조금 두근거리긴한다.무엇보다 백엔드는 어떤 역할을 하는지(기능, 로직, DB...) 구체적으로 체험 할 수 있게 되었다.4일차 - 데이터베이스를 만드는 API 구체적으로 jdbcTemplate를 사용하는 구간이 아닌가 싶다. DB를 사용하면서, 데이터 자체가 유효한 값을 가지는지, 정당한 요청이 오지 않아 오류를 던져준다던지(예외 처리) 확인하는 구간이다.5일차 - 클린코드의 개념과 첫 리팩토링 클린코드에 대해서 많이 들었던 기억이 있다. 이론적으로만 들었기에 어떻게 적용할지 몰랐는데, Controller에 너무 많은 역할이 존재하므로 Controller - HTTP 관련 역할 담당 , Service - 분기처리, 로직 담당, Repository - DB와 접근을 담당으로 나눈 방법을 통해서 클린코드를 구체적인 방법으로 체험하는 시간이었다. 미션1일차 - 자바 어노테이션 스프링에서 현업에 사용하시는 분들의 필요에 의해서 이미 여러개의 어노테이션이 정립이 되어있는 것으로 기억한다. 하지만 그게 어떤 원리로 작성이 되었는지는 모르고 있다. 특히 원초적인 자바 어노테이션은 더더욱 알일이 없다. 일반적인 어노테이션은 눈에 익을 만큼 자주 보이지만, 일반적인 어노테이션에서 벗어나는 특별한 어노테이션이 필요할 때는 커스텀 어노테이션을 작성한다는 것을 알게 되었다. 특히 커스텀 어노테이션을 만들어 반복작업을 줄이는 노력을 할 수 있다는 것이다.다양한 답변들을 알아보기 위해서 네이버, 구글, ChatGPT를 사용하여 여러 방면으로 데이터를 얻고자 했고, 이론적인 부분만 존재하는 것보다는 최대한 개발자에게 있어 최고의 문서인 코드를 통해서 나타내는 예시들을 골라서 정리했다.2일차 - 추가적인 API 개발 쿼리 파라미터를 받아서 JSON으로 반환하는 방법을 배우고, LocalDate를 이용하여 날짜를 받아서 getDayOfWeek()을 이용하여 날짜를 나타내는 방법을 배웠다.마지막으로는 쿼리 파라미터가 아니라 JSON 바디로 받으면서 또 List를 가지고 있는 JSON을 이용하여 API를 만드는 방법에 대해서도 배우게 되었다. 힌트로 알려 주신게 컸지만 DTO에서 List를 받아 iter로 반복하여 API가 기능하게끔 반환 할 수 있다. POST MAN의 API 테스트 툴이 정말 절실하다는 것을 느끼게 되었다.3일차 - 익명 클래스와 람다식 람다식은 함수형 프로그래밍 개념을 자바에 도입하기 위해서, 코드를 더 간결하고, 읽게 쉽게 만들고, 성능이 중요시 되는 최근 병렬 처리와 이벤트 기반 프로그래밍으로 효율적으로 대응 할 수 있다.람다식과 익명 클래스의 관계는람다식은 익명 함수를 간결하게 표기, 익명 클래스는 이름이 없는 클래스 = 주로 인터페이스 구현체 생성에 사용한다.그러므로 람다식은 익명 클래스를 대체, 코드가 더 간결해지고 가독성이 향상 된다.함수형 프로그래밍, 익명클래스, 람다식, 함수형 인터페이스, 스트림 API, 메소드 레퍼런스등 저 2개의 질문에 대해서 많은 양의 검색과 정리를 통해서 답을 도출해낼 수 있었다. 도입배경과 적용 방법 등이 있지만 무엇보다 많은 숙련도를 요구하는 방법이다보니 쉽게 접근하지 못하지만 분명 열심히 단련하면 좋은 접근 방식인 것 같다. 4일차 - 추가적인 API 개발기존 API 개발에서 발전하여 JdbcTemplate를 적용하여 API를 작성하는 과제였다.다만 단순하게 API를 작성한다면 각각의 요구에 맞게 작성을 해나가면 되겠지만, 이번 과제는 모든 요구사항을 확인하여 테이블을 작성하고나서 문제를 해결해나가는 것이 도움이 되었던 것 같다. 마치 Q&A에서 기획 -> 논의 -> 개발 단계처럼 먼저 기획을 통해서 기능을 적고, 이후 API 명세서를 만들고 DB 스키마를 만들고나서, 개발 단계로 들어가 직접 코드를 타이핑 하는 과정 처럼 말이다. 5일차 - 클린 코드과제로 주어진 코드를 코딩테스트를 준비하던 과정에서 겪었던 것 처럼, 입력을 받고 기본적인 설정을 하는 구간 / 주사위를 굴리고 카운트 하는 클래스 / 주사위가 나온 횟수를 출력하는 클래스 등으로 나눠서 명확하게 나누어 읽기 쉬운 코드를 만드는게 클린 코드를 만드는 방법일 것 같다.사실 이런 과정이 어렵지는 않았는데 코딩테스트 스터디를 준비하면서 여러 언어가 모이게 되고소통의 어려움이 있었다. 좀 더 구성을 깔끔하게 나누어 클래스로 구성하고 주석을 통해서 어떤 기능을 하는지 알려주어 소통의 어려움을 해결 했던 경험이 한 몫을 했던 것 같다.  

백엔드워밍업스터디BE1기회고록

miiro

[인프런 워밍업 스터디 클럽 1기] BE 1주차 회고록

첫 번째 발자국자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]를 수강하고인프런 워밍업 클럽에 참여하여 쓰는 첫 번째 회고록입니다. 학습 내용스프링 프로젝트를 시작하는 방법과 네트워크, HTTP, API에 대한 기본적인 개념에 대해 학습하였습니다.HTTP는 데이터를 주고 받는 표준이고, 행위와 자원은 HTTP 요청을 보내기 전에 약속을 해야합니다.HTTP Method는 GET, POST, PUT, DELETE 가 있습니다. 예시로 GET는 HTTP 요청을 받는 컴퓨터에게 요청하는 행위입니다.GET 요청의 경우 /portion 이라는 요청 받는 path와 ?의 구분기호로 세부 조건인 쿼리스트링 작성합니다.GET /portion?color=red&count=2POST 요청의 경우 데이터를 저장하는 것으로 바디를 사용합니다.POST /oak/leatherDELETE는 데이터를 삭제하기 위해 쿼리스트링을 사용하고, PUT은 데이터를 수정하기 위해 바디를 사용합니다. POST API는 HTTP Body를 활용해서 데이터를 받습니다.데이터를 보낼 때는 JSON(객체표기법)을 활용합니다.key : 'value' 형태로 Java 문법 상 Map<Object, Object> 형태와 유사합니다.@PostMapping("/multiply") public int multiplyTwoNumbers(@RequestBody CalculatorMultiplyRequest request){ return request.getNumber1()* request.getNumber2(); }위의 예시의 주요 어노테이션은 아래와 같습니다.@PostMapping : HTTP Method가 POST 이고, 요청 경로인 /path인 API를 생성합니다.@RequestBody : HTTP Body로 들어오는 JSON 파라미터로 데이터를 전달하는 객체인 DTO로 바꿔줍니다. DTO에는 JSON의 key 값이 명시되어야하며, 각 속성은 key 값과 동일하게 value도 타입에 맞게 작성합니다. Database는 데이터를 구조화시켜 저장합니다. 마치 엑셀과 비슷하게 표처럼 구조화하여 저장합니다.여기서 구조화된 데이터를 조회하는 언어를 SQL 이라고 합니다.SQL문의 예시는 아래와 같습니다.// DB 생성 create database [데이터베이스 이름]; // DB 조회 show databases; // DB 삭제 drop database [데이터베이스 이름]; // DB 사용 use [데이터베이스 이름]; // TABLE 조회 show tables; // TABLE 생성 create table [table 이름] ([필드 이름] [타입] [부가 조건], [필드 이름] [타입] [부가 조건], ... primary key([필드 이름]) ); // TABLE 삭제 drop table [table 이름];테이블 자체를 생성, 삭제, 변경, 초기화 하는 것을 DDL(Data Definition Language) 라고 합니다. 테이블의 데이터를 조작하는 것을 일명 C.R.U.D 라고 부릅니다.테이블 데이터를 조작하는 SQL문을 DML(Data Manipulation Language) 라고 합니다.데이터 삽입insert into [table 이름]([필드 이름1], [필드 이름2], ...) values (값1, 값2, ...);데이터 조회select * from [db 이름]; select [필드 이름1], [필드 이름2] from [db 이름];조건 데이터 조회select * from [db 이름] where [조건];데이터 업데이트update [table 이름] set 필드1=값, 필드2=값,... where [조건];❗ 조건문을 작성하지 않으면 모든 데이터가 바뀌니 항상 주의하자!데이터 삭제delete from [table 이름] where [조건];❗ 조건문을 작성하지 않으면 모든 데이터가 삭제되니 항상 주의하자!  과제 내용Day 1HTTP 요청을 보내기 위한 Method 중 하나인 GET API 를 만들기 위해서 어노테이션을 사용했었습니다.이를 통해 어노테이션을 사용하는 이유는 무엇인지, 또한 나만의 어노테이션을 만드는 방법에 대해 학습하게 되었습니다.처음에는 클래스 위에 붙은 @ 어노테이션은 의미를 생각하기보다는 레이어에 맞는 동작을 하기 위해서 알맞는 어노테이션을 사용할 수 있도록 암기하는 것으로만 생각하고 공부했었습니다. 자바에서 제공하는 표준 어노테이션을 다양하게 찾아봤으며, 코드가 작동되면서 reflection을 이용하여 코드를 직접적으로 호출하지 않고 코드를 제어할 수 있는 다양한 기술의 집합체라는 것을 알게 되었습니다.그리고, 유저가 직접 만드는 어노테이션을 구현해보면서 메타 어노테이션 즉, 내가 만드는 어노테이션의 유지 기간, 위치를 결정할 수 있도록 결정할 수 있는 사용자 친화적인 조작을 할 수 있다는 것을 알게 되었습니다.📋 1일차 미션 : 어노테이션의 개념과 특징 Day 2GET, POST API를 활용한 과제인데 일반적으로, GET을 사용할 때는 URL 뒤에 query를 사용하는 방식, POST를 사용할 때는 body를 사용하는 방식으로 볼 수 있습니다. 하지만 부득이하게 데이터의 양이 많이 복잡하다면 쿼리 파라미터로 받는 방식(GET)보다는 body 로 받는 방식(POST)로 변경하는 방향이 좋다는 것을 알았습니다.또한, LocalDate 타입을 string 형태로 받아 치환을 해줬는데, 스프링부트 2.x.x 버전에서 @DateTimeFormat을 활용하여 localDate를 바로 받을 수 있는 방법도 알게 되어, java 문법의 변수가 아닌 스프링에 친화적인 어노테이션을 활용하여 구현할 수 있도록 많이 접해보고 공부해야겠다는 생각이 들었습니다.📋 2일차 미션 : GET API와 POST API Day 3람다식의 등장한 이유와 람다식과 익명 클래스의 관계에 대한 내용을 중점적으로 공부하는 것이었습니다.위의 내용을 공부하면서 함수형 프로그래밍과 @FunctionalInterface, stream API와 메서드 레퍼런스에 대한 내용에 대한 연관성도 함께 예시를 만들어보면서 공부했습니다. 위의 내용은 코딩테스트를 해본 사람이면 한 번 쯤은 실습해봤을 내용이라서 쉽게 내용을 이해할 수 있을 것이라고 생각했습니다.하지만 필자의 경우 문법에 대한 내용보다는 코드를 구현할 줄만 알았습니다. 해당 내용을 공부하니 왜 만들어졌는지, 자바에서는 버전을 올라가면서 메서드를 쉽게 구현할 수 있도록 점차 단순화시키고 간결하게 표현할 수 있다는 것에 대해 면밀하게 알 수 있었습니다.📋 3일차 미션 : 익명 클래스와 람다식  회고기초 지식보다는 실제 프로젝트를 구현하기 위한 기술에 대한 내용에 중점을 두고 공부를 했었는데, 백엔드 개발을 하기 위한 서버 지식과 Java, Spring에 관한 내용을 다시 처음부터 하나씩 이해하면서 다시금 지식을 쌓을 수 있었던 거 같습니다.또한, 강의만 듣는 게 아닌 과제를 해결하면서 강의에 대한 이해와 구현할 수 있는 능력을 키우면서 나 자신의 부족한 점과 다른 방식으로 구현할 수 있을 수 있을까라는 여러 방법에 대해 골똘하게 생각할 수 있는 계기가 되었던 거 같습니다.

백엔드인프런워밍업스터디클럽1주차회고록

채널톡 아이콘